Logging with Zephyr

Enable log collection on devices running Zephyr RTOS and analyze ingested log messages.

This guide explains how to enable log collection on devices running Zephyr RTOS using the Spotflow device module and analyze logs in the Spotflow web application.

Install Spotflow Device Module

As the very first step, check one of the following basic integration guides:

Use Zephyr logging macros

After installing the Spotflow device module and enabling logging via Kconfig configuration, you can use standard Zephyr logging macros to send the logs:

src/main.c
#include <zephyr/logging/log.h>

// Register the logging module
LOG_MODULE_REGISTER(main);

void main(void)
{
    // Ensure the device has an active internet connection.

    LOG_INF("Device has booted up successfully.");

    for (int i = 1; i <= 5; i++) {
        int reading = i * 10;
        LOG_INF("Sensor reading %d: %d units", i, reading);
        if (reading > 30) LOG_WRN("Reading is above normal. Value: %d.", reading);
    }

    LOG_INF("Device shutting down.");
}

Analyze Logs in the Web Application

Once your device is integrated and sending logs, you can analyze them in the web application. The main entry point is the Events page, which gives you a comprehensive view of all events collected from your devices. There, you can filter logs by their content, device ID, severity, and other metadata.

Spotflow Web Application Screenshot
The Events page displays all logs with filtering and search capabilities.

You can click on individual log messages to see their details, and it is possible to drill down into specific events by matching their metadata.

Detail a single log message.
It is possible to query logs based on metadata of a particular log message.

How the Device Module Works

The Spotflow device module integrates with Zephyr's native logging subsystem to provide a familiar development experience. Instead of replacing your existing logging workflow, it extends it by implementing a custom logging backend that captures logs from standard Zephyr macros and transmits them to Spotflow.

Diagram of the device module architecture for logging.

Key benefits of this architecture:

  • Zero code changes: Continue using LOG_DBG(), LOG_INF(), LOG_WRN(), and LOG_ERR() macros as before.
  • Local debugging: Our device module can run alongside other logging backends, allowing you to see logs in your local console while also transmitting them to Spotflow.

These logs will be consumed by Spotflow and your existing logging backends (such as the built-in UART backend from Zephyr), with no additional code required.

Handling Network Interruptions

The device module is designed to handle network interruptions gracefully. When the connection is unavailable, logs are stored in a circular buffer. That is, when the buffer is full, the oldest logs are overwritten with the new ones. Once the connection is restored, buffered logs are automatically sent to Spotflow.

Support for Constrained Devices

To minimize the memory footprint, the device module exposes number of configuration options to tune the buffer size and other parameters. See the available Kconfig options below.

Reliability of data delivery

Spotflow is using MQTT as the underlying transport protocol for log ingestion.

Most embedded devices running Zephyr are significantly resource-constrained which has several implications:

  1. To minimize the footprint of the Spotflow device module, MQTT QoS level 0 is used which has minimal overhead but at the cost of weaker delivery guarantees. Although MQTT itself is TCP-based protocol and TCP guarantees transport-level delivery, with QoS 0, some messages still can be lost in case of client or broker failures and similar issues. This should not be an issue for most observability use-cases.

  2. In case of a network interruption or slow down, the device module buffers not yet sent logs in a circular buffer. However, this buffer has limited size and once it is full, the oldest logs are overwritten with the new ones. Size of this buffer can be via Kconfig options.

If needed, you can create your custom integration directly with our MQTT broker to tailor the solution to your specific resource constraints vs. reliability tradeoff. Spotflow MQTT broker supports all QoS levels from 0 to 2 and is designed to handle even high throughput log streams.

If these trade-offs are not acceptable for your use-case, please open a Feature request or let us know via email hello@spotflow.io or our Discord. We will be happy to work with you to incorporate necessary changes to the platform or find other suitable solution.

Kconfig options

prj.conf
CONFIG_SPOTFLOW_LOG_BACKEND=y

To explicity enable or disable Spotflow logging backend (e.g. in cases when only crash reports are required), use SPOTFLOW_LOG_BACKEND. It is enabled by default.

prj.conf
SPOTFLOW_LOGS_PROCESSING_LOG_LEVEL=3

To configure logging level for the Spotflow backend code, use SPOTFLOW_LOGS_PROCESSING_LOG_LEVEL option with one of the following values:

  • 0 = OFF, do not write.
  • 1 = ERROR, only write LOG_ERR.
  • 2 = WARNING, write LOG_WRN and lower.
  • 3 = INFO, write LOG_INF and lower.
  • 4 = DEBUG, write LOG_DBG and lower.

By default, INFO is used.

prj.conf
CONFIG_SPOTFLOW_LOG_BACKEND_QUEUE_SIZE=64
CONFIG_SPOTFLOW_LOG_BUFFER_SIZE=512
CONFIG_SPOTFLOW_CBOR_LOG_MAX_LEN=1024
CONFIG_HEAP_MEM_POOL_ADD_SIZE_SPOTFLOW=6144

You can configure these options to adjust performance and resource usage.

See KConfig for logging for details about all options above.

See Advanced configuration options for Zephyr for additional options not directly related to logging.

Learn more

How is this guide?