Skip to content

Formats

The default format used for logs is:

I [yyyy-mm-dd hh:mm:ss] tag (main.c:10): Hello World!

Predefined formats

Different formats can be chosen from by defining LOG_FORMAT and LOG_FORMAT_ARGS.

The following predefined formats are available:

  • JSON:
{"level":"info", "ts":"yyyy-mm-dd hh:mm:dd", "component":"main", "caller":"main.c:10", "msg":"Hello World!"}
#define LOG_FORMAT      LOG_FORMAT_JSON
#define LOG_FORMAT_ARGS LOG_FORMAT_JSON_ARGS
  • Key/Values:
ts=yyyy-mm-dd hh:mm:ss caller=main.c:10 level=info component=main msg="Hello World!"
#define LOG_FORMAT      LOG_FORMAT_KEYS
#define LOG_FORMAT_ARGS LOG_FORMAT_KEYS_ARGS

Usage

Use a predefined format by defining LOG_FORMAT and LOG_FORMAT_ARGS at the project level:

# CMakeFiles.txt
target_compile_definitions(${your_app} PUBLIC "-DLOG_FORMAT=LOG_FORMAT_JSON -DLOG_FORMAT_ARGS=LOG_FORMAT_JSON_ARGS")

Or at the file level before including logger.h:

#define LOG_FORMAT      LOG_FORMAT_JSON
#define LOG_FORMAT_ARGS LOG_FORMAT_JSON_ARGS
#include "logger.h"

Timestamp format

Datetime

The timestamp format used is defined by LOG_TIMESTAMP_FORMAT and defaults to %Y-%m-%d %H:%M:%S. It is internally generated by a call to strftime() and can be overriden with a valid strftime format string.

# CMakeFiles.txt
target_compile_definitions(${your_app} PUBLIC LOG_TIMESTAMP_FORMAT="%Y-%m-%d %H:%M:%S")

NOTE:

The LOG_TIMESTAMP_FORMAT can be overriden independantly of LOG_FORMAT.

Sub-seconds addition

Sub-seconds formats are not supported by strftime but can additionally be appended to the generated timestamp string.

This can be done by defining one of the following:

Definition Description
LOG_TIMESTAMP_MILLISECONDS Add milliseconds string to timestamp.
LOG_TIMESTAMP_MICROSECONDS Add microseconds string to timestamp.
LOG_TIMESTAMP_NANOSECONDS Add nanoseconds string to timestamp (Not supported on every platform).
# CMakeFiles.txt
target_compile_definitions(${your_app} PUBLIC LOG_TIMESTAMP_MILLISECONDS)

Custom format

A custom format can be created by defining two macros with the same "signature" as these:

#define LOG_FORMAT(msg)  "%s [%s] %s (%s:%ld): " msg "\n"
#define LOG_FORMAT_ARGS(level, level_short, tag, time, file, line, ...) level, (time), tag, file, line, ##__VA_ARGS__

The first one is the format of the message using the printf formatted output syntax. The second one is the list of arguments for the formatted syntax.
These macros can be thought as wrappers of the user defined log() call to printf().

// With the following custom format
#define LOG_FORMAT(msg)  "%s [%s] %s (%s:%ld): " msg "\n"
#define LOG_FORMAT_ARGS(level, level_short, tag, time, file, line, ...) level, (time), tag, file, line, ##__VA_ARGS__

// Calling a log macro ...
log_i("tag", "%s", "Hello World!");

// ... would be equivalent to:           
printf(LOG_FORMAT("%s"), LOG_FORMAT_ARGS(<predefined args>, "Hello World!"));

// ... which would be compiled to:
printf("%s [%s] %s (%s:%ld): %s\n",
        "info", "yyyy-mm-dd hh:mm::dd", "tag", "main.c", 10, "Hello World!");

You can look at logger.h source code for examples on how the Default, JSON and Key/Value formats are defined using this system.

Macro arguments

The main idea behind this macro system is that all the available parameters are provided and they can be used, formatted and/or reordered as wanted.

LOG_FORMAT(msg)
Argument Type Description
msg string "%s" The first argument from the log macro.
LOG_FORMAT_ARGS(level, level_short, tag, time, file, line, ...)
Argument Type Description
level string "%s" The level string (ie: "error", "warning", "info", "debug" or "verbose").
level_short char "%c" A single character for the level ('E', 'W', 'I', 'D' or 'V').
tag string "%s" The tag name.
time string "%s" The timestamp string. NOTE: This argument needs to be rewritten with parentheses.
file string "%s" The filename where the log was called.
line long "%ld" The line where the log was called.
... variable args The rest of the arguments from the log macro. NOTE: Rewrite these as ##__VA_ARGS__.

NOTE:

  1. It is not mandatory to use all the available arguments in the macros.
  2. Ensure that all the formatted '%' in the LOG_FORMAT macro have a corresponding in-order parameter in the LOG_FORMAT_ARGS macro.