A small collection of useful C++ classes targeted for high performance servers.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.



A small collection of useful C++ classes targeted for high performance servers.


Logging is a pain-point in many C++ projects. My log library was written before boost::log was available, and I must admit that i was a bit disappointed over the complexity of boost:log when it arrived. I have written a handful of logger libraries over the years, and used quite a few in different programing languages. Why so complex? Logging is not all that hard, is it?

WarLog gives you control over what you want to log. You can filter on severity and context, and log-statements that won't be forwarded to any logs are not expanded (the log processing stops after evaluating if the log statement is required).

For example:

  LOG_NOTICE << "If we log at notice level, this line will be processed and logged";

  LOG_DEBUG << "While this will not";

This is significant if some of your log statement contains method calls that are slow (like pulling stack frames, or context data from variables scattered around in memory). Method calls in the log statements are only called if the data is required at the current log-level.

I usually add lots of log statements in my code, much of which I never want to see when things work as expected. Therefore, I have 4 TRACE levels, so that I can log really low-level and frequently called code, and very easily filter it out while still getting lots of details. In a server, like a HTTP server, I may have several layers processing input from the client. I can log the data received over the wire at TRACE level 4, the decompression at level 3, decoding of chunks at level 2, final raw data at level one, and then nicely show what's going on like "Client at sent a GET request regarding "/bla/bla" with headers headers dumped here at debug level. That means that if there ever is a problem with, for example, the chunk-decoding (and be sure - there will be if you wrote it yourself!), it's trivial to deduce from the logs what went wrong. But normally, you will only see the high-level debug messages (and higher).

Log levels:

/*! Log Level */
enum LogLevel {
    /// Fatal error. The application terminates
    /// Error
    /// Warning
    /// Information. Typically program version, internal modules being enabled etc.
    /// Notice. Typically some action that is started or completed.
    /// Debug messages. These provides verbose information regarding the processing
    /// Trace message
    /// Trace message
    /// Trace message
    /// Trace message

WarLog can also filter on context, based on bits. These are the defined values. You are free to add more yourself in your own code.

enum LogAbout {
    /// General message
    LA_GENERAL  = 0x00000001,
    /// Security
    LA_SECURITY = 0x00000002,
    /// File transfer
    LA_TRANSFER = 0x00000004,
    /// Authentication
    LA_AUTH = 0x00000008,
    /// IO operations (file system)
    LA_IO = 0x00000010,
    /// Network operations (relevant for debug and trace-levels)
    LA_NETWORK = 0x00000020,
    /// Threads (relevant for debug and trace-levels)
    LA_THREADS = 0x00000040,
    /// Inter process commnication (relevant for debug and trace-levels)
    LA_IPC = 0x00000080,
    /// Statistics updates
    LA_STATS = 0x00000100,
    /// Function called and left
    LA_FUNCTION_CALL = 0x00000200

WarLog allows you to log at different log-levels and context flags to different logs. A log may be the console, or it may be a file. You can add any number of logs with their own filters. When a log-message is processed, the message traverse trough each logger until all have seen it. There are global variables caching the lowest log-level used by any log. Messages logged at a lower level will be skipped at run-time.

Some examples