1.. _logging_api:
2
3Logging
4#######
5
6.. contents::
7    :local:
8    :depth: 2
9
10The logging API provides a common interface to process messages issued by
11developers. Messages are passed through a frontend and are then
12processed by active backends.
13Custom frontend and backends can be used if needed.
14
15Summary of the logging features:
16
17- Deferred logging reduces the time needed to log a message by shifting time
18  consuming operations to a known context instead of processing and sending
19  the log message when called.
20- Multiple backends supported (up to 9 backends).
21- Custom frontend support. It can work together with backends.
22- Compile time filtering on module level.
23- Run time filtering independent for each backend.
24- Additional run time filtering on module instance level.
25- Timestamping with user provided function. Timestamp can have 32 or 64 bits.
26- Dedicated API for dumping data.
27- Dedicated API for handling transient strings.
28- Panic support - in panic mode logging switches to blocking, synchronous
29  processing.
30- Printk support - printk message can be redirected to the logging.
31- Design ready for multi-domain/multi-processor system.
32- Support for logging floating point variables and long long arguments.
33- Built-in copying of transient strings used as arguments.
34- Support for multi-domain logging.
35- Rate-limited logging macros to prevent log flooding when messages are generated frequently.
36
37Logging API is highly configurable at compile time as well as at run time. Using
38Kconfig options (see :ref:`logging_kconfig`) logs can be gradually removed from
39compilation to reduce image size and execution time when logs are not needed.
40During compilation logs can be filtered out on module basis and severity level.
41
42Logs can also be compiled in but filtered on run time using dedicate API. Run
43time filtering is independent for each backend and each source of log messages.
44Source of log messages can be a module or specific instance of the module.
45
46There are four severity levels available in the system: error, warning, info
47and debug. For each severity level the logging API (:zephyr_file:`include/zephyr/logging/log.h`)
48has set of dedicated macros. Logger API also has macros for logging data.
49
50For each level the following set of macros are available:
51
52- ``LOG_X`` for standard printf-like messages, e.g. :c:macro:`LOG_ERR`.
53- ``LOG_HEXDUMP_X`` for dumping data, e.g. :c:macro:`LOG_HEXDUMP_WRN`.
54- ``LOG_INST_X`` for standard printf-like message associated with the
55  particular instance, e.g. :c:macro:`LOG_INST_INF`.
56- ``LOG_INST_HEXDUMP_X`` for dumping data associated with the particular
57  instance, e.g. :c:macro:`LOG_INST_HEXDUMP_DBG`
58
59The warning level also exposes the following additional macro:
60
61- :c:macro:`LOG_WRN_ONCE` for warnings where only the first occurrence is of interest.
62
63Rate-limited logging macros are also available for all severity levels to prevent log flooding:
64
65- ``LOG_X_RATELIMIT`` for rate-limited standard printf-like messages using default rate, e.g. :c:macro:`LOG_ERR_RATELIMIT`.
66- ``LOG_X_RATELIMIT_RATE`` for rate-limited standard printf-like messages with custom rate, e.g. :c:macro:`LOG_ERR_RATELIMIT_RATE`.
67- ``LOG_HEXDUMP_X_RATELIMIT`` for rate-limited data dumping using default rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT`.
68- ``LOG_HEXDUMP_X_RATELIMIT_RATE`` for rate-limited data dumping with custom rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE`.
69
70The convenience macros use the default rate specified by ``CONFIG_LOG_RATELIMIT_INTERVAL_MS``,
71while the explicit rate macros take a rate parameter (in milliseconds) that specifies the minimum interval between log messages.
72
73There are two configuration categories: configurations per module and global
74configuration. When logging is enabled globally, it works for modules. However,
75modules can disable logging locally. Every module can specify its own logging
76level. The module must define the :c:macro:`LOG_LEVEL` macro before using the
77API. Unless a global override is set, the module logging level will be honored.
78The global override can only increase the logging level. It cannot be used to
79lower module logging levels that were previously set higher. It is also possible
80to globally limit logs by providing maximal severity level present in the
81system, where maximal means lowest severity (e.g. if maximal level in the system
82is set to info, it means that errors, warnings and info levels are present but
83debug messages are excluded).
84
85Each module which is using the logging must specify its unique name and
86register itself to the logging. If module consists of more than one file,
87registration is performed in one file but each file must define a module name.
88
89Logger's default frontend is designed to be thread safe and minimizes time needed
90to log the message. Time consuming operations like string formatting or access to the
91transport are not performed by default when logging API is called. When logging
92API is called a message is created and added to the list. Dedicated,
93configurable buffer for pool of log messages is used. There are 2 types of messages:
94standard and hexdump. Each message contain source ID (module or instance ID and
95domain ID which might be used for multiprocessor systems), timestamp and
96severity level. Standard message contains pointer to the string and arguments.
97Hexdump message contains copied data and string.
98
99.. _logging_kconfig:
100
101Global Kconfig Options
102**********************
103
104These options can be found in the following path :zephyr_file:`subsys/logging/Kconfig`.
105
106:kconfig:option:`CONFIG_LOG`: Global switch, turns on/off the logging.
107
108Mode of operations:
109
110:kconfig:option:`CONFIG_LOG_MODE_DEFERRED`: Deferred mode.
111
112:kconfig:option:`CONFIG_LOG_MODE_IMMEDIATE`: Immediate (synchronous) mode.
113
114:kconfig:option:`CONFIG_LOG_MODE_MINIMAL`: Minimal footprint mode.
115
116Filtering options:
117
118:kconfig:option:`CONFIG_LOG_RUNTIME_FILTERING`: Enables runtime reconfiguration of the
119filtering.
120
121:kconfig:option:`CONFIG_LOG_DEFAULT_LEVEL`: Default level, sets the logging level
122used by modules that are not setting their own logging level.
123
124:kconfig:option:`CONFIG_LOG_OVERRIDE_LEVEL`: It overrides module logging level when
125it is not set or set lower than the override value.
126
127:kconfig:option:`CONFIG_LOG_MAX_LEVEL`: Maximal (lowest severity) level which is
128compiled in.
129
130Processing options:
131
132:kconfig:option:`CONFIG_LOG_MODE_OVERFLOW`: When new message cannot be allocated,
133oldest one are discarded.
134
135:kconfig:option:`CONFIG_LOG_BLOCK_IN_THREAD`: If enabled and new log message cannot
136be allocated thread context will block for up to
137:kconfig:option:`CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS` or until log message is
138allocated.
139
140:kconfig:option:`CONFIG_LOG_PRINTK`: Redirect printk calls to the logging.
141
142:kconfig:option:`CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD`: When the number of buffered log
143messages reaches the threshold, the dedicated thread (see :c:func:`log_thread_set`)
144is woken up. If :kconfig:option:`CONFIG_LOG_PROCESS_THREAD` is enabled then this
145threshold is used by the internal thread.
146
147:kconfig:option:`CONFIG_LOG_PROCESS_THREAD`: When enabled, logging thread is created
148which handles log processing.
149
150:kconfig:option:`CONFIG_LOG_PROCESS_THREAD_STARTUP_DELAY_MS`: Delay in milliseconds
151after which logging thread is started.
152
153:kconfig:option:`CONFIG_LOG_BUFFER_SIZE`: Number of bytes dedicated for the circular
154packet buffer.
155
156:kconfig:option:`CONFIG_LOG_FRONTEND`: Direct logs to a custom frontend.
157
158:kconfig:option:`CONFIG_LOG_FRONTEND_ONLY`: No backends are used when messages goes to frontend.
159
160:kconfig:option:`CONFIG_LOG_FRONTEND_OPT_API`: Optional API optimized for the most common
161simple messages.
162
163:kconfig:option:`CONFIG_LOG_CUSTOM_HEADER`: Injects an application provided header into log.h
164
165:kconfig:option:`CONFIG_LOG_TIMESTAMP_64BIT`: 64 bit timestamp.
166
167:kconfig:option:`CONFIG_LOG_SIMPLE_MSG_OPTIMIZE`: Optimizes simple log messages for size
168and performance. Option available only for 32 bit architectures.
169
170Formatting options:
171
172:kconfig:option:`CONFIG_LOG_FUNC_NAME_PREFIX_ERR`: Prepend standard ERROR log messages
173with function name. Hexdump messages are not prepended.
174
175:kconfig:option:`CONFIG_LOG_FUNC_NAME_PREFIX_WRN`: Prepend standard WARNING log messages
176with function name. Hexdump messages are not prepended.
177
178:kconfig:option:`CONFIG_LOG_FUNC_NAME_PREFIX_INF`: Prepend standard INFO log messages
179with function name. Hexdump messages are not prepended.
180
181:kconfig:option:`CONFIG_LOG_FUNC_NAME_PREFIX_DBG`: Prepend standard DEBUG log messages
182with function name. Hexdump messages are not prepended.
183
184:kconfig:option:`CONFIG_LOG_BACKEND_SHOW_COLOR`: Enables coloring of errors (red)
185and warnings (yellow).
186
187:kconfig:option:`CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP`: If enabled timestamp is
188formatted to *hh:mm:ss:mmm,uuu*. Otherwise is printed in raw format.
189
190Backend options:
191
192:kconfig:option:`CONFIG_LOG_BACKEND_UART`: Enabled built-in UART backend.
193
194.. _log_usage:
195
196Usage
197*****
198
199Logging in a module
200===================
201
202In order to use logging in the module, a unique name of a module must be
203specified and module must be registered using :c:macro:`LOG_MODULE_REGISTER`.
204Optionally, a compile time log level for the module can be specified as the
205second parameter. Default log level (:kconfig:option:`CONFIG_LOG_DEFAULT_LEVEL`) is used
206if custom log level is not provided.
207
208.. code-block:: c
209
210   #include <zephyr/logging/log.h>
211   LOG_MODULE_REGISTER(foo, CONFIG_FOO_LOG_LEVEL);
212
213If the module consists of multiple files, then ``LOG_MODULE_REGISTER()`` should
214appear in exactly one of them. Each other file should use
215:c:macro:`LOG_MODULE_DECLARE` to declare its membership in the module.
216Optionally, a compile time log level for the module can be specified as
217the second parameter. Default log level (:kconfig:option:`CONFIG_LOG_DEFAULT_LEVEL`)
218is used if custom log level is not provided.
219
220.. code-block:: c
221
222   #include <zephyr/logging/log.h>
223   /* In all files comprising the module but one */
224   LOG_MODULE_DECLARE(foo, CONFIG_FOO_LOG_LEVEL);
225
226In order to use logging API in a function implemented in a header file
227:c:macro:`LOG_MODULE_DECLARE` macro must be used in the function body
228before logging API is called. Optionally, a compile time log level for the module
229can be specified as the second parameter. Default log level
230(:kconfig:option:`CONFIG_LOG_DEFAULT_LEVEL`) is used if custom log level is not
231provided.
232
233.. code-block:: c
234
235   #include <zephyr/logging/log.h>
236
237   static inline void foo(void)
238   {
239   	LOG_MODULE_DECLARE(foo, CONFIG_FOO_LOG_LEVEL);
240
241   	LOG_INF("foo");
242   }
243
244Dedicated Kconfig template (:zephyr_file:`subsys/logging/Kconfig.template.log_config`)
245can be used to create local log level configuration.
246
247Example below presents usage of the template. As a result CONFIG_FOO_LOG_LEVEL
248will be generated:
249
250.. code-block:: none
251
252   module = FOO
253   module-str = foo
254   source "subsys/logging/Kconfig.template.log_config"
255
256Logging in a module instance
257============================
258
259In case of modules which are multi-instance and instances are widely used
260across the system enabling logs will lead to flooding. The logger provides the tools
261which can be used to provide filtering on instance level rather than module
262level. In that case logging can be enabled for particular instance.
263
264In order to use instance level filtering following steps must be performed:
265
266- a pointer to specific logging structure is declared in instance structure.
267  :c:macro:`LOG_INSTANCE_PTR_DECLARE` is used for that.
268
269.. code-block:: c
270
271   #include <zephyr/logging/log_instance.h>
272
273   struct foo_object {
274   	LOG_INSTANCE_PTR_DECLARE(log);
275   	uint32_t id;
276   }
277
278- module must provide macro for instantiation. In that macro, logging instance
279  is registered and log instance pointer is initialized in the object structure.
280
281.. code-block:: c
282
283   #define FOO_OBJECT_DEFINE(_name)                             \
284   	LOG_INSTANCE_REGISTER(foo, _name, CONFIG_FOO_LOG_LEVEL) \
285   	struct foo_object _name = {                             \
286   		LOG_INSTANCE_PTR_INIT(log, foo, _name)          \
287   	}
288
289Note that when logging is disabled logging instance and pointer to that instance
290are not created.
291
292In order to use the instance logging API in a source file, a compile-time log
293level must be set using :c:macro:`LOG_LEVEL_SET`.
294
295.. code-block:: c
296
297   LOG_LEVEL_SET(CONFIG_FOO_LOG_LEVEL);
298
299   void foo_init(foo_object *f)
300   {
301   	LOG_INST_INF(f->log, "Initialized.");
302   }
303
304In order to use the instance logging API in a header file, a compile-time log
305level must be set using :c:macro:`LOG_LEVEL_SET`.
306
307.. code-block:: c
308
309   static inline void foo_init(foo_object *f)
310   {
311   	LOG_LEVEL_SET(CONFIG_FOO_LOG_LEVEL);
312
313   	LOG_INST_INF(f->log, "Initialized.");
314   }
315
316Controlling the logging
317=======================
318
319By default, logging processing in deferred mode is handled internally by the
320dedicated task which starts automatically. However, it might not be available
321if multithreading is disabled. It can also be disabled by unsetting
322:kconfig:option:`CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD`. In that case, logging can
323be controlled using the API defined in :zephyr_file:`include/zephyr/logging/log_ctrl.h`.
324Logging must be initialized before it can be used. Optionally, the user can provide
325a function which returns the timestamp value. If not provided, :c:macro:`k_cycle_get`
326or :c:macro:`k_cycle_get_32` is used for timestamping.
327The :c:func:`log_process` function is used to trigger processing of one log
328message (if pending), and returns true if there are more messages pending.
329However, it is recommended to use macro wrappers (:c:macro:`LOG_INIT` and
330:c:macro:`LOG_PROCESS`) which handle the case where logging is disabled.
331
332The following snippet shows how logging can be processed in simple forever loop.
333
334.. code-block:: c
335
336   #include <zephyr/logging/log_ctrl.h>
337
338   int main(void)
339   {
340   	LOG_INIT();
341   	/* If multithreading is enabled provide thread id to the logging. */
342   	log_thread_set(k_current_get());
343
344   	while (1) {
345   		if (LOG_PROCESS() == false) {
346   			/* sleep */
347   		}
348   	}
349   }
350
351If logs are processed from a thread (user or internal) then it is possible to enable
352a feature which will wake up processing thread when certain amount of log messages are
353buffered (see :kconfig:option:`CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD`).
354
355.. _logging_ratelimited:
356
357Rate-limited logging
358********************
359
360Rate-limited logging macros provide a way to prevent log flooding when messages are
361generated frequently. These macros ensure that log messages are not output more
362frequently than a specified interval, similar to Linux's ``printk_ratelimited``
363functionality.
364
365The rate-limited logging system provides two types of macros:
366
367**Convenience macros (using default rate):**
368- :c:macro:`LOG_ERR_RATELIMIT` - Rate-limited error messages
369- :c:macro:`LOG_WRN_RATELIMIT` - Rate-limited warning messages
370- :c:macro:`LOG_INF_RATELIMIT` - Rate-limited info messages
371- :c:macro:`LOG_DBG_RATELIMIT` - Rate-limited debug messages
372- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT` - Rate-limited error hexdump
373- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT` - Rate-limited warning hexdump
374- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT` - Rate-limited info hexdump
375- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT` - Rate-limited debug hexdump
376
377**Explicit rate macros (with custom rate):**
378- :c:macro:`LOG_ERR_RATELIMIT_RATE` - Rate-limited error messages with custom rate
379- :c:macro:`LOG_WRN_RATELIMIT_RATE` - Rate-limited warning messages with custom rate
380- :c:macro:`LOG_INF_RATELIMIT_RATE` - Rate-limited info messages with custom rate
381- :c:macro:`LOG_DBG_RATELIMIT_RATE` - Rate-limited debug messages with custom rate
382- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT_RATE` - Rate-limited error hexdump with custom rate
383- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE` - Rate-limited warning hexdump with custom rate
384- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT_RATE` - Rate-limited info hexdump with custom rate
385- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT_RATE` - Rate-limited debug hexdump with custom rate
386
387The convenience macros use the default rate specified by :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS`
388(5000ms by default). The explicit rate macros take a rate parameter (in milliseconds) that specifies
389the minimum interval between log messages. The rate limiting is per-macro-call-site, meaning
390that each unique call to a rate-limited macro has its own independent rate limit.
391
392Example usage:
393
394.. code-block:: c
395
396    #include <zephyr/logging/log.h>
397    #include <zephyr/kernel.h>
398
399    LOG_MODULE_REGISTER(my_module, CONFIG_LOG_DEFAULT_LEVEL);
400
401    void process_data(void)
402    {
403        /* Convenience macros using default rate (CONFIG_LOG_RATELIMIT_INTERVAL_MS) */
404        LOG_WRN_RATELIMIT("Data processing warning: %d", error_code);
405        LOG_ERR_RATELIMIT("Critical error occurred: %s", error_msg);
406        LOG_INF_RATELIMIT("Processing status: %d items", item_count);
407        LOG_HEXDUMP_WRN_RATELIMIT(data_buffer, data_len, "Data buffer:");
408
409        /* Explicit rate macros with custom intervals */
410        LOG_WRN_RATELIMIT_RATE(1000, "Fast rate warning: %d", error_code);
411        LOG_ERR_RATELIMIT_RATE(30000, "Slow rate error: %s", error_msg);
412        LOG_INF_RATELIMIT_RATE(2000, "Custom rate status: %d items", item_count);
413        LOG_HEXDUMP_ERR_RATELIMIT_RATE(5000, data_buffer, data_len, "Error data:");
414    }
415
416Rate-limited logging is particularly useful for:
417
418- Error conditions that might occur frequently but don't need to flood the logs
419- Status updates in tight loops or high-frequency callbacks
420- Debug information that could overwhelm the logging system
421- Network or I/O operations that might fail repeatedly
422
423Configuration
424==============
425
426Rate-limited logging can be configured using the following Kconfig options:
427
428- :kconfig:option:`CONFIG_LOG_RATELIMIT` - Master switch to enable/disable rate-limited logging
429- :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS` - Default interval for convenience macros (5000ms)
430
431When :kconfig:option:`CONFIG_LOG_RATELIMIT` is disabled, the behavior of rate-limited macros is controlled
432by the :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK` choice:
433
434- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_LOG` - All rate-limited macros behave as regular logging macros
435- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_DROP` - All rate-limited macros expand to no-ops (default)
436
437This allows you to control whether rate-limited log macros should always print or be completely
438suppressed when rate limiting is not available.
439
440The rate limiting is implemented using static variables and :c:func:`k_uptime_get_32`
441to track the last log time for each call site.
442
443.. _logging_panic:
444
445Logging panic
446*************
447
448In case of error condition system usually can no longer rely on scheduler or
449interrupts. In that situation deferred log message processing is not an option.
450Logger controlling API provides a function for entering into panic mode
451(:c:func:`log_panic`) which should be called in such situation.
452
453When :c:func:`log_panic` is called, _panic_ notification is sent to all active
454backends. Once all backends are notified, all buffered messages are flushed. Since
455that moment all logs are processed in a blocking way.
456
457.. _logging_printk:
458
459Printk
460******
461
462Typically, logging and :c:func:`printk` use the same output, which they compete
463for. This can lead to issues if the output does not support preemption but it may
464also result in corrupted output because logging data is interleaved with printk
465data. However, it is possible to redirect printk messages to the
466logging subsystem by enabling :kconfig:option:`CONFIG_LOG_PRINTK`. In that case,
467printk entries are treated as log messages with level 0 (they cannot be disabled).
468When enabled, logging manages the output so there is no interleaving. However,
469in deferred mode the printk behaviour is changed since the output is delayed
470until the logging thread processes the data. :kconfig:option:`CONFIG_LOG_PRINTK`
471is enabled by default.
472
473
474.. _log_architecture:
475
476Architecture
477************
478
479Logging consists of 3 main parts:
480
481- Frontend
482- Core
483- Backends
484
485Log message is generated by a source of logging which can be a module or
486instance of a module.
487
488Default Frontend
489================
490
491Default frontend is engaged when the logging API is called in a source of logging (e.g.
492:c:macro:`LOG_INF`) and is responsible for filtering a message (compile and run
493time), allocating a buffer for the message, creating the message and committing that
494message. Since the logging API can be called in an interrupt, the frontend is optimized
495to log the message as fast as possible.
496
497Log message
498-----------
499
500A log message contains a message descriptor (source, domain and level), timestamp,
501formatted string details (see :ref:`cbprintf_packaging`) and optional data.
502Log messages are stored in a continuous block of memory.
503Memory is allocated from a circular packet buffer (:ref:`mpsc_pbuf`), which has
504a few consequences:
505
506 * Each message is a self-contained, continuous block of memory thus it is suited
507   for copying the message (e.g. for offline processing).
508 * Messages must be sequentially freed. Backend processing is synchronous. Backend
509   can make a copy for deferred processing.
510
511A log message has following format:
512
513+------------------+----------------------------------------------------+
514| Message Header   | 2 bits: MPSC packet buffer header                  |
515|                  +----------------------------------------------------+
516|                  | 1 bit: Trace/Log message flag                      |
517|                  +----------------------------------------------------+
518|                  | 3 bits: Domain ID                                  |
519|                  +----------------------------------------------------+
520|                  | 3 bits: Level                                      |
521|                  +----------------------------------------------------+
522|                  | 10 bits: Cbprintf Package Length                   |
523|                  +----------------------------------------------------+
524|                  | 12 bits: Data length                               |
525|                  +----------------------------------------------------+
526|                  | 1 bit: Reserved                                    |
527|                  +----------------------------------------------------+
528|                  | pointer: Pointer to the source descriptor [#l0]_   |
529|                  +----------------------------------------------------+
530|                  | 32 or 64 bits: Timestamp [#l0]_                    |
531|                  +----------------------------------------------------+
532|                  | Optional padding [#l1]_                            |
533+------------------+----------------------------------------------------+
534| Cbprintf         | Header                                             |
535|                  +----------------------------------------------------+
536| | package        | Arguments                                          |
537| | (optional)     +----------------------------------------------------+
538|                  | Appended strings                                   |
539+------------------+----------------------------------------------------+
540| Hexdump data (optional)                                               |
541+------------------+----------------------------------------------------+
542| Alignment padding (optional)                                          |
543+------------------+----------------------------------------------------+
544
545.. rubric:: Footnotes
546
547.. [#l0] Depending on the platform and the timestamp size fields may be swapped.
548.. [#l1] It may be required for cbprintf package alignment
549
550Log message allocation
551----------------------
552
553It may happen that the frontend cannot allocate a message. This happens if the
554system is generating more log messages than it can process in certain time
555frame. There are two strategies to handle that case:
556
557- No overflow - the new log is dropped if space for a message cannot be allocated.
558- Overflow - the oldest pending messages are freed, until the new message can be
559  allocated. Enabled by :kconfig:option:`CONFIG_LOG_MODE_OVERFLOW`. Note that it degrades
560  performance thus it is recommended to adjust buffer size and amount of enabled
561  logs to limit dropping.
562
563.. _logging_runtime_filtering:
564
565Run-time filtering
566------------------
567
568If run-time filtering is enabled, then for each source of logging a filter
569structure in RAM is declared. Such filter is using 32 bits divided into ten 3
570bit slots. Except *slot 0*, each slot stores current filter for one backend in
571the system. *Slot 0* (bits 0-2) is used to aggregate maximal filter setting for
572given source of logging. Aggregate slot determines if log message is created
573for given entry since it indicates if there is at least one backend expecting
574that log entry. Backend slots are examined when message is processed by the core
575to determine if message is accepted by the given backend. Contrary to compile
576time filtering, binary footprint is increased because logs are compiled in.
577
578In the example below backend 1 is set to receive errors (*slot 1*) and backend
5792 up to info level (*slot 2*). Slots 3-9 are not used. Aggregated filter
580(*slot 0*) is set to info level and up to this level message from that
581particular source will be buffered.
582
583+------+------+------+------+-----+------+
584|slot 0|slot 1|slot 2|slot 3| ... |slot 9|
585+------+------+------+------+-----+------+
586| INF  | ERR  | INF  | OFF  | ... | OFF  |
587+------+------+------+------+-----+------+
588
589.. _log_frontend:
590
591Custom Frontend
592===============
593
594Custom frontend is enabled using :kconfig:option:`CONFIG_LOG_FRONTEND`. Logs are directed
595to functions declared in :zephyr_file:`include/zephyr/logging/log_frontend.h`.
596If option :kconfig:option:`CONFIG_LOG_FRONTEND_ONLY` is enabled then log message is not
597created and no backend is handled. Otherwise, custom frontend can coexist with
598backends.
599
600In some cases, logs need to be redirected at the macro level. For these cases,
601:kconfig:option:`CONFIG_LOG_CUSTOM_HEADER` can be used to inject an application provided
602header named :file:`zephyr_custom_log.h` at the end of :zephyr_file:`include/zephyr/logging/log.h`.
603
604Frontend using ARM Coresight STM (System Trace Macrocell)
605---------------------------------------------------------
606
607For more details about logging using ARM Coresight STM see :ref:`logging_cs_stm`.
608
609.. _logging_strings:
610
611Logging strings
612===============
613
614String arguments are handled by :ref:`cbprintf_packaging`. See
615:ref:`cbprintf_packaging_limitations` for limitations and recommendations.
616
617Multi-domain support
618====================
619
620More complex systems can consist of multiple domains where each domain is an
621independent binary. Examples of domains are a core in a multicore SoC or one
622of the binaries (Secure or Nonsecure) on an ARM TrustZone core.
623
624Tracing and debugging on a multi-domain system is more complex and requires an efficient logging
625system. Two approaches can be used to structure this logging system:
626
627* Log inside each domain independently.
628  This option is not always possible as it requires that each domain has an available backend
629  (for example, UART). This approach can also be troublesome to use and not scalable,
630  as logs are presented on independent outputs.
631* Use a multi-domain logging system where log messages from each domain end up in one root domain,
632  where they are processed exactly as in a single domain case.
633  In this approach, log messages are passed between domains using a connection between domains
634  created from the backend on one side and linked to the other.
635
636  The Log link is an interface introduced in this multi-domain approach. The Log link is
637  responsible for receiving any log message from another domain, creating a copy, and
638  putting that local log message copy (including remote data) into the message queue.
639  This specific log link implementation matches the complementary backend implementation
640  to allow log messages exchange and logger control like configuring filtering, getting log
641  source names, and so on.
642
643There are three types of domains in a multi-domain system:
644
645* The *end domain* has the logging core implementation and a cross-domain
646  backend. It can also have other backends in parallel.
647* The *relay domain* has one or more links to other domains but does not
648  have backends that output logs to the user. It has a cross-domain backend either to
649  another relay or to the root domain.
650* The *root domain* has one or multiple links and a backend that outputs logs
651  to the user.
652
653See the following image for an example of a multi-domain setup:
654
655.. figure:: images/multidomain.png
656
657    Multi-domain example
658
659In this architecture, a link can handle multiple domains.
660For example, let's consider an SoC with two ARM Cortex-M33 cores with TrustZone: cores A and B (see
661the example illustrated above). There are four domains in the system, as
662each core has both a Secure and a Nonsecure domain. If *core A nonsecure* (A_NS) is the
663root domain, it has two links: one to *core A secure* (A_NS-A_S) and one to
664*core B nonsecure* (A_NS-B_NS). *B_NS* domain has one link, to *core B secure*
665*B_NS-B_S*), and a backend to *A_NS*.
666
667Since in all instances there is a standard logging subsystem, it is always possible
668to have multiple backends and simultaneously output messages to them. An example of this is shown
669in the illustration above as a dotted UART backend on the *B_NS* domain.
670
671Domain ID
672---------
673
674The source of each log message can be identified by the following fields in the header:
675``source_id`` and ``domain_id``.
676
677The value assigned to the ``domain_id`` is relative. Whenever a domain creates a log message,
678it sets its ``domain_id`` to ``0``.
679When a message crosses the domain, ``domain_id`` changes as it is increased by the link offset.
680The link offset is assigned during the initialization, where the logger core is iterating
681over all the registered links and assigned offsets.
682
683The first link has the offset set to 1.
684The following offset equals the previous link offset plus the number of domains in the previous
685link.
686
687The following example is shown below, where
688the assigned ``domain_ids`` are shown for each domain:
689
690.. figure:: images/domain_ids.png
691
692    Domain IDs assigning example
693
694Let's consider a log message created on the *B_S* domain:
695
6961. Initially, it has its ``domain_id`` set to ``0``.
697#. When the *B_NS-B_S* link receives the message, it increases the ``domain_id``
698   to ``1`` by adding the *B_NS-B_S* offset.
699#. The message is passed to *A_NS*.
700#. When the *A_NS-B_NS* link receives the message, it adds the offset (``2``) to the ``domain_id``.
701   The message ends up with the ``domain_id`` set to ``3``, which uniquely identifies the message
702   originator.
703
704Cross-domain log message
705------------------------
706
707In most cases, the address space of each domain is unique, and one domain
708cannot access directly the data in another domain. For this reason, the backend can
709partially process the message before it is passed to another domain. Partial
710processing can include converting a string package to a *fully self-contained*
711version (copying read-only strings to the package body).
712
713Each domain can have a different timestamp source in terms of frequency and
714offset. Logging does not perform any timestamp conversion.
715
716Runtime filtering
717-----------------
718
719In the single-domain case, each log source has a dedicated variable with runtime
720filtering for each backend in the system. In the multi-domain case, the originator of
721the log message is not aware of the number of backends in the root domain.
722
723As such, to filter logs in multiple domains, each source requires a runtime
724filtering setting in each domain on the way to the root domain. As the number of
725sources in other domains is not known during the compilation, the runtime filtering
726of remote sources must use dynamically allocated memory (one word per
727source). When a backend in the root domain changes the filtering of the module from a
728remote domain, the local filter is updated. After the update, the aggregated
729filter (the maximum from all the local backends) is checked and, if changed, the remote domain is
730informed about this change. With this approach, the runtime filtering works identically
731in both multi-domain and single-domain scenarios.
732
733Message ordering
734----------------
735
736Logging does not provide any mechanism for synchronizing timestamps across multiple
737domains:
738
739* If domains have different timestamp sources, messages will be
740  processed in the order of arrival to the buffer in the root domain.
741* If domains have the same timestamp source or if there is an out-of-bound mechanism that
742  recalculates timestamps, there are 2 options:
743
744  * Messages are processed as they arrive in the buffer in the root domain.
745    Messages are unordered but they can be sorted by the host as the timestamp
746    indicates the time of the message generation.
747  * Links have dedicated buffers. During processing, the head of each buffer is checked
748    and the oldest message is processed first.
749
750    With this approach, it is possible to maintain the order of the messages at the cost
751    of a suboptimal memory utilization (since the buffer is not shared) and increased processing
752    latency (see :kconfig:option:`CONFIG_LOG_PROCESSING_LATENCY_US`).
753
754Logging backends
755================
756
757Logging backends are registered using :c:macro:`LOG_BACKEND_DEFINE`. The macro
758creates an instance in the dedicated memory section. Backends can be dynamically
759enabled (:c:func:`log_backend_enable`) and disabled. When
760:ref:`logging_runtime_filtering` is enabled, :c:func:`log_filter_set` can be used
761to dynamically change filtering of a module logs for given backend. Module is
762identified by source ID and domain ID. Source ID can be retrieved if source name
763is known by iterating through all registered sources.
764
765Logging supports up to 9 concurrent backends. Log message is passed to the
766each backend in processing phase. Additionally, backend is notified when logging
767enter panic mode with :c:func:`log_backend_panic`. On that call backend should
768switch to synchronous, interrupt-less operation or shut down itself if that is
769not supported.  Occasionally, logging may inform backend about number of dropped
770messages with :c:func:`log_backend_dropped`. Message processing API is version
771specific.
772
773:c:func:`log_backend_msg_process` is used for processing message. It is common for
774standard and hexdump messages because log message hold string with arguments
775and data. It is also common for deferred and immediate logging.
776
777.. _log_output:
778
779Message formatting
780------------------
781
782Logging provides set of function that can be used by the backend to format a
783message. Helper functions are available in :zephyr_file:`include/zephyr/logging/log_output.h`.
784
785Example message formatted using :c:func:`log_output_msg_process`.
786
787.. code-block:: console
788
789   [00:00:00.000,274] <info> sample_instance.inst1: logging message
790
791
792.. _logging_guide_dictionary:
793
794Dictionary-based Logging
795========================
796
797Dictionary-based logging, instead of human readable texts, outputs the log
798messages in binary format. This binary format encodes arguments to formatted
799strings in their native storage formats which can be more compact than their
800text equivalents. For statically defined strings (including the format
801strings and any string arguments), references to the ELF file are encoded
802instead of the whole strings. A dictionary created at build time contains
803the mappings between these references and the actual strings. This allows
804the offline parser to obtain the strings from the dictionary to parse
805the log messages. This binary format allows a more compact representation
806of log messages in certain scenarios. However, this requires the use of
807an offline parser and is not as intuitive to use as text-based log messages.
808
809Note that ``long double`` is not supported by Python's ``struct`` module.
810Therefore, log messages with ``long double`` will not display the correct
811values.
812
813
814Configuration
815-------------
816
817Here are kconfig options related to dictionary-based logging:
818
819- :kconfig:option:`CONFIG_LOG_DICTIONARY_SUPPORT` enables dictionary-based logging
820  support. This should be selected by the backends which require it.
821
822- The UART backend can be used for dictionary-based logging. These are
823  additional config for the UART backend:
824
825  - :kconfig:option:`CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX` tells
826    the UART backend to output hexadecimal characters for dictionary based
827    logging. This is useful when the log data needs to be captured manually
828    via terminals and consoles.
829
830  - :kconfig:option:`CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_BIN` tells
831    the UART backend to output binary data.
832
833
834Usage
835-----
836
837When dictionary-based logging is enabled via enabling related logging backends,
838a JSON database file, named :file:`log_dictionary.json`, will be created
839in the build directory. This database file contains information for the parser
840to correctly parse the log data. Note that this database file only works
841with the same build, and cannot be used for any other builds.
842
843To use the log parser:
844
845.. code-block:: console
846
847  ./scripts/logging/dictionary/log_parser.py <build dir>/log_dictionary.json <log data file>
848
849The parser takes two required arguments, where the first one is the full path
850to the JSON database file, and the second part is the file containing log data.
851Add an optional argument ``--hex`` to the end if the log data file contains
852hexadecimal characters
853(e.g. when ``CONFIG_LOG_BACKEND_UART_OUTPUT_DICTIONARY_HEX=y``). This tells
854the parser to convert the hexadecimal characters to binary before parsing.
855
856Please refer to the :zephyr:code-sample:`logging-dictionary` sample to learn more on how to use
857the log parser.
858
859
860Recommendations and limitations
861*******************************
862
863The are following recommendations:
864
865* Enable :kconfig:option:`CONFIG_LOG_SPEED` to slightly speed up deferred logging at the
866  cost of slight increase in memory footprint.
867* Compiler with C11 ``_Generic`` keyword support is recommended. Logging
868  performance is significantly degraded without it. See :ref:`cbprintf_packaging`.
869* It is recommended to cast pointer to ``const char *`` when it is used with ``%s``
870  format specifier and it points to a constant string.
871* It is recommended to cast pointer to ``char *`` when it is used with ``%s``
872  format specifier and it points to a transient string.
873* It is required to cast a character pointer to non character pointer
874  (e.g., ``void *``) when it is used with ``%p`` format specifier.
875
876.. code-block:: c
877
878   LOG_WRN("%s", str);
879   LOG_WRN("%p", (void *)str);
880
881There are following limitations:
882
883* Logging does not support string format specifier with width (e.g., ``%.*s`` or ``%8s``). That
884  is because format string content is not used to build a log message, only argument types.
885
886Benchmark
887*********
888
889Benchmark numbers from :zephyr_file:`tests/subsys/logging/log_benchmark` performed
890on ``qemu_x86``. It is a rough comparison to give a general overview.
891
892+--------------------------------------------+------------------+
893| Feature                                    |                  |
894+============================================+==================+
895| Kernel logging                             | 7us [#f0]_/11us  |
896|                                            |                  |
897+--------------------------------------------+------------------+
898| User logging                               | 13us             |
899|                                            |                  |
900+--------------------------------------------+------------------+
901| kernel logging with overwrite              | 10us [#f0]_/15us |
902+--------------------------------------------+------------------+
903| Logging transient string                   | 42us             |
904+--------------------------------------------+------------------+
905| Logging transient string from user         | 50us             |
906+--------------------------------------------+------------------+
907| Memory utilization [#f1]_                  | 518              |
908|                                            |                  |
909+--------------------------------------------+------------------+
910| Memory footprint (test) [#f2]_             | 2k               |
911+--------------------------------------------+------------------+
912| Memory footprint (application) [#f3]_      | 3.5k             |
913+--------------------------------------------+------------------+
914| Message footprint [#f4]_                   | 47 [#f0]_/32     |
915|                                            | bytes            |
916+--------------------------------------------+------------------+
917
918.. rubric:: Benchmark details
919
920.. [#f0] :kconfig:option:`CONFIG_LOG_SPEED` enabled.
921
922.. [#f1] Number of log messages with various number of arguments that fits in 2048
923  bytes dedicated for logging.
924
925.. [#f2] Logging subsystem memory footprint in :zephyr_file:`tests/subsys/logging/log_benchmark`
926  where filtering and formatting features are not used.
927
928.. [#f3] Logging subsystem memory footprint in :zephyr_file:`samples/subsys/logging/logger`.
929
930.. [#f4] Average size of a log message (excluding string) with 2 arguments on ``Cortex M3``
931
932Stack usage
933***********
934
935When logging is enabled it impacts stack usage of the context that uses logging API. If stack
936is optimized it may lead to stack overflow. Stack usage depends on mode and optimization. It
937also significantly varies between platforms. In general, when :kconfig:option:`CONFIG_LOG_MODE_DEFERRED`
938is used stack usage is smaller since logging is limited to creating and storing log message.
939When :kconfig:option:`CONFIG_LOG_MODE_IMMEDIATE` is used then log message is processed by the backend
940which includes string formatting. In case of that mode, stack usage will depend on which backends
941are used.
942
943Some of the platforms characterization for log message with two ``integer`` arguments listed below:
944
945+---------------+----------+----------------------------+-----------+-----------------------------+
946| Platform      | Deferred | Deferred (no optimization) | Immediate | Immediate (no optimization) |
947+===============+==========+============================+===========+=============================+
948| ARM Cortex-M3 | 40       | 152                        | 412       | 783                         |
949+---------------+----------+----------------------------+-----------+-----------------------------+
950| x86           | 12       | 224                        | 388       | 796                         |
951+---------------+----------+----------------------------+-----------+-----------------------------+
952| riscv32       | 24       | 208                        | 456       | 844                         |
953+---------------+----------+----------------------------+-----------+-----------------------------+
954| xtensa        | 72       | 336                        | 504       | 944                         |
955+---------------+----------+----------------------------+-----------+-----------------------------+
956| x86_64        | 32       | 528                        | 1088      | 1440                        |
957+---------------+----------+----------------------------+-----------+-----------------------------+
958
959Logging using ARM Coresight STM
960*******************************
961
962For logging on NRF54H20 using ARM Coresight STM see :ref:`logging_cs_stm`.
963
964API Reference
965*************
966
967Logger API
968==========
969
970.. doxygengroup:: log_api
971
972Logger control
973==============
974
975.. doxygengroup:: log_ctrl
976
977Log message
978===========
979
980.. doxygengroup:: log_msg
981
982Logger backend interface
983========================
984
985.. doxygengroup:: log_backend
986
987Logger output formatting
988========================
989
990.. doxygengroup:: log_output
991
992.. toctree::
993   :maxdepth: 1
994
995   cs_stm.rst
996