ulog

Library with macros and functions to log text messages in the logging system (printf-like but redirected to a kernel device to allow saving on storage and real-time display). For further information, you can find the source code here.

How to use Ulog

First, declare one or several ULOG tag names in a .c or .cpp source file, like this:

#include "ulog.h"
ULOG_DECLARE_TAG(toto);
ULOG_DECLARE_TAG(Foo_Bar);

Note that the argument of ULOG_DECLARE_TAG() is the tag name and should be a valid C symbol string, such as ‘my_module’, ‘MyTag’, etc.

Then, set the default tag to use inside a given source file by defining macro ULOG_TAG before including ulog.h:

#define ULOG_TAG Foo_Bar
#include "ulog.h"

You can now use short macros for logging:

ULOGW("This module will auto-destruct in %d seconds...\n", 3);
ULOGE("Fatal error\n");

If you forget to define macro ULOG_TAG, then a default empty tag is used.

Note

If you need to log messages from a signal handler, make sure a first message using the tag is logged at runtime before installing your handler.

How to control Ulog logging level

Ulog logging is globally controlled by environment variable ULOG_LEVEL. This variable should contain a single letter (‘C’, ‘E’, ‘W’, ‘N’, ‘I’, or ‘D’) or, alternatively, a single digit with an equivalent meaning:

  • C = Critical = 2

  • E = Error = 3

  • W = Warning = 4

  • N = Notice = 5

  • I = Info = 6

  • D = Debug = 7

For instance, to enable all priorities up to and including the ‘Warning’ level, you should set: ULOG_LEVEL=W or, equivalently, ULOG_LEVEL=4

The default logging level is ‘I’, i.e. all priorities logged except ‘Debug’. ULOG_LEVEL controls logging levels globally for all tags. Setting an empty ULOG_LEVEL string disables logging completely. You can also control the logging level of a specific tag by defining environment variable ULOG_LEVEL_<tagname>. For instance:

ULOG_LEVEL_Foo_Bar=D   # set level Debug for tag 'Foo_Bar'

The above environment variables are read only once, before the first use of a tag. To dynamically change a logging level at any time, you can use macro ULOG_SET_LEVEL() like this:

ULOG_SET_LEVEL(ULOG_DEBUG);
ULOGD("This debug message will be logged.");
ULOG_SET_LEVEL(ULOG_INFO);
ULOGD("This debug message will _not_ be logged.");
ULOGI("But this one will be.");

ULOG_SET_LEVEL() takes precedence over ULOG_LEVEL_xxx environment variables. If ULOG_SET_LEVEL() is used without a defined ULOG_TAG, then it sets the default logging level used when no environment variable is defined. ULOG_GET_LEVEL() returns the current logging level of the default tag defined with ULOG_TAG.

If you need to dynamically control the logging level of an external tag, i.e. a tag not declared in your code (for instance declared and used in a library to which your code is linked), you can use the following function (assuming the tag is ‘foobar’):

ulog_set_tag_level("foobar", ULOG_WARN);

There is a restriction to the above code: the tag will be accessible and controllable at runtime only after its has been used at least once. This is because the tag “registers” itself during its first use, and remains unknown until it does so. A library can make sure its tags are externally visible by forcing early tag registration with macro ULOG_INIT() like this:

ULOG_INIT(foobar); // at this point, tag 'foobar' logging level is externally controllable

This can be done typically during library initialization. You can also dynamically list ‘registered’ tags at runtime with function ulog_get_tag_names().

How to control Ulog output device

To control which kernel logging device is used, use environment variable ULOG_DEVICE:

ULOG_DEVICE=balboa  # default device is 'main'

The logging device can be changed dynamically with:

ulog_set_log_device("newdevicename");

To enable printing a copy of each message to stderr:

ULOG_STDERR=y