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