Migrate nRF Cloud Alerts to Memfault Trace Events
This guide covers migrating nRF Cloud SDK Alerts (nrf_cloud_alert_send())
to Memfault Trace Events. These are unrelated to
Memfault's platform Alerts, which trigger notifications
based on Fleet-wide Metric thresholds.
Migrating from nRF Cloud Alerts to Memfault Trace Events enhances the monitored data from simple application-level signaling, to detailed code-level execution tracking.
Both systems enable devices to report critical issues without halting or rebooting, but Memfault automatically captures the call site, deduplicates recurring errors into Issues, and operates independently of the nRF Cloud transport.
Conceptual Comparison
nRF Cloud Alerts signal predefined application conditions - low battery,
temperature threshold, Device online/offline. A call to nrf_cloud_alert_send()
transmits a compact JSON payload containing a type enum, a float value, an
optional description string, and a timestamp. Each alert is independent: there
is no deduplication or grouping, and alerts are stored in the nRF Cloud portal
for 30 days.
Memfault Trace Events track recoverable errors. In addition to a user-defined reason code, each event automatically captures the Program Counter (PC) and Link Register (LR) at the call site - enough for Memfault to decode the exact source file, function name, and line number for the topmost two stack frames. Similar events are deduplicated and grouped into Issues, and data persists indefinitely.
| nRF Cloud Alerts | Memfault Trace Events | |
|---|---|---|
| Primary purpose | Application condition signaling | Recoverable error tracking |
| Data captured | Type enum + float value + string | Reason code + PC + LR (+ optional status or log) |
| Call-site context | None | Top 2 stack frames decoded to source |
| Issue grouping | None | Automatic by reason + backtrace |
| ISR-safe | No | Yes |
| Retention | 30 days in nRF Cloud portal | Persistent Issues in Memfault |
| Transport dependency | MQTT, CoAP, or REST (selected at build time) | Independent of transport |
Migration Steps
Prerequisite Complete the Nordic nRF Connect SDK integration before following this guide.
1. Define your Trace reasons
nRF Cloud Alert types come from the built-in nrf_cloud_alert_type enum or from
application-defined integers above ALERT_TYPE_CUSTOM = 100. Replace each one
with an entry in memfault_trace_reason_user_config.def (see
Trace Events):
// memfault_trace_reason_user_config.def
MEMFAULT_TRACE_REASON_DEFINE(device_online)
MEMFAULT_TRACE_REASON_DEFINE(device_offline)
MEMFAULT_TRACE_REASON_DEFINE(low_battery)
MEMFAULT_TRACE_REASON_DEFINE(high_temperature)
MEMFAULT_TRACE_REASON_DEFINE(high_humidity)
MEMFAULT_TRACE_REASON_DEFINE(shock_detected)
For how reason names are rendered in the Memfault UI, see Trace Events - UI Rendering.
2. Replace alert calls with Trace macros
Before - nRF Cloud uses a dedicated function per transport:
#include <net/nrf_cloud_alert.h>
// MQTT or CoAP transport
nrf_cloud_alert_send(ALERT_TYPE_BATTERY, battery_volts, "Low battery");
// REST transport (separate function, requires context and device ID)
nrf_cloud_rest_alert_send(&rest_ctx, device_id,
ALERT_TYPE_BATTERY, battery_volts, "Low battery");
After - Memfault uses a single macro regardless of transport:
#include <memfault/core/trace_event.h>
// Captures PC + LR automatically - no struct to populate
MEMFAULT_TRACE_EVENT(low_battery);
// Include the numeric value (replaces the float value field)
MEMFAULT_TRACE_EVENT_WITH_STATUS(low_battery, battery_mv);
// Include a log string (replaces the description field)
MEMFAULT_TRACE_EVENT_WITH_LOG(low_battery, "Battery: %.2fV", battery_volts);
For details on how events are grouped and when to prefer each variant, see Trace Events - Trace Event Variants.
3. Configure timestamps
Both systems use the Date-Time library for timestamps when it is enabled in your application - there is no trade-off here. If Date-Time is not enabled, nRF Cloud falls back to a sequence number, while Memfault timestamps events at upload time (which works well for frequently-connected devices). Memfault also supports alternate on-device time sources such as a hardware RTC. A single Kconfig option selects the source:
# nRF91 Series (uses the Nordic Date-Time library)
CONFIG_MEMFAULT_SYSTEM_TIME_SOURCE_DATETIME=y
# Zephyr projects with a hardware RTC
CONFIG_MEMFAULT_SYSTEM_TIME_SOURCE_RTC=y
Full details: Event Timestamps.
Syntax Mapping
| nRF Cloud Alert Type | Suggested Trace Reason | Recommended Macro |
|---|---|---|
ALERT_TYPE_DEVICE_NOW_ONLINE | device_online | MEMFAULT_TRACE_EVENT(device_online) |
ALERT_TYPE_DEVICE_NOW_ONLINE_WDT | device_online_after_wdt | MEMFAULT_TRACE_EVENT(device_online_after_wdt) |
ALERT_TYPE_DEVICE_GOING_OFFLINE | device_offline | MEMFAULT_TRACE_EVENT(device_offline) |
ALERT_TYPE_MSG | app_message | MEMFAULT_TRACE_EVENT_WITH_LOG(app_message, "%s", desc) |
ALERT_TYPE_TEMPERATURE | high_temperature | MEMFAULT_TRACE_EVENT_WITH_STATUS(high_temperature, temp_c) |
ALERT_TYPE_HUMIDITY | high_humidity | MEMFAULT_TRACE_EVENT_WITH_STATUS(high_humidity, humidity_pct) |
ALERT_TYPE_BATTERY | low_battery | MEMFAULT_TRACE_EVENT_WITH_STATUS(low_battery, battery_mv) |
ALERT_TYPE_SHOCK | shock_detected | MEMFAULT_TRACE_EVENT_WITH_STATUS(shock_detected, accel_ms2) |
ALERT_TYPE_CUSTOM + N | (define your own) | MEMFAULT_TRACE_EVENT(your_custom_reason) |
Complete Before/After Example
// BEFORE: nRF Cloud Alert
#include <net/nrf_cloud_alert.h>
void battery_monitor_check(float voltage_v)
{
if (voltage_v < BATTERY_LOW_THRESHOLD_V) {
nrf_cloud_alert_send(ALERT_TYPE_BATTERY, voltage_v, "Low battery");
}
}
// AFTER: Memfault Trace Event
#include <memfault/core/trace_event.h>
// In memfault_trace_reason_user_config.def:
// MEMFAULT_TRACE_REASON_DEFINE(low_battery)
void battery_monitor_check(int voltage_mv)
{
if (voltage_mv < BATTERY_LOW_THRESHOLD_MV) {
MEMFAULT_TRACE_EVENT_WITH_STATUS(low_battery, voltage_mv);
}
}