Jump to content
  • Advertisement
Sign in to follow this  
popsoftheyear

Logging - if not a singleton, what?

This topic is 3989 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

Ok, so what exactly is a good, low bug-potential, safe way, to create a logger? I've seen opinions about singletons being ok because "they fit the criteria" and really really bad for other reasons that never seem to stick around in my head because I'm really focused on other things and I suppose they have never come back to haunt me yet (well I haven't really ever used them). Thanks. Cheers -Scott

Share this post


Link to post
Share on other sites
Advertisement
It depends on your exact requirements, but a global variable generally works well. Note that C++'s built-in logger is a global variable. Note also that a logger does NOT fit the criteria for a singleton: It is not logically impossible for one to create multiple loggers (in fact, people tend to do it a lot).

Share this post


Link to post
Share on other sites
Globals are OK, even though the fact a singleton is a global is often an argument levied against the singleton pattern (really, the argument is that a singleton is no better than a global.)

That said, there are a few alternate approaches.

One is to simply create a logger class which can be instantiated at an appropriate scope, for example, a texture cache has a logger, the renderer has another logger. Each can open their own file. In some cases, the logger might be better off as a static class member, for example, when many of that class will exist and need access to logging facilities (for example if your enemy class required logging.)

If you want all logging to go to a single file, you can implement the logger classes with an internal, private static member which owns and is responsible for the log file. In this case, the logger classes essentially present an interface into the single, internal logging system. This is probably the only real way to have a single file without polluting the global namespace.

If your application supports multi-threading, you will have to add the appropriate measures to the internal logging system, but at least its confined to one place.

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001
One is to simply create a logger class which can be instantiated at an appropriate scope, for example, a texture cache has a logger, the renderer has another logger. Each can open their own file. In some cases, the logger might be better off as a static class member, for example, when many of that class will exist and need access to logging facilities (for example if your enemy class required logging.)
It's a fine approach, but that particular reasoning is flawed. It's the tail wagging the dog. First decide whether you want one file or a lot of files, then figure out how to implement it. Don't tailor your feature set to your architectural choices. It eats at the programmer's soul.
Quote:
If you want all logging to go to a single file, you can implement the logger classes with an internal, private static member which owns and is responsible for the log file. In this case, the logger classes essentially present an interface into the single, internal logging system. This is probably the only real way to have a single file without polluting the global namespace.
a.k.a. a scoped global. Really, namespace pollution is something of a bugaboo. If you feel like it, put the logger class in an anonymous namespace and the logger variable in global scope. Presto: exactly as much namespace pollution as having the class global and the variables local.

Share this post


Link to post
Share on other sites
Quote:
If you want all logging to go to a single file, you can implement the logger classes with an internal, private static member which owns and is responsible for the log file. In this case, the logger classes essentially present an interface into the single, internal logging system. This is probably the only real way to have a single file without polluting the global namespace.


This looks close enough to some singleton implementations.

A related architecture would be to have segmented isolated log dumps. That is, each "loggable" class would log to its own logger along with its time stamp and scope ID.

When you want to generate the final log, your logger simply scans all the sources and aggregates the log results that match your query (eg. like keeping log entries for a specific time frame only, or a selection of scope ID's). Obviously you'll only need to do this when you're just about to write the log file (or present it to the user).

One way to implement this scheme is to add the logging functionality to your "source" classes's base, or define a new ILogger interface.

Share this post


Link to post
Share on other sites
My logger (not a singleton, but could be kept in one or just as a global variable) just keeps track of logs (actually, they are log dispatchers), log targets (the actual loggers) and a default log (which, by default, will buffer all its messages and log them to the new default log, once it has been replaced, should one choose to do so).
Log (log dispatchers) are just log holders - they dispatch the messages, they are supposed to log, to their log targets (if they have any assigned, that is).
Log targets - they can log to anything, anywhere (files, consoles, whatever - the user can register new log target types) and can be shared among multiple logs (since the logger itself owns both logs and log targets and only hands out weak pointers).
Every subsystem may have a log attached (no logs are attached by default, meaning that the user decides, who, where, when and what is logged) - log targets makes it possible to subsystems logging to multiple targets (or even multiple logs).
Log messages are just standard text + source + type objects (where both logs and log targets will only log/dispatch log messages relevant to their specified logging level).

It sounds a bit complex, but IMO it is actually quite simple to utilize and gives me the opportunity to decide the logging process very detailed without much effort. I just wanted a little bit more from my logger :)

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!