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