Date
1 - 4 of 4
RFC Common System logging API Rev. 2
Saucedo Tejada, Genaro <genaro.saucedo.tejada@...>
This is the second attempt to define a common system logging API,
Original thread can be seen here: https://lists.zephyrproject.org/archives/list/devel(a)lists.zephyrproject .org/thread/A6CROK67VKFKFSCENJ6UVQL2IRNHLNW2/#A6CROK67VKFKFSCENJ6UVQL2I RNHLNW2 Background: Currently several files declare their own logging infrastructure and sometimes even in the same way, effectively duplicating code, there is no common logger header or a single interface for logging, this situation also complicates enhancement of logging functionality. We want to concentrate logging functionality at a single point to ease configuration and enhancement while reusing some existing logging features. Proposal to implement new logging API: Create a new header file at include directory, remove all logger macro definition from .c files and have a single, definition on the new header. On each .c file that requires logging include the new header and specify feature/file specific values, such as logging domain (if any) and per-feature logging switch (view number 7 below). The surveyed features selected for this logging API are: 1. Kconfig based selection of output backend, these currently being stdio printf when console is available and printk as fall back. 2. Optional macro expansion, controlled at compile time by Kconfig files and make menuconfig command. Disabling this helps saving size at binary images when logging is not needed. 3. Multi category logging, this allows to only enable some of the logging macros. Previous proposal considered "levels" that are inherently incremental, i.e., a given level is always a super set of lower levels. New proposal doesn't force precedence between any of the four defined macros. 4. Caller thread printing, optionally prints the current thread pointer. 5. Caller function printing. New features are added: 6. Labeled log, helps differentiate log categories by using a label at the beginning. 7. Fine grain per-feature log activation. Allows enabling log at specific parts of the code through menuconfig. 8. Logging domain, a string optionally specified to be appended to log messages in order to helps differentiate log output in case several features are enabled, domain is specified by definition of SYS_LOG_DOMAIN macro. Design decisions and rationale: This API was implemented based on macros instead of run-time functions (except for thread retrieval) in an attempt to minimize both execution overhead and binary size increments introduced by logging. It's important to emphasize that by leaving log activation logic to preprocessor (at compile time) the binary images size can be effectively reduced by decreasing the amount of activated log macros, of course verbosity is reduced as well. The macros also act as a facade that can be implemented in the background by different implementations, currently printk and printf are the only available implementations. Taking into account feedback from previous RFC version, specifically ht tps://lists.zephyrproject.org/archives/list/devel(a)lists.zephyrproject.o rg/message/RKVXWR75XFN3TCXKQV2STRACPMPVSEB4/, a given log macro gets activated when its category is selected for the current module. Such combination allows to specify different verbosity at each module. The macro categories are intended to filter the log according to the nature of the messages, e.g., ERROR category would report failures found by the program during execution while DEBUG could record tracing information relevant to programmer during development and debugging. Each module needs its own category specified and different modules might have different categories specified. For example, a new driver might depend on GPIO, so for debugging this new driver the GPIO related module gets its log category set to ERROR and the driver has all categories activated, that way developer can identify when an error was encountered by GPIO code, without having to see messages on all the categories at GPIO code, and could check the DEBUG category of the new driver to see the details on how was this error handled. Implementation details: The macros are defined at include/misc/sys_log.h, they get enabled by the per-module switch SYS_LOG_LEVEL (specified before header include) and the global switch (CONFIG_SYS_LOG). The per-module switch gets relayed at .c file from the Kconfig options in the following way: #define SYS_LOG_LEVEL CONFIG_SYS_LOG_GROVE_LEVEL #include <misc/sys_log.h> If SYS_LOG_LEVEL is not defined a default is used: CONFIG_SYS_LOG_DEFAULT_LEVEL. Previous approach was to enforce the definition by failing compilation if not defined. The following switches control some optional formatting: CONFIG_SYS_LOG_ENABLE_PRINTF: specifies printf as backend. CONFIG_SYS_LOG_ENABLE_PRINTK: specifies printk as backend. CONFIG_SYS_LOG_SHOW_TAGS: sets category tags on. SYS_LOG_DOMAIN: sets domain string that will be included at the start of the messages. CONFIG_SYS_LOG_THREAD: specifies whether to print thread pointer or not. Log categories are selected through a bitmap, each of the 4 least significant bits of bitmap correspond each of the four defined categories. Macros get activated when the bit for their category is 1 on the SYS_LOG_LEVEL of including compile unit, e.g.: When SYS_LOG_LEVEL is 9 (0b1001) for current compile unit SYS_LOG_DBG and SYS_LOG_ERR, corresponding to ERROR and DEBUG categories, are active. The macros SYS_LOG_INF and SYS_LOG_WRN instead expand to "{ ; }" 0b0000 //LOG is off (0) 0b1000 //LOG is ERROR (1) 0b1100 //LOG is ERROR + WARNING (3) 0b1110 //LOG is ERROR + WARNING + INFO (7) 0b1111 //LOG is ERROR + WARNING + INFO + DEBUG (15) Future work: Subsequent patches need to define a sanity test, and replace old DBG macro calls on several files.
|
|
Tomasz Bursztyka
Hi Genaro,
Could you give the gerrit links? The following switches control some optional formatting:Aren't these 2 being mitigated by CONFIG_STDOUT_CONSOLE ? If this option is set: printf will be used, printk otherwise. Tomasz
|
|
Saucedo Tejada, Genaro <genaro.saucedo.tejada@...>
On Fri, 2016-03-11 at 11:49 +0100, Tomasz Bursztyka wrote:
Hi Genaro,Yes, I got a similar comment on gerrit, this has been done in such way because in the future more "back ends" are expected, i.e., other functions could be called hence a "back end" menu choice. But for following patch I'm likely removing that. Somehow outdated patches are available at gerrit: https://gerrit.zephyrproject.org/r/691 https://gerrit.zephyrproject.org/r/722
|
|
Boie, Andrew P
I really think that officially supporting both printk() and printf() in the kernel is a bad idea. Having Zephyr depend on libc APIs really isn't the way to go. Zephyr should not care whether printf() exists or not.CONFIG_SYS_LOG_ENABLE_PRINTF: specifies printf as backend. The real "backend" should simply be the character output routine, an interface for emitting one character to an output device, whether a RAM buffer, IPM channel, UART, etc. Currently this is managed by ad hoc private APIs, but this would be a good thing to make official. Andrew
|
|