
Hi, Why not do something like my_log("this_module_logging_flag_notes") << "Doing something in this_module"; my_log("that_module_logging_flag_errors") << "Something went wrong in that_module"; where a log object is either (depending on a compile time setting) a proxy for a stream or a not_logger than has template <class OUTPUT_THINGGY> not_logger &operator<<(const OUTPUT_THINGGY &o) { return *this; } so when logging is compiled off, the statement evaluates to no code. And where "this_module_logging_flag_notes" is a key to a std::map<std::string, bool> that tells you whether logging is on for that key or not. You'd probably still need a macro for log so you could get a file and line number, though. What would be REALLY nice would be if C++ had a built in stack tracing facility. In the past I've written a tracing library to keep track of the stack (and turn tracing and logging on and off above and below particular functions) and I once found 68000 stack tracing assembler for the old mac os, which was really nice. I should really get around to implementing something like that again... cheers, Geoff On 19/03/2004, at 6:32 PM, John Torjo wrote:
I think it's the wrong approach. In our company we have implemented logging through macros which has one very important property: When I write
LOG_DEBUG( whatever() );
into my source, then whatever() is only evaluated when the debug-logger is active. The macro basically expands to something like this:
if( Base::hasLogger( LogLevel::DEBUG ) ) Base::log( whatever(), LogLevel::DEBUG );
I think this cannot be done without macros as normal function calls (including operator<< for streams) need to evaluate their arguments before they are called. As the difference in the application execution speed can vary by a factor of 1000, this is a very valuable optimization for us. My 2ยข.
Man, you must be doing a LOT of logging ;) I do quite a lot of logging myself, but I've never needed anything like above.
Anyway, in my code I have functions, which return a log_stream (a thread-safe wrapper over a stream).
And use it like this:
activity_log() << "My app. started at" << time(0) << std::endl; error_log() << "should have not arrived here" << std::endl; // etc.
And if I truly want, I can implement an operator bool(), and be able to disable it at runtime, like this:
if (activity_log()) activity_log() << ...;
Best, John