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