OnixS C++ CME MDP Conflated UDP Handler  1.1.2
API documentation
Logging Services

Logger Abstraction

The logging services have been advanced in the SDK starting with this major release. Now it exposes abstraction of logging services defining the way for users to bring custom solutions more suitable for their purposes.

Logger abstraction is based on two primary classes:

The OnixS::CME::ConflatedUDP::Logger defines an interface for adding entries to the logger. The OnixS::CME::ConflatedUDP::LogEntry in its turn defines an interface of the entry being added to a log.

The SDK contains a few utility classes like OnixS::CME::ConflatedUDP::LogEvent and its descendants to improve the experience with using logging services.

A typical use-case for the logger inside the Handler looks like following:

using namespace OnixS::CME::ConflatedUDP;
if (LogEntry* entry =
logger.addEntry(LogSeverity::Important))
{
LogWarning warning(*entry, warningSource);
static_cast<LogEvent&>(warning) << warningDescription;
}

Adding a new entry into a log is done by the OnixS::CME::MD3::Logger::addEntry member. It returns instance of OnixS::CME::ConflatedUDP::Entry which should be used to put information to be logged.

An important aspect of Logger abstraction is the fact Logger may return NULL instance of OnixS::CME::ConflatedUDP::LogEntry. That may happen if the information, which is added to a log, has lower severity than a logger configured with it. For example, an implementation may log only important events and thus regular and debug information is ignored. Therefore, when a caller of the OnixS::CME::ConflatedUDP::Logger::addEntry supplies a lower severity level, the member returns a NULL instance.

A valid (non-NULL) instance of the OnixS::CME::ConflatedUDP::LogEntry class it can be filled with any information. Once the entry is set up, information in it must be committed to the log by invoking the OnixS::CME::ConflatedUDP::LogEntry::commit member.

Note
An instance of OnixS::CME::ConflatedUDP::Logger successor can be bound to multiple instances of OnixS:CME::ConflatedUDP::Handler. Therefore, successors of the Logger abstraction must take into consideration the fact the OnixS::CME::ConflatedUDP::Logger::addEntry member can be invoked simultaneously.
Warning
It's up to the implementation to allow allocation of the new entries while another entry is in the process of fulfilling with data to be logged. However, the common rule while using a logger is to avoid adding multiple entries at the same time as other implementations may not allow that.
Logging issues should not affect market data processing and thus should be exposed through own way. For example, the OnixS::CME::ConflatedUDP::FileLogger can be associated with an instance of the OnixS::CME::ConflatedUDP::FileLoggerListener class upon the instance construction. In case of failure like the inability to log an event into a file, an issue is raised and delivered through the OnixS::CME::ConflatedUDP::FileLoggerListener::onFileLoggerIssue member.

Ready-to-use Logger Implementations

The SDK comes with a few ready-to-use implementations of the Logger abstractions allowing the users to build their solutions quickly:

Logger Implementation Description
OnixS::CME:MDH::FileLogger Implements logging services over text-based files. Logged data is stored into files which may be limited by size. Once volume reaches its limit, Logger detaches logged data, backs it up and starts a new volume.
OnixS::CME:MDH::NullLogger Logs nothings. The Handler suppresses logging at all, if the instance of given class is bound to it.

Binding Logger to the Handler

The Handler logs important aspects of its execution with the help of Logger abstraction explained above. Logging includes network data received and processed by the Handler, states of books and, of course, errors occurred at execution time.

The following example demonstrates how to configure and bind file-based logger to the Handler:

using namespace OnixS::CME::ConflatedUDP;
// Implementing logger listener to get notified on
// issues which are not raised through other ways.
struct FileLoggerIssueTracer
{
// Member is invoked when file logger experience
// issue solely beloning to logging subsystem.
void
onFileLoggerIssue(
const FileLogger& logger,
const Char* issue)
{
std::cout
<< "ALERT!!! "
"Issue occurred while logging data. "
<< issue
<< std::endl;
}
};
// Later, in code..
FileLoggerSettings loggerSettings;
loggerSettings.filename(makeLogFilename(handlerSettings.channel()));
FileLoggerIssueTracer loggerTracer;
FileLogger logger(loggerSettings, &loggerTracer);
// Now, setting up the Handler.
Handler handler;
handler.settings().channel(310);
handler.settings().feeds().connectivityConfigurationFile("config.xml");
handler.settings().logging().logger(&logger);