Lager

This project is really so insignificant that it doesn't deserve it's own web page. But as I'm getting sick of implementing a logging class every time I start a new project I figured I'd just make one and adapt it as I go. This is that logging class. It was inspired by an article I read in one of the Game Programming Gems books (which I unfortunately can't find at the moment) that spoke about using function scope and object lifetime to create a logging system that automatically kept track of the call stack for you. The idea is pretty simple, when you go into a function you create an object that just holds a string that tells you the scope. That object gets put on a singleton stack. When you come to a point where you want to log that stack is printed out before the log message is printed. If you do this all using XML then you end up with log files that have a built in tree structure and can be easily parsed and manipulated and what not. Ideally I'd like to build tools to work with the output xml files, but for now I just use a web browser and it gives me enough control.

Using the Lager is pretty simple, you initialize the singleton LogServer for a thread, then you just use some macros to define scope and log messages. Here's a full program to illustrate the point:
#include "../../LogServer.h"
#include "../../Lager.h"

using namespace Lager;

void Func1();
void Func2();

int main( int argc, char** argv )
{
	Func1();
	Func2();

	return 1;
}

void Func1()
{
	LOG_SCOPE_LOW( "Func1", "testing 1 2 3 " << 4 );
	LOG_LOW( "DEVELOPER Test log entry 1 Func1" );
	Func2();
	LOG_MID( "GEEK Test log entry 2 Func1" );
}

void Func2()
{
	LOG_SCOPE( "Func2" );
	LOG_LOW( "DEVELOPER Test log entry 1 Func2" );
	LOG_HIGH( "USER Test log entry 2 Func2" );
}

The above program will produce this xml file.

The Lager can be compiled into two libraries, a threaded and a non-threaded one. The threaded version keeps thread information in a std::vector and it uses thread local storage to index it. Because of this it isn't incredibly efficient. The non-threaded version doesn't incur this overhead. The included solution/workspace files let you build both versions. If you're using the threaded version you must define THREADED_LAGER in your project.

You can download the Lager source here. It includes 2 subdirectories:
  • Lager: The actual Lager library.
  • Lager.Tests: Two simple test apps to show how it works.
I hope you find it useful.