Extended Information Logging

From ClusterLabs
Jump to: navigation, search

libqb 0.17.2 and later supports "extended information logging," also referred to as "split logging."

With this feature, you can log a single message with less detail in one log and more detail in another log.

Why

LibQB lets you have multiple logs, and filter messages to them differently. For example, Pacemaker uses this to put messages of notice and higher severity (which are of interest to system administrators) in the system log, and all messages (including info and lower severity, of interest mainly to developers) in /var/log/pacemaker.log.

However, users might still find the system log messages difficult to follow. Extended information logging is one way to address that, by filtering not just separate log messages, but the contents of a single log message.

The extended information marker

LibQB defines the constants QB_XC (character literal) and QB_XS (the same thing but as a string literal). If a format string contains that character, everything after it is considered "extended information".

Applications can enable or disable the logging of extended information. The default is enabled -- the entire message goes to all logs.

The magic character will be displayed as a pipe ('|') in actual output.

Example:

/* Disable printing extended information to syslog */
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_EXTENDED, QB_FALSE);

/* Print a message with extended information */
/* We are just using string literal concatenation here */
qb_log(LOG_ERROR, "Something bad happened! " QB_XS " foo=2");

With the above, the system log will only show "Something bad happened!", but any other logs defined will show "Something bad happened! | foo=2".

FYI The magic character is defined as the ASCII 'bell' control character ('\a'). In the unlikely event someone wants to actually log that, they can put it in the extended information (only the first occurrence is significant) or use a %c specifier in the format string (only occurrences in the format string are significant).

Backward compatibility

If you want to use the new feature but still be able to link against older versions of libqb, you can wrap calls according to whether QB_XS is defined.

Here is an example based on how Pacemaker does it:

* "Extended information" logging support */
#ifdef QB_XS
#  define CRM_XS QB_XS
#  define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e))
#else
#  define CRM_XS "|"

/* A caller might want to check the return value, so we can't define this as a
 * no-op, and we can't simply define it to be 0 because gcc will then complain
 * when the value isn't checked.
 */
static inline int
crm_extended_logging(int t, int e)
{
    return 0;
}
#endif