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