Click here to Skip to main content
15,867,835 members
Articles / Programming Languages / C++

Minimalist Logger

Rate me:
Please Sign up or sign in to vote.
4.76/5 (15 votes)
10 May 2009CPOL3 min read 68.9K   2K   58   32
A single header cross-platform thread-safe logging facility

Introduction

It's simple to use implementation of cross-platform and thread-safe logging facility.

Background

Logging is a fundamental technique in programming. Sometimes it's the single available diagnostic tool. No surprise there're a lot of different logging libraries. They provide logging to different kind of targets most of them you never heard about, dozens of log categories (like "warning", "serious warning", "almost error", "critical error", "the end of the Earth"), comprehensive configurations and output formats, vertical takeoff (I'm sure I remember one such log-library), etc. And I'm sure there're projects that really need all those features. Who doesn't need them writes their own logging.

One day when I decided to throw out one of those comprehensive log-libraries (because it had a 4 pages feature list but was not thread-safe), I tried to write a simple logger and had the following requirements for it:

  • Logging to log-file and to console (if present)
  • Logging errors, ordinal log-messages and debug messages (with the ability to turn off not-important category)
  • Simplicity: single header only
  • Usability: printf()-like formatting and ability to automatically put function name (or class_name::function_name) to beginning of log-message
  • Logging should be thread-safe
  • Library should work fine under Windows and Linux (not tested under MacOS but don't see any reason why it shouldn't work there)
  • Logging should be as efficient as possible and I need to be able to turn it off

It's already the second version of the library, with some improvements and additions. Further development is planned too, e.g. the next version will include log-message format configuration. If you see how this library can be improved or if you need a not-implemented feature - don't hesitate to write in the comments below.

Using the Code

You need to include "logger.h" to your sources (precompiled header is the most appropriate place for this), set filename of log output and log, log, log. :) This looks like:

C++
#include "logger.h"

int main()
{
	logging::set_output("filename.log");
	logging::set_minimal_category(logging::cat_info); 	// to filter out 
							// debug messages

	log_error("to log w/o logging place info, uses %s format", "printf()");
	LOG("to log with function name and with single %s", "argument");
	log_debug("debug message shouldn't appear because of category filter");

    return 0;
} 

Output looks like:

08:30:20:609  3412 ERROR: to log w/o logging place info, uses printf() format
08:30:20:609  3412 info: main: to log with function name and with single argument
08:30:20:625  3412 info: main: this long log message should be truncated 
				because of too short buf

Format is:

HH:MM:SS:FFF thread_id log_category: optional_function_name: log-message

Macros LOG, LOG_ERROR and LOG_DEBUG put the function name where logging occurred.

To turn off logging, define LOGGING_DISABLED before including "logger.h".

BTW, these macros are very useful, e.g. if you have a function...

C++
void DoSomething(ID item_id) 

... you can log it like...

C++
LOG("id = %d", item_id)

It's enough because the function name will be added automatically.

By default log-message formatting buffer is 4096 chars long that should be enough in most cases. But you can change this using logging::set_buffer_size(size_t new_size).

Points of Interest

To provide portability, I used Boost. If you still don't use Boost Libraries, it's good chance to start, they will "boost" your C++ programming performance.

Efficiency is provided by optimizing memory allocation for output formatting and by lock-free output buffer synchronization - keeping it in thread local storage. printf() formatting style instead of modern and much more robust boost::format was chosen also for better performance.

Acknowledgements

I would like to thank my friend Sviatoslav Danyliv (aka Dans.Lviv.Ua) and all guys who commented on this library, for their help.

History

  • 28th April, 2009: Initial post
  • 9th May, 2009: Version 2.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Ukraine Ukraine
12 years of professional programming and IT enterprise
C++, Python
multithreading, networking, multimedia streaming/coding/playback, VoIP, client/server, MMO game server cluster
co-founder of IM-History
freelancer on RentACoder

