RLog - a C++ logging library

RLog is a flexible message logging facility for C++ programs and libraries. It is highly optimized for the case where no log messages are output, so that it can be left in production code and enabled on-demand.

Distributed under the LGPL license, see the file ‘COPYING’ in the distribution for details.

Technical documentation is part of the distribution, but is temporarily offline.

Introduction

RLog provides macros which are similar to Qt’s debug macros, which are similar to simple printf() statements. Messages may be categorized hierarchically, or just use the predefined channels:

// create custom logging channel (part of debug hierarchy)
// Any subscriber to 'debug' will also pick up this sub channel,
// or it can be subscribed to directly.
static RLogChannel *timeChannel = DEF_CHANNEL("debug/timeStamp", Log_Debug);

void func(int foo)
{
    // log to the 'debug' channel
    rDebug("foo = %i", foo);
    int ans = 6 * 9;
    if(ans != 42)
        rWarning("ans = %i, expecting 42", ans); // log to warning channel
    // log to error channel
    rError("I'm sorry %s, I can't do that (error code %i)", name, errno);

    // log to custom channel
    // Note: time() never gets called unless there are subscribers to this message
    rLog(timeChannel, "the time is now %i", (int)time(NULL));
}

The difference to Qt’s macros is that the log messages are on-demand publishers and there can be any number of subscribers to log messages. Subscribers may choose which messages they want to receive in a number of different ways:

  • subscribe to messages to a particular channel. Channels are hierarchical can be easily created.
  • subscribe to anything from a particular component.
  • subscribe to messages from a particular file name within a component.

If there are no subscribers to a particular logging statement, that statement can be said to be dormant. RLog is optimized to minimize overhead of dormant logging statements, with the goal of allowing logging to be left in release versions of software. This way if problems show up in production code, it is possible to activate logging statements in real time to aid debugging.

As an indication of just how cheap a dormant logging statement is, on an x86-64 class CPU with g++ 4.2, a dormant log in a tight loop adds on the order of 2 clock cycles of overhead (exact value depends on the CPU and compiler - see also note #1). By comparison a simple logging function such as Qt’s qDebug() adds about 1000 (a thousand) clock cycles of overhead - even when messages are being thrown away.

In addition, logging statements in RLog can be individually activated at run-time, allowing targeted log reporting.

Using RLog

In order to begin using RLog in your code, you should do the following:

  • define RLOG_COMPONENT in your build environment. Eg: librlog is built with -DRLOG_COMPONENT=”rlog”. You should use a unique name for your program or library (do not use “rlog”). If your program is made up of separate components, then you can define RLOG_COMPONENT as a different name for each component.
  • add subscribers (rlog::StdioNode , rlog::SyslogNode , or your own) to catch any messages you are interested in.
  • (optional) add a call to RLogInit() in your main program startup code. This is not a requirement, however not including it may reduce functionality of external rlog modules.
  • link with librlog

Requirements

RLog is cross-platform and has been built on a number of systems: 

Platform Operating System Compiler Notes
ix86-64 Ubuntu 8.04 GNU G++ 4.2.3 tested with RLog 1.4
ix86 Fedora 9
GNU G++ 4.3.0 tested with RLog 1.4

SuSE 10
GNU G++ 4.0.2 tested with RLog 1.3.7

SuSE 9.0 Intel ICC 8.0 last test was prior to RLog 1.3.4

OpenBSD 3.4 GNU G++ 2.95.3 tested with RLog 1.3.5

FreeBSD 4.10-beta GNU G++ 2.95.4 tested with RLog 1.3.6

Windows Visual C++ 7.1 tested with RLog 1.3.6 (note #2)
sparc Solaris 5.9 GNU G++ 3.3.2 tested with RLog 1.3.6
PowerPC Darwin 5.5 gcc-932.1 tested with RLog 1.3.6

To build development versions, you will also need the GNU autoconf tools (with automake and libtool). Documentation is built using Doxygen.

You can find pre-built versions of RLog on many Linux distributions, however the package name may vary. On Debian systems, look for the package "librlog1c2a" and "librlog-dev".  In Fedora, look for rpms "rlog" and "rlog-devel".

Downloads

RLog is available in source code and RPM packaged binaries for some systems. 

For downloads or bug reports, please visit http://code.google.com/p/rlog/ 

Changelog:

RLog Version 1.4 - June 14, 2008 release:

  • Fixes to compile with G++ 4.x
  • Add thread safety for multiple threads using the same log statement
  • Add PublishLoc destructor, so RLog can be used in dynamic modules which may be unloaded
  • Performance improvements for unsubscribed log messages - down to less then 2 clock cycles average cost on x86-64 system by helping the system to better cache log metadata
  • Import Windows build updates for VC 8.0 (thanks to David Wolfe)

If you wish to be notified automatically of new releases, you can subscribe to new release notifications on the Freshmeat page

For checking signatures, you can get my GPG from any public key server, or here: fingerprint 2EAF4D80