Best way to implement a logging feature

Started by
5 comments, last by joanusdmentia 17 years ago
I currently have 5 subsytems like input.cpp, system.cpp, sound.cpp etc Id like to implement a logging feature for all of them, but all of the subsytems need to use it. Iv tried to make a class with ofstream, but found it hard to let all the other instances use the same stream sigh this is annoying me now, please help me!
Advertisement
You might want to look into the "singleton pattern". I use it for the log manager in my game. Basically, it restricts a certain class to having at most one instantiation. Sometimes people overuse singletons, but for a LogManager, one instance is all you would ever want. So when I need to log a message, I just call LogManager::instance().log("blah") and it deals with the stream internally, and I can log messages from any part of my game that I need to without passing around a stream object.
Why dont you just pass a pointer to the same ofstream, found in the parent class of all of them, to each ones constructor?
I use a global instance of a small logging class for every log file I want. Don't know if that's the "best" or "cleanest" way, but it's very simple and works.
Please do not use a singleton (google will provide many reasons).

Personally, I tend to use the strategy pattern (akin to Crazyfool's suggestion) if doing anything moderately complex. Otherwise std::cerr is sufficient.
<IMHO>

While I'm not big on singletons generally, passing around a pointer to all classes that may possibly need to log something (ie. everything) is probably a bit overkill/fugly/annoying. :)

However, doing the whole Logger::instance().log("blah") is also pretty fugly, so what I'm doing for my logger is have a global instance (*gasp*), rather than using a singleton (which is just a global in fancy dress anyway). In fact, I have several instances, one for each level of "severity".

</IMHO>

Here's an example of what I do:

in Log.h:namespace Log {class Logger { }extern Logger Normal;extern Logger Warning;extern Logger Error;extern Logger Debug;}in Log.cppLogger Normal(kSeverity_Normal);Logger Warning(kSeverity_Warning);etc...


My Logger class overloads << (using ostringstream internally) so i can just do:

Log::Normal << "Level of pie: " << pieLevel << Log::End;


It's probably worth pointing out that the Logger class is pretty much a stub class that's pretty empty of functionality besides the stream operator. Once Log::End is streamed in, the Logger class calls a callback that was setup by the application on startup. It's up to the application to log to file, print to game console, etc.

Okay, I better stop rambling and get back to work. Hope this helps :)

- Thomas Cowellwebsite | journal | engine video

Personally I use a singleton for my logger (it's one of the few places where I feel the singleton pattern actually has a use), along with a helper macro for working with it:

extern Singleton<Logger> g_logger;#define LOG(level) g_logger::get().startEntry(level, __FILE__, __LINE__)void func(){    LOG(WARNING) << "This is warning number " << 5;}int main(){    g_logger::get().open("app.log");    g_logger::get().set_formatter(new LogFormatterXML);    func();}


The Logger::startEntry() function returns a helper object that acts as a std::stringstream, and on destruction of the helper outputs the complete log entry (the format of which is determined by a LogFormatter object) to the log file.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The only verdict is vengeance; a vendetta held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous. Verily, this vichyssoise of verbiage veers most verbose, so let me simply add that it's my very good honor to meet you and you may call me V.".....V

This topic is closed to new replies.

Advertisement