diff --git a/applications/asset_tracker_v2/doc/debug_module.rst b/applications/asset_tracker_v2/doc/debug_module.rst index 3cb0581e6f1e..0e53e4966715 100644 --- a/applications/asset_tracker_v2/doc/debug_module.rst +++ b/applications/asset_tracker_v2/doc/debug_module.rst @@ -22,14 +22,7 @@ This section documents the various features implemented by the module. Memfault ======== -The debug module uses `Memfault SDK`_ to track |NCS| specific metrics such as LTE and stack metrics. -In addition, the following types of custom Memfault metrics are defined and tracked when compiling in the debug module: - - * ``gnss_time_to_fix_ms`` - Time duration between the start of a GNSS search and obtaining a fix. - * ``gnss_satellites_tracked_count`` - Number of satellites tracked during a GNSS search window. - * ``location_timeout_search_time_ms`` - Time duration between the start of a location search and a search timeout. - -The debug module also implements `Memfault SDK`_ software watchdog, which is designed to trigger an assert before an actual watchdog timeout. +The debug module uses `Memfault SDK`_ to track |NCS| specific metrics such as LTE and stack metrics. The debug module also implements `Memfault SDK`_ software watchdog, which is designed to trigger an assert before an actual watchdog timeout. This enables the application to be able to collect coredump data before a reboot occurs. To enable Memfault, you must include the :file:`../overlay-memfault.conf` when building the application. diff --git a/applications/asset_tracker_v2/overlay-memfault.conf b/applications/asset_tracker_v2/overlay-memfault.conf index 3fd47d59fc9b..5d29bc52c6ef 100644 --- a/applications/asset_tracker_v2/overlay-memfault.conf +++ b/applications/asset_tracker_v2/overlay-memfault.conf @@ -9,6 +9,7 @@ CONFIG_MEMFAULT_NCS_PROJECT_KEY="" CONFIG_MEMFAULT_NCS_DEVICE_ID_IMEI=y CONFIG_MEMFAULT_NCS_LTE_METRICS=y CONFIG_MEMFAULT_NCS_STACK_METRICS=y +CONFIG_MEMFAULT_NCS_LOCATION_METRICS=y CONFIG_MEMFAULT_LOGGING_ENABLE=y CONFIG_MEMFAULT_ROOT_CERT_STORAGE_NRF9160_MODEM=y diff --git a/applications/asset_tracker_v2/src/modules/debug_module.c b/applications/asset_tracker_v2/src/modules/debug_module.c index 7b7836b1424f..51d574f110ab 100644 --- a/applications/asset_tracker_v2/src/modules/debug_module.c +++ b/applications/asset_tracker_v2/src/modules/debug_module.c @@ -25,7 +25,6 @@ #include "events/data_module_event.h" #include "events/sensor_module_event.h" #include "events/util_module_event.h" -#include "events/location_module_event.h" #include "events/modem_module_event.h" #include "events/ui_module_event.h" #include "events/debug_module_event.h" @@ -41,7 +40,6 @@ struct debug_msg_data { struct sensor_module_event sensor; struct data_module_event data; struct app_module_event app; - struct location_module_event location; struct modem_module_event modem; } module; }; @@ -143,15 +141,6 @@ static bool app_event_handler(const struct app_event_header *aeh) message_handler(&debug_msg); } - if (is_location_module_event(aeh)) { - struct location_module_event *event = cast_location_module_event(aeh); - struct debug_msg_data debug_msg = { - .module.location = *event - }; - - message_handler(&debug_msg); - } - if (is_sensor_module_event(aeh)) { struct sensor_module_event *event = cast_sensor_module_event(aeh); @@ -257,38 +246,6 @@ static void send_memfault_data(void) } } -static void add_location_metrics(uint8_t satellites, uint32_t search_time, - enum location_module_event_type event) -{ - int err; - - switch (event) { - case LOCATION_MODULE_EVT_GNSS_DATA_READY: - err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_time_to_fix_ms, search_time); - if (err) { - LOG_ERR("Failed updating gnss_time_to_fix_ms metric, error: %d", err); - } - break; - case LOCATION_MODULE_EVT_TIMEOUT: - err = MEMFAULT_METRIC_SET_UNSIGNED(location_timeout_search_time_ms, search_time); - if (err) { - LOG_ERR("Failed updating location_timeout_search_time_ms metric, error: %d", - err); - } - break; - default: - LOG_ERR("Unknown location module event."); - return; - } - - err = MEMFAULT_METRIC_SET_UNSIGNED(gnss_satellites_tracked_count, satellites); - if (err) { - LOG_ERR("Failed updating gnss_satellites_tracked_count metric, error: %d", err); - } - - memfault_metrics_heartbeat_debug_trigger(); -} - static void memfault_handle_event(struct debug_msg_data *msg) { if (IS_EVENT(msg, app, APP_EVT_START)) { @@ -349,14 +306,6 @@ static void memfault_handle_event(struct debug_msg_data *msg) send_memfault_data(); return; } - - if ((IS_EVENT(msg, location, LOCATION_MODULE_EVT_TIMEOUT)) || - (IS_EVENT(msg, location, LOCATION_MODULE_EVT_GNSS_DATA_READY))) { - add_location_metrics(msg->module.location.data.location.satellites_tracked, - msg->module.location.data.location.search_time, - msg->module.location.type); - return; - } } #endif /* defined(CONFIG_MEMFAULT) */ @@ -388,7 +337,6 @@ APP_EVENT_LISTENER(MODULE, app_event_handler); APP_EVENT_SUBSCRIBE_EARLY(MODULE, app_module_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, modem_module_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, cloud_module_event); -APP_EVENT_SUBSCRIBE_EARLY(MODULE, location_module_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, ui_module_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, sensor_module_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, data_module_event); diff --git a/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c b/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c index f3afcee45763..9f9d66403dec 100644 --- a/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c +++ b/applications/asset_tracker_v2/tests/debug_module/src/debug_module_test.c @@ -18,7 +18,6 @@ #include "cmock_watchdog_app.h" #include "app_module_event.h" -#include "location_module_event.h" #include "debug_module_event.h" #include "data_module_event.h" @@ -29,7 +28,6 @@ extern struct event_listener __event_listener_debug_module; */ static struct app_module_event app_module_event_memory; static struct data_module_event data_module_event_memory; -static struct location_module_event location_module_event_memory; static struct debug_module_event debug_module_event_memory; #define DEBUG_MODULE_EVT_HANDLER(aeh) __event_listener_debug_module.notification(aeh) @@ -38,7 +36,6 @@ static struct debug_module_event debug_module_event_memory; * depend on these to exist. But since we are unit testing, we dont need * these subscriptions and hence these structs can remain uninitialized. */ -struct event_type __event_type_location_module_event; struct event_type __event_type_debug_module_event; struct event_type __event_type_app_module_event; struct event_type __event_type_data_module_event; @@ -108,62 +105,6 @@ void setup_debug_module_in_init_state(void) app_event_manager_free(app_module_event); } -/* Test whether the correct Memfault metrics are set upon a GNSS fix. */ -void test_memfault_trigger_metric_sampling_on_gnss_fix(void) -{ - setup_debug_module_in_init_state(); - - __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(gnss_time_to_fix_ms), 60000, 0); - __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count), - 4, - 0); - __cmock_memfault_metrics_heartbeat_debug_trigger_Expect(); - - __cmock_app_event_manager_alloc_ExpectAnyArgsAndReturn(&location_module_event_memory); - __cmock_app_event_manager_free_ExpectAnyArgs(); - struct location_module_event *location_module_event = new_location_module_event(); - - location_module_event->type = LOCATION_MODULE_EVT_GNSS_DATA_READY; - location_module_event->data.location.satellites_tracked = 4; - location_module_event->data.location.search_time = 60000; - - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - app_event_manager_free(location_module_event); -} - -/* Test whether the correct Memfault metrics are set upon a GNSS timeout. */ -void test_memfault_trigger_metric_sampling_on_location_timeout(void) -{ - resetTest(); - setup_debug_module_in_init_state(); - - /* Update this function to expect the search time and number of satellites. */ - __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(location_timeout_search_time_ms), - 30000, - 0); - __cmock_memfault_metrics_heartbeat_set_unsigned_ExpectAndReturn( - MEMFAULT_METRICS_KEY(gnss_satellites_tracked_count), - 2, - 0); - __cmock_memfault_metrics_heartbeat_debug_trigger_Ignore(); - - __cmock_app_event_manager_alloc_ExpectAnyArgsAndReturn(&location_module_event_memory); - __cmock_app_event_manager_free_ExpectAnyArgs(); - struct location_module_event *location_module_event = new_location_module_event(); - - location_module_event->type = LOCATION_MODULE_EVT_TIMEOUT; - location_module_event->data.location.satellites_tracked = 2; - location_module_event->data.location.search_time = 30000; - - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - app_event_manager_free(location_module_event); -} - /* Test that the debug module is able to submit Memfault data externally through events * of type DEBUG_EVT_MEMFAULT_DATA_READY carrying chunks of data. */ @@ -198,42 +139,6 @@ void test_memfault_trigger_data_send(void) k_sleep(K_SECONDS(1)); } -/* Test that no Memfault SDK specific APIs are called on GNSS module events - * that should not be handled. - */ -void test_memfault_unhandled_event(void) -{ - resetTest(); - setup_debug_module_in_init_state(); - - /* Expect no memfault APIs to be called on LOCATION_MODULE_EVT_ACTIVE */ - - __cmock_app_event_manager_alloc_ExpectAnyArgsAndReturn(&location_module_event_memory); - __cmock_app_event_manager_free_ExpectAnyArgs(); - struct location_module_event *location_module_event = new_location_module_event(); - - location_module_event->type = LOCATION_MODULE_EVT_ACTIVE; - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - - location_module_event->type = LOCATION_MODULE_EVT_INACTIVE; - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - - location_module_event->type = LOCATION_MODULE_EVT_SHUTDOWN_READY; - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - - location_module_event->type = LOCATION_MODULE_EVT_AGNSS_NEEDED; - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - - location_module_event->type = LOCATION_MODULE_EVT_ERROR_CODE; - TEST_ASSERT_EQUAL(0, DEBUG_MODULE_EVT_HANDLER( - (struct app_event_header *)location_module_event)); - app_event_manager_free(location_module_event); -} - /* Test whether the correct Memfault software watchdog APIs are called on callbacks from the * application watchdog library. */ diff --git a/doc/nrf/libraries/debug/memfault_ncs.rst b/doc/nrf/libraries/debug/memfault_ncs.rst index 025e7d1f3d90..fd6c6a533e8f 100644 --- a/doc/nrf/libraries/debug/memfault_ncs.rst +++ b/doc/nrf/libraries/debug/memfault_ncs.rst @@ -97,6 +97,7 @@ The Kconfig options for Memfault that are defined in |NCS| provide some addition * :kconfig:option:`CONFIG_MEMFAULT_NCS_PROVISION_CERTIFICATES` * :kconfig:option:`CONFIG_MEMFAULT_NCS_INTERNAL_FLASH_BACKED_COREDUMP` * :kconfig:option:`CONFIG_MEMFAULT_NCS_LTE_METRICS` +* :kconfig:option:`CONFIG_MEMFAULT_NCS_LOCATION_METRICS=y` * :kconfig:option:`CONFIG_MEMFAULT_NCS_STACK_METRICS` * :kconfig:option:`CONFIG_MEMFAULT_NCS_BT_METRICS` diff --git a/modules/memfault-firmware-sdk/CMakeLists.txt b/modules/memfault-firmware-sdk/CMakeLists.txt index 4a9ffd4dfac6..b0d972ef529a 100644 --- a/modules/memfault-firmware-sdk/CMakeLists.txt +++ b/modules/memfault-firmware-sdk/CMakeLists.txt @@ -22,6 +22,11 @@ zephyr_library_sources_ifdef( memfault_lte_metrics.c ) +zephyr_library_sources_ifdef( + CONFIG_MEMFAULT_NCS_LOCATION_METRICS + memfault_location_metrics.c +) + zephyr_library_sources_ifdef( CONFIG_MEMFAULT_NCS_BT_METRICS memfault_bt_metrics.c) diff --git a/modules/memfault-firmware-sdk/Kconfig b/modules/memfault-firmware-sdk/Kconfig index 7056b99bfe43..5012789f581d 100644 --- a/modules/memfault-firmware-sdk/Kconfig +++ b/modules/memfault-firmware-sdk/Kconfig @@ -164,10 +164,17 @@ config MEMFAULT_NCS_BT_METRICS help Collect metrics related to the Bluetooth stack in background while application is running. +config MEMFAULT_NCS_LOCATION_METRICS + bool "Collect location metrics" + depends on LOCATION + depends on LOCATION_DATA_DETAILS + help + Collect metrics related to location fixes while the application is running. + config MEMFAULT_NCS_USE_DEFAULT_METRICS bool select MEMFAULT_METRICS_EXTRA_DEFS_FILE - default y if (MEMFAULT_NCS_STACK_METRICS || MEMFAULT_NCS_LTE_METRICS || MEMFAULT_NCS_BT_METRICS) + default y if (MEMFAULT_NCS_STACK_METRICS || MEMFAULT_NCS_LTE_METRICS || MEMFAULT_NCS_BT_METRICS || MEMFAULT_NCS_LOCATION_METRICS) config MEMFAULT_NCS_IMPLEMENT_METRICS_COLLECTION bool "Implement metrics collection" diff --git a/modules/memfault-firmware-sdk/config/memfault_metrics_heartbeat_extra.def b/modules/memfault-firmware-sdk/config/memfault_metrics_heartbeat_extra.def index 62c2d357d31a..85322e5e29c7 100644 --- a/modules/memfault-firmware-sdk/config/memfault_metrics_heartbeat_extra.def +++ b/modules/memfault-firmware-sdk/config/memfault_metrics_heartbeat_extra.def @@ -38,3 +38,48 @@ MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_connection_time_ms, kMemfaultMetricType_Timer MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_connection_count, kMemfaultMetricType_Unsigned) MEMFAULT_METRICS_KEY_DEFINE(ncs_bt_bond_count, kMemfaultMetricType_Unsigned) #endif /* CONFIG_MEMFAULT_NCS_BT_METRICS */ + +#ifdef CONFIG_MEMFAULT_NCS_LOCATION_METRICS + +// Heartbeat metrics +MEMFAULT_METRICS_KEY_DEFINE(ncs_loc_search_request_count, kMemfaultMetricType_Unsigned) + +// Session metrics +MEMFAULT_METRICS_SESSION_KEY_DEFINE(ncs_loc) + +// Successful search metrics +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_search_success, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_search_time_ms, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_accuracy_cm, kMemfaultMetricType_Unsigned, ncs_loc) + +// Failed search metrics +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_search_failure, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_search_timeout_ms, kMemfaultMetricType_Unsigned, ncs_loc) + +// Method-specific metrics (GNSS, Cellular, WiFi) +// - All reported in both successful and failed searches unless noted +// - *_method_result metric values map to the location_event_id enumeration in nrf/include/modem/location.h + +// GNSS +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_gnss_on_time_ms, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_gnss_satellites_tracked_count, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_gnss_satellites_used_count, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_gnss_method_result, kMemfaultMetricType_Unsigned, ncs_loc) + +// Only reported in successful session +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_gnss_time_to_fix_ms, kMemfaultMetricType_Unsigned, ncs_loc) + +// Cellular +#if defined(CONFIG_LOCATION_METHOD_CELLULAR) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_lte_neighbor_cells_count, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_lte_gci_cells_count, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_lte_method_result, kMemfaultMetricType_Unsigned, ncs_loc) +#endif /* CONFIG_LOCATION_METHOD_CELLULAR */ + +// WiFi +#if defined(CONFIG_LOCATION_METHOD_WIFI) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_wifi_ap_count, kMemfaultMetricType_Unsigned, ncs_loc) +MEMFAULT_METRICS_KEY_DEFINE_WITH_SESSION(ncs_loc_wifi_method_result, kMemfaultMetricType_Unsigned, ncs_loc) +#endif /* CONFIG_LOCATION_METHOD_WIFI */ + +#endif /* CONFIG_MEMFAULT_NCS_LOCATION_METRICS */ diff --git a/modules/memfault-firmware-sdk/include/memfault_location_metrics.h b/modules/memfault-firmware-sdk/include/memfault_location_metrics.h new file mode 100644 index 000000000000..0482acf31a8f --- /dev/null +++ b/modules/memfault-firmware-sdk/include/memfault_location_metrics.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef MEMFAULT_LOCATION_METRICS_H_ +#define MEMFAULT_LOCATION_METRICS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Initialize default location metrics. */ +void memfault_location_metrics_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MEMFAULT_LOCATION_METRICS_H_ */ diff --git a/modules/memfault-firmware-sdk/memfault_location_metrics.c b/modules/memfault-firmware-sdk/memfault_location_metrics.c new file mode 100644 index 000000000000..be4fe57a6100 --- /dev/null +++ b/modules/memfault-firmware-sdk/memfault_location_metrics.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include + +#include "memfault/metrics/metrics.h" +#include "memfault_location_metrics.h" + +LOG_MODULE_DECLARE(memfault_ncs_metrics, CONFIG_MEMFAULT_NCS_LOG_LEVEL); + +static bool session_in_progress = false; + +static void memfault_location_method_to_string(char *buf, size_t buf_len, + enum location_method method) +{ + switch (method) { + case LOCATION_METHOD_CELLULAR: + snprintk(buf, buf_len, "Cellular"); + break; + case LOCATION_METHOD_GNSS: + snprintk(buf, buf_len, "GNSS"); + break; + case LOCATION_METHOD_WIFI: + snprintk(buf, buf_len, "Wi-Fi"); + break; + default: + snprintk(buf, buf_len, "Unknown"); + break; + } +} + +static void memfault_location_method_results_record(const enum location_method method, + const enum location_event_id id, + const struct location_data_details details, + const float *accuracy) +{ + if (method == LOCATION_METHOD_GNSS) { + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_gnss_method_result, id); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_gnss_on_time_ms, + details.gnss.elapsed_time_gnss); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_gnss_satellites_tracked_count, + details.gnss.satellites_tracked); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_gnss_satellites_used_count, + details.gnss.satellites_used); + + // Only record TTF and accuracy when a fix is acquired + if (id == LOCATION_EVT_LOCATION) { + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_gnss_time_to_fix_ms, + details.gnss.pvt_data.execution_time); + + if (accuracy != NULL) { + uint32_t accuracy_cm = (uint32_t)(*accuracy * 100.0f); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_accuracy_cm, accuracy_cm); + } + } + } +#if defined(CONFIG_LOCATION_METHOD_CELLULAR) + else if (method == LOCATION_METHOD_CELLULAR) { + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_lte_method_result, id); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_lte_neighbor_cells_count, + details.cellular.ncells_count); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_lte_gci_cells_count, + details.cellular.gci_cells_count); + } +#endif +#if defined(CONFIG_LOCATION_METHOD_WIFI) + else if (method == LOCATION_METHOD_WIFI) { + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_wifi_method_result, id); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_wifi_access_points_count, + details.wifi.ap_count); + } +#endif +} + +static void memfault_location_method_fallback_record(const enum location_method method, + struct location_data_fallback fallback) +{ + memfault_location_method_results_record(method, fallback.cause, fallback.details, NULL); + + // Log the results + char method_str[16]; + memfault_location_method_to_string(method_str, sizeof(method_str), method); + LOG_DBG("%s method attempted", method_str); + char fallback_method_str[16]; + memfault_location_method_to_string(fallback_method_str, sizeof(fallback_method_str), + fallback.next_method); + LOG_DBG("Falling back to %s method", fallback_method_str); +} + +/** + * @brief Start a location session. + * + */ +static void memfault_location_metrics_start_fix_session(void) +{ + if (session_in_progress) { + return; + } + + session_in_progress = true; + LOG_DBG("Starting location session"); + MEMFAULT_METRICS_SESSION_START(ncs_loc); + MEMFAULT_METRIC_ADD(ncs_loc_search_request_count, 1); +} + +/** + * @brief Stop a location fix session. + * + * @param event_data pointer to location event data + */ +static void memfault_location_metrics_stop_fix_session(const struct location_event_data *event_data) +{ + if (!session_in_progress) { + return; + } + + uint32_t session_time_ms; + memfault_metrics_heartbeat_timer_read( + MEMFAULT_METRICS_KEY(MEMFAULT_METRICS_SESSION_TIMER_NAME(ncs_loc)), + &session_time_ms); + + switch (event_data->id) { + case LOCATION_EVT_LOCATION: + LOG_DBG("Stopping location session, fix data acquired"); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_search_time_ms, + event_data->location.details.elapsed_time_method); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_search_success, 1); + + memfault_location_method_results_record(event_data->method, event_data->id, + event_data->location.details, + &event_data->location.accuracy); + + break; + case LOCATION_EVT_TIMEOUT: + LOG_DBG("Timeout recorded"); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_search_timeout_ms, + event_data->error.details.elapsed_time_method); + // Intentional fall through + case LOCATION_EVT_ERROR: + // Intentional fall through + case LOCATION_EVT_RESULT_UNKNOWN: + // Intentional fall through + default: + LOG_DBG("Stopping location session, no fix found, id=%d", event_data->id); + MEMFAULT_METRIC_SET_UNSIGNED(ncs_loc_search_failure, 1); + memfault_location_method_results_record(event_data->method, event_data->id, + event_data->location.details, NULL); + break; + } + + MEMFAULT_METRICS_SESSION_END(ncs_loc); + session_in_progress = false; +} + +static void memfault_location_event_handler(const struct location_event_data *event_data) +{ + if (event_data->id == LOCATION_EVT_STARTED) { + memfault_location_metrics_start_fix_session(); + } else if (event_data->id == LOCATION_EVT_FALLBACK) { + memfault_location_method_fallback_record(event_data->method, event_data->fallback); + } else if (event_data->id == LOCATION_EVT_LOCATION || + event_data->id == LOCATION_EVT_TIMEOUT || event_data->id == LOCATION_EVT_ERROR || + event_data->id == LOCATION_EVT_RESULT_UNKNOWN) { + memfault_location_metrics_stop_fix_session(event_data); + } +} + +void memfault_location_metrics_init(void) +{ + int result = location_handler_register(memfault_location_event_handler); + if (result != 0) { + LOG_DBG("Error registering location handler, err %d", result); + } +} diff --git a/modules/memfault-firmware-sdk/memfault_ncs_metrics.c b/modules/memfault-firmware-sdk/memfault_ncs_metrics.c index 2b144c1577b0..96acbe832014 100644 --- a/modules/memfault-firmware-sdk/memfault_ncs_metrics.c +++ b/modules/memfault-firmware-sdk/memfault_ncs_metrics.c @@ -19,6 +19,7 @@ LOG_MODULE_REGISTER(memfault_ncs_metrics, CONFIG_MEMFAULT_NCS_LOG_LEVEL); #include "memfault_ncs_metrics.h" #include "memfault_lte_metrics.h" #include "memfault_bt_metrics.h" +#include "memfault_location_metrics.h" #define HEX_NAME_LENGTH 11 @@ -127,4 +128,8 @@ void memfault_ncs_metrics_init(void) if (IS_ENABLED(CONFIG_MEMFAULT_NCS_BT_METRICS)) { memfault_bt_metrics_init(); } + + if (IS_ENABLED(CONFIG_MEMFAULT_NCS_LOCATION_METRICS)) { + memfault_location_metrics_init(); + } }