When debugging an issue, it is often useful to inspect what the system was doing in the time leading up to the problem.
On embedded systems it's also desirable to buffer recent logs in RAM and periodically flush the logs out to a slower medium (i.e UART, Flash). This way logging does not impact any real time behavior of the system.
The Memfault SDK offers a simple RAM based logging buffer which can be used to accomplish both!
Any logs present in the buffer get automatically decoded when a coredump is uploaded:
Logs can also be uploaded independently, without being part of a coredump. These logs will appear on the Timeline of a Device. A tabular view of log files is also available under the Log Files tab:
In this guide we will walk through how to save logs using the Memfault core log utility and how the module can be used to queue up logs to flush out to a slower storage medium.
First you will need to allocate some space for the RAM backed log storage. Any size works but at least a couple hundred bytes is recommended so at least a few logs can be stored at any given time.
If your project does not have any logging infrastructure yet, you can make use of the implementation in the SDK directly:
Otherwise, you can wrap a preexisting implementation with a call to
The Memfault logging system can optionally be used as a general purpose location to store logs you plan to save to flash or flush out over UART.
In the example above this would mean removing the direct calls to
your_platform_log_error(__VA_ARGS__) and leaving the call to
Then as part of a RTOS task or bare-metal while loop you need to check if there are any logs available to flush:
Note that anytime
MEMFAULT_LOG_SAVE is called,
memfault_log_handle_saved_callback() is invoked by the memfault log module.
You can use this callback to programmatically schedule log flush events when new
logs have been generated by adding the following:
If the RAM buffer fills, the oldest logs will be overwritten. Any time this
happens when you next call
memfault_log_read(), a log such as "... 5 messages
dropped ...", will be emitted indicating how many messages were dropped.
If you are using an RTOS where tasks do not run to completion, you need to
Note that locks are only held while copying data into the backing circular buffers so the durations the lock is held will always be very short.
By design, logs are not collected and uploaded automatically. To trigger
collection of logs, your code will need to call the
memfault_log_trigger_collection() API. This API "freezes" the current contents
of the log buffer, marking those logs as pending upload to Memfault. We
recommend using this API to capture additional information when significant
events or unexpected errors take place in your platform.
Pending logs get uploaded just like any other type of data, through the data packetizer.
This step assumes you have integrated coredump collection in your project.
If you are already collecting all of your
bss RAM region in a coredump, logs
will automatically be recovered and displayed in the Memfault UI alongside a
crash and you can skip this step.
If you are only collecting select RAM regions, collection of the regions needed to decode logs can be automatically collected by adding the following to your memfault_platform_config.h.
You'll also want to double check that you have a sufficient amount of space to
store the region in your coredump storage. This can be achieved by performing
the following check after you have called