logog
logger optimized for games
Internal architecture

The logog system uses a publisher-subscriber model in order to handle message flow from source to destination. While the higher-level class architecture takes care of typical message routing, the standard message flow can be changed to support advanced logging models.

A key base class is the Topic class. Topics contain strings and numeric information representing a file name, line number, a free-form group name, a free-form category name, and a free-form message string. Topics know how to transmit and receive themselves to and from other topics, but they don't know how to discover those other topics. They do know how to negotiate with another topic in order to discover whether they should subscribe to that other topic – see Topic::CanSubscribeCheckTopic() for details. Topics implement the core functionality of subscribing and publishing. Topics can subscribe to multiple other topics, and they can publish to multiple other topics.

Some Topic behavior, especially the subscriber-publisher behavior and cross-thread locking, is subsumed into the Node class. Nodes should generally not be instanced by themselves, as they are not sufficiently functional to be useful.

Topics are subclassed into TopicSource and TopicSink classes. TopicSources can only publish, and TopicSinks can only subscribe.

A Target is a TopicSink that is capable of rendering its subscriptions to a logical output device. Targets include the Cout, Cerr, and the OutputDebug classes. To make logog send output to some arbitrary new destination, create a new Target subclass and override the Target::Output() method, and instance a new element of your class at the top of your program.

A Filter is a Topic that functions basically as a subscriber and a publisher. It's used to limit the scope of incoming messages to a particular type, group, or category. For example, a Filter may be used to permit only messages with a level of LOGOG_LEVEL_WARN or higher to be logged. Other messages are dropped. By default a filter will attempt to subscribe itself to all existing Targets; however, this behavior may be changed by overriding the Initialize() method within your Target subclass, or by manually calling Target::Unpublish() on each Target that you want the Filter to not publish to.

This design permits more advanced logging models. For example, it's possible to have two Filters, one which filters for error messages and logs those to the console, versus informational and warning messages, which are logged to a file. Note that the routing of any of the higher-level classes such as Filter or Output by simply instantiating a Topic and manually calling PublishTo() and SubscribeTo() to the desired inputs and outputs.

A Message is a sub-sub-class of TopicSource that knows how to publish itself automatically to any outstanding Filter objects. A program will typically instance a set of static Message objects and use them to indicate execution of a certain point in the program.

String types receive their own custom class. Since logog spends a lot of time shuffling strings from class to class, this permits string copies to be fast constant-time operations (a copy of pointers).

All statically allocated elements are stored inside the Statics class. This permits all items to be tracked and freed, thus assuring no memory leaks.

In order to support cross-platform, multithread-safe support, logog implements a Thread class, a Timer class, and a Mutex class. These of course can be customized to support future platforms.