Comments and Discussions

 
BugNot thread-safe Pin
Member 861516929-Aug-16 0:16
Member 861516929-Aug-16 0:16 
QuestionGreat work! But I have 2 simple questions Pin
Scarlettlee4-Apr-13 1:01
professionalScarlettlee4-Apr-13 1:01 
Hello, I'm Scarlett. I have to say that I really like your work.

However, I have 2 questions:
1. How can I produce a log file every day, which can be named by Date, rather than write all events in a unique file?

2. How to make the code more suitable in such case:
C++
CString cs = "mmm";
LOG("to log with function name and with CString %s variable", cs);

When I test this code:
//08:30:20:609  3412 info: main: to log with function name and with CString m variable

Only one "m" is printed. Especially, when I give "cs" a value of chinese characters, what I get for "%s" is messy code.
I can solve this problem in this way:
C++
std::string stemp = CT2CA(cs); //a transitional code
LOG("to log with function name and with CString variable %s", stemp.c_str());

But I don't want to add the transitional code every time I want to use "Log". Is there any way to modify the Logger.h to solve my problem?
GeneralMy vote of 5 Pin
studleylee23-Jan-13 15:38
studleylee23-Jan-13 15:38 
QuestionDoes not compile Pin
Michael Markov14-Nov-12 1:45
Michael Markov14-Nov-12 1:45 
Questionhow could I limit the size of log file to avoid increasing the file size more and more Pin
Member 90179457-Nov-12 3:48
Member 90179457-Nov-12 3:48 
Questionerror C3083: 'detail': the symbol to the left of a '::' must be a type Pin
jimmy_knj5-Sep-12 16:33
jimmy_knj5-Sep-12 16:33 
AnswerRe: error C3083: 'detail': the symbol to the left of a '::' must be a type Pin
Member 967258010-Dec-12 4:54
Member 967258010-Dec-12 4:54 
GeneralMy vote of 5 Pin
evenkeel27-Aug-12 16:48
evenkeel27-Aug-12 16:48 
GeneralMy vote of 5 Pin
Liquinaut26-Oct-11 4:22
Liquinaut26-Oct-11 4:22 
QuestionSimple problem. Pin
ahandke6-Jul-09 2:37
ahandke6-Jul-09 2:37 
AnswerRe: Simple problem. Pin
Andriy Tylychko6-Jul-09 5:32
Andriy Tylychko6-Jul-09 5:32 
AnswerRe: Simple problem. Pin
ahandke6-Jul-09 23:06
ahandke6-Jul-09 23:06 
Generalok Pin
Donsw13-Jun-09 5:45
Donsw13-Jun-09 5:45 
GeneralSome adds-on Pin
Ruaudel13-May-09 2:23
Ruaudel13-May-09 2:23 
GeneralRe: Some adds-on Pin
Andriy Tylychko13-May-09 2:55
Andriy Tylychko13-May-09 2:55 
GeneralRe: Some adds-on Pin
x-trailer10-Jun-09 21:44
x-trailer10-Jun-09 21:44 
GeneralRe: Some adds-on Pin
Andriy Tylychko10-Jun-09 22:12
Andriy Tylychko10-Jun-09 22:12 
GeneralLogging library Pin
Rob Koll5-May-09 8:05
Rob Koll5-May-09 8:05 
GeneralRe: Logging library Pin
Andriy Tylychko5-May-09 20:21
Andriy Tylychko5-May-09 20:21 
Generalnice but... Pin
agovorovsky5-May-09 3:20
agovorovsky5-May-09 3:20 
GeneralRe: nice but... Pin
Andriy Tylychko5-May-09 6:01
Andriy Tylychko5-May-09 6:01 
GeneralRe: nice but... Pin
agovorovsky6-May-09 21:56
agovorovsky6-May-09 21:56 
GeneralRe: nice but... Pin
Andriy Tylychko6-May-09 22:06
Andriy Tylychko6-May-09 22:06 
GeneralRe: nice but... Pin
agovorovsky6-May-09 22:18
agovorovsky6-May-09 22:18 
GeneralRe: nice but... Pin
Andriy Tylychko7-May-09 4:38
Andriy Tylychko7-May-09 4:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.