Some things that are missing (at least from the docs):
- multithreaded logging (show thread ID with each line)
- nesting (e.g. indent logged lines when entering a scope)
- logging of values other than strings (mentioned already)
- storing the results in a separate file (rather than outputting to stderr)
Also, the documentation is too terse. And, what is that lambda symbol doing in the output?
This code also constructs a std::string each time you do some logging.
Really, you need to be using a #define to call the logging function, one that goes a bit like this. You invoke it like printf. (I know some people hate printf, but I like it. Anyway, that's addressed below.)
Then you use it, like, ``LOG(MyLog, "Hello: %d\n", n)''. You need another macro to generate the LogData_XXX variables with the right name and so on.
There are two advantages to doing it like this.
Firstly, the cost is minimal if the logging is disabled. This isn't so much to avoid the call to PrintToLog - though that doesn't hurt! - as PrintToLog would surely check the flag itself and early out at little cost. It's more to avoid having to evaluate the printf args. Say you're printing out 3 things, and each thing requires a function call - along the lines of ``PrintToLog("%d %d %d",f0(),f1(),f2())'' - then calling PrintToLog requires those 3 function calls to be made before PrintToLog is entered, even when the log is disabled. No good, especially if they're expensive.
The second - and one reason I've always done this printf-style rather than iostreams, though maybe iostreams-style would be doable, if you didn't mind some slightly funny syntax - is that you can strip all the debugging out with an alternative #define:
#define LOG(...) ((void)0)
This gets rid of everything, code and string literals. If your product won't have anywhere to put debug logs when it's running in the wild, or you're short on code/data space, or you just want to strip out certain types of message (you might have a VLOG for verbose debugging, for example, that doesn't want to be in the final product), then you can do that.
This particular package suffers from both problems, I think, as (based on a quick skim of the code) does the Google one mentioned elsewhere.
8 comments
[ 3.1 ms ] story [ 32.2 ms ] threadhttps://google-glog.googlecode.com/svn/trunk/doc/glog.html
Hipsterish $PS1
Really, you need to be using a #define to call the logging function, one that goes a bit like this. You invoke it like printf. (I know some people hate printf, but I like it. Anyway, that's addressed below.)
Then you use it, like, ``LOG(MyLog, "Hello: %d\n", n)''. You need another macro to generate the LogData_XXX variables with the right name and so on.There are two advantages to doing it like this.
Firstly, the cost is minimal if the logging is disabled. This isn't so much to avoid the call to PrintToLog - though that doesn't hurt! - as PrintToLog would surely check the flag itself and early out at little cost. It's more to avoid having to evaluate the printf args. Say you're printing out 3 things, and each thing requires a function call - along the lines of ``PrintToLog("%d %d %d",f0(),f1(),f2())'' - then calling PrintToLog requires those 3 function calls to be made before PrintToLog is entered, even when the log is disabled. No good, especially if they're expensive.
The second - and one reason I've always done this printf-style rather than iostreams, though maybe iostreams-style would be doable, if you didn't mind some slightly funny syntax - is that you can strip all the debugging out with an alternative #define:
This gets rid of everything, code and string literals. If your product won't have anywhere to put debug logs when it's running in the wild, or you're short on code/data space, or you just want to strip out certain types of message (you might have a VLOG for verbose debugging, for example, that doesn't want to be in the final product), then you can do that.This particular package suffers from both problems, I think, as (based on a quick skim of the code) does the Google one mentioned elsewhere.