7.2. log — Logging

The logging module consists of log objects and log handlers. A log object filters log entries and a log handler writes log entries to an output channel.

A log object called “log” and a log handler writing to standard output are created during the log module initialization. The log handler can be replaced by calling log_set_default_handler_output_channel().

Normally one log object is created for each subsystem in an application. This gives the user the power to control which parts of the system to debug and/or monitor at runtime.

It’s also possible to print log entries without using log objects, but instead use the current threads’ log mask to filter log entries. Just give NULL as the first arguement to log_object_print(), and the threads’ log mask will be used. See thrd — Threads details on how to change the threads’ log mask.

Sometimes it’s useful to write log entries to multiple channels. This is possible by creating and adding another log handler to the log module.

7.2.1. Log levels

There are five log levels defined; fatal, error, warning, info and debug. The log levels are defined as LOG_<upper case level> in the log module header file.

7.2.2. Log entry format

A log entry consists of a timestamp, log level, thread name, log object name and the message. The timestamp is the log entry creation time and the log level is one of fatal, error, warning, info and debug. The thread name is the name of the thread that created the log entry and the log object name is the name of the log object the entry was printed on. The message is a user defined string.

<timestamp>:<log level>:<thread name>:<log object name>: <message>

7.2.3. Debug file system commands

Three debug file system commands are available, all located in the directory debug/log/.

Command Description
list Print a list of all log objects.
print <string> Print a log entry using the default log object and log
level LOG_INFO. This command has no use except to test
that the log module works.
set_log_mask <object> <mask> Set the log mask to <mask> for log object <object>.

Example output from the shell:

$ debug/log/list
     OBJECT NAME  MASK
         default  0x0f
OK
$ debug/log/print "Hello World!"
OK
$ debug/log/set_log_mask default 0x1f
OK
$ debug/log/list
     OBJECT NAME  MASK
         default  0x1f
OK
$ debug/log/print "Hello World!!!"
56:info:main:default: Hello World!!!
OK

7.2.4. Example

Here is an example of how to create two log objects; foo and bar, and then use them and the default log object default.

The source code:

/* Initialize the log objects foo and bar. */
struct log_object_t foo;
struct log_object_t bar;

log_object_init(&foo, "foo", LOG_UPTO(INFO));
log_object_init(&bar, "bar", LOG_UPTO(DEBUG));

/* Print four log entries. */
log_object_print(&foo, LOG_INFO, OSTR("A foo info message."));
log_object_print(&bar, LOG_INFO, OSTR("A bar info message."));
log_object_print(&bar, LOG_DEBUG, OSTR("A bar debug message."));
log_object_print(NULL, LOG_ERROR, OSTR("A default error message."));

All logs are printed from the main thread as can be seen in the third field in the entries in the output below.

23.0:info:main:foo: A foo info message.
24.0:info:main:bar: A bar info message.
37.0:debug:main:bar: A bar debug message.
56.0:error:main:default: A default error message.

Source code: src/debug/log.h, src/debug/log.c

Test code: tst/debug/log/main.c

Test coverage: src/debug/log.c


Defines

LOG_FATAL
LOG_ERROR

A handable error conditions.

LOG_WARNING

A warning.

LOG_INFO

Generic (useful) information about system operation.

LOG_DEBUG

Developer debugging messages.

LOG_MASK(level)

Craete a log mask with given level set.

LOG_UPTO(level)

Set all levels up to and including given level.

LOG_ALL

Set all levels.

LOG_NONE

Clear all levels.

Functions

int log_module_init(void)

Initialize the logging module. This function must be called before calling any other function in this module.

The module will only be initialized once even if this function is called multiple times.

Return
zero(0) or negative error code.

int log_object_init(struct log_object_t *self_p, const char *name_p, char mask)

Initialize given log object with given name and mask.

Return
zero(0) or negative error code.
Parameters
  • self_p: Log object to initialize.
  • name_p: Log object name.
  • mask: Log object mask.

int log_object_set_log_mask(struct log_object_t *self_p, char mask)

Set given log mask for given log object.

Return
zero(0) or negative error code.
Parameters
  • self_p: Log object.
  • mask: Log object mask.

char log_object_get_log_mask(struct log_object_t *self_p)

Get the log mask of given log object.

Return
Log mask.
Parameters
  • self_p: Log object.

int log_object_is_enabled_for(struct log_object_t *self_p, int level)

Check if given log level is enabled in given log object.

Return
true(1) if given log level is enabled, false(0) if given log level is disabled, otherwise negative error code.
Parameters
  • self_p: Log object, or NULL to check the level in the thread log mask.
  • level: Log level to check.

int log_object_print(struct log_object_t *self_p, int level, const char *fmt_p, ...)

Check if given log level is set in the log object mask. If so, format a log entry and write it to all log handlers.

self_p may be NULL, and in that case the current thread’s log mask is used instead of the log object mask.

Return
zero(0) or negative error code.
Parameters
  • self_p: Log object, or NULL to use the thread’s log mask.
  • level: Log level.
  • fmt_p: Log format string.
  • ...: Variable argument list.

int log_handler_init(struct log_handler_t *self_p, void *chout_p)

Initialize given log handler with given output channel.

Return
zero(0) or negative error code.
Parameters
  • self_p: Log handler to initialize.
  • chout_p: Output handler.

int log_add_handler(struct log_handler_t *handler_p)

Add given log handler to the list of log handlers. Log entries will be written to all log handlers in the list.

Return
zero(0) or negative error code.
Parameters
  • handler_p: Log handler to add.

int log_remove_handler(struct log_handler_t *handler_p)

Remove given log handler from the list of log handlers.

Return
zero(0) or negative error code.
Parameters
  • handler_p: Log handler to remove.

int log_add_object(struct log_object_t *object_p)

Add given log object to the list of log objects. There are file system commands to list all log objects in the list and also modify their log mask.

Return
zero(0) or negative error code.
Parameters
  • object_p: Log object to add.

int log_remove_object(struct log_object_t *object_p)

Remove given log object from the list of log objects.

Return
zero(0) or negative error code.
Parameters
  • object_p: Object to remove.

int log_set_default_handler_output_channel(void *chout_p)

Set the output channel of the default log handler.

Return
zero(0) or negative error code.
Parameters
  • chout_p: Channel to set as the default output channel. May be NULL if no output should be written.

struct log_handler_t

Public Members

void *chout_p
struct log_handler_t *next_p
struct log_object_t

Public Members

const char *name_p
char mask
struct log_object_t *next_p