-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Description
Introduction
Logging subsystem has been in zephyr for more than 2 years. During that time there were feature requests which could not be fulfilled with current design. As number of those requests has grown I've started to look into overhaul of logger internals. Overhaul does not plan to change logger application API but it will change backend API. Currently logger has following limitations:
- 64 bit values cannot be logged
- floats cannot be logged logging: 32 bit float values don't work. #18351
- logging transient strings is problematic and requires explicit
log_strdupRFC: adjust policies and introduce new macros for logging strings #18147 - log message is not self-contained as it arguments may point to transient strings RFC: adjust policies and introduce new macros for logging strings #18147
- log hexdump macros does not accept arguments for meta string HEXDUMP log gives warning when logging function name. #26170
- logging from user space is time consuming
Further weaknesses:
- processing log message takes a lot of stack and flash as log message arguments need to be resolved to vla function:
zephyr/subsys/logging/log_output.c
Line 278 in a953ac8
static void std_print(struct log_msg *msg, - internal handling of log messages is troublesome because of fragmented nature.
There were suggestions (@andyross) to switch to use ring buffer instead of current fragmented messages.
Proposed change
Plan is to rework internals of the logger to store log message in a ring buffer. This will require that backends handle message synchronously (make a copy if needed).
There will be only one type of a log message (instead of current distinction between standard and hexdump). Message will consist of header, arguments, data (optional), transient strings (optional). Logger will attempt to store arguments in a way that it can be directly casted to va_list (validated on majority of platforms). String arguments will point to space within the message.
_Generic keyword (https://en.cppreference.com/w/c/language/generic) will be used to detect types of logger message arguments at compile time. Any float arguments will be promoted to double, any char * arguments will trigger further processing which will involve detecting %s arguments, calculating length needed to store strings, copying strings to the message body. log_strdup will be deprecated.
This approach shall solve all weaknesses and limitations mentioned above.
As already mentioned, internal architecture change will impact backend interface. Currently, log_message handling is asynchronous, message is alive until last backend indicates that message is not used. This approach may give better memory utilization in certain scenarios because backend does not need to copy the message but, in general, new approach will more memory efficient due to ring buffer. Current approach comes from nrf5 sdk where it was used in a bare metal applications where asynchronous handling is more welcomed. In RTOS environment value of this approach diminishes.
Ring buffer needed for the logger may be generic since it is a variable length messages buffer with following arguments:
- multiple producers
- 3 modes: saturate, overwrite the oldest, block thread context until available
- two consumers: standard and panic which may interrupt standard
There are further requests which does not imply architecture change and they will be gradually fixed:
- Storing log filtering data in persistent memory Store logger filtering data in persistent memory #29147
- LOG_RAW macro logging: add LOG_RAW macro #23019
- User definable logger tag User definable logger tag #20430
@andyross please let me know if you have any comments.
Dependencies
Logger backends interface will change. It will be simplified as there will be only single message type, message will not be fragmented and arguments will form va_list which can be directly passed to the formatter.
Concerns and Unresolved Questions
_Generic keyword is C11 (#30105) and it is unclear which C standard is currently used by Zephyr. However, it currently compiles without enforcing C11. I didn't who enables C11.