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