Sign in to follow this  

Logger ideas

This topic is 3862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I'm thinking about rewriting my cheap little logger class into a newer, stream-based logger. I know std::clog is all I need, but I want it to support multiple streams at a time, so, for example, I can be generating a log file, but at the same time, I may turn on logging in the in-game console, which would require the log entries being pumped into two streams. I was wondering if you guys could share some more ideas for really useful (but relatively lightweight) features on a logger geared towards gaming. I think something like what I describe should be sufficient though... Also, what's a good way to entirely compile out that stuff? Like suppose I have this in an inner loop:
someDebugLog << "Values are " << slightPerformanceHit(x) << " and "
             << otherSlightPerformanceHit(y) << endl;
Just turning off debug logging won't do me any good, because of the order of execution of the chained operator<<'s. I don't want to do some tacky macro that puts a comment there or something (plus that would be hard due to the multiline nature of it all anyway). I guess I could do something that would make my code look like:
logDebug(someDebugLog << .....);
But that's also kind of ugly-looking..... Ideas?

Share this post


Link to post
Share on other sites
How about log levels? The idea is to allow the creation of certain log
destinations to only listen to certain log levels.

For example:

LogLocation* pFile = new LogLocHTML ("MyLog.html");
pFile.SetThreshold (LOG_WARNING); // only output warnings/errors

LogSource lout;

lout << LogLevel (DEBUG) << "Hi" << std::endl; // will only output to DEBUG streams

lout << LogLevel (WARNING) << " *** Some error" << std::endl; //outputs to file

My log manager uses this approch[smile]


For compiling out, you can try using the preprocessor:

#ifdef DEBUG
lout << LogLevel (DEBUG) << "Hi" << std::endl; // will only output to DEBUG streams
#endif

#define DEBUG for debuig builds, #undef for release. In release builds, the
compilier will not see the above code. It will only compile if DEBUG is
defined.

Alot of compilier IDEs predefine NDEBUG for debug builds. You can use
this method instead, if you like.

Share this post


Link to post
Share on other sites
Oh yeah don't worry loglevels are kind of assumed to be in there, sorry, should have mentioned that (already had them in the old logger). That's kind of a given :D.

As for compiling out, having to put #ifdefs all over the code is precisely what I wanted to avoid. Though I guess if I rely on the loglevels, then I only really have to ifdef out the parts that really are in an inner loop... but that could be lots of them.

Share this post


Link to post
Share on other sites
Some time ago, I asked a very simular question (Looking for a way around
#ifdef/#endif everywhere)

Unfortanatly, its the only (Clean!) solution I could find right now.

Unless, anyone has suggestions?

Share this post


Link to post
Share on other sites
I'm not a big fan of log levels myself, but certain languages allow for cleaner conditional compilation sans ifdefs (C# for example).

I do like the idea of log decoration though. Quite useful.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
I do like the idea of log decoration though. Quite useful.


Hmm, can you elaborate on this? Are you talking about implementing such things as log levels and timestamps in the form of decorators around a very simple basic log system?

Share this post


Link to post
Share on other sites

#if !defined(NDEBUG)
#define someDebugLog MyActualLoggingClassInstance
#else
#define someDebugLog MyNullLoggingClassInstance
#endif


class MyNullLoggingClassInstance : public std::ostream
{
public:
template <typename T>
MyNullLoggingClassInstance& operator << (T&)
{
// Do nothing, compiler will hopefully optimise it all away
return *this;
}
};




Treat this as untested pseudo-code...

Share this post


Link to post
Share on other sites
Unfortunately that probably won't do what the OP wants. It will suppress output but slightPerformanceHit and otherSlightPerformanceHit would still have to be called unless the compiler can prove to itself that those functions have no side effects.

Share this post


Link to post
Share on other sites
Quote:
Original post by Replicon
Quote:
Original post by Telastyn
I do like the idea of log decoration though. Quite useful.


Hmm, can you elaborate on this? Are you talking about implementing such things as log levels and timestamps in the form of decorators around a very simple basic log system?


Timestamps, linenumbers, current memory usage, synchronization primitives, stuff like your log 'fork'... all of which work off a common interface and end with non-decorators like 'dump to file $x', 'dump to console', 'dump to /dev/null', etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anon Mike
Unfortunately that probably won't do what the OP wants. It will suppress output but slightPerformanceHit and otherSlightPerformanceHit would still have to be called unless the compiler can prove to itself that those functions have no side effects.


Yeah, that's kind of what I was getting at. Maybe there's a way to cause short-circuiting behaviour with operator<<? But I think the order of evaluation of a '<<' chain (extractor chain?) is either undefined, or highly dependant on what goes into it.

Share this post


Link to post
Share on other sites
Sign in to follow this