New in v1.14: Logging via the .NET ILogger API
Version 1.14 introduced support for logging via the .NET ILogger API.
QuickFIX/n now has constructors for
SocketInitiator
and
ThreadedSocketAcceptor
that take a paramater of type
Microsoft.Extensions.Logging.ILoggerFactory.
(The existing constructors that take QuickFix.Logger.ILogFactory are still present
and will be supported for the foreseeable future.)
We do not yet offer any built-in implementations of ILoggerFactory,
but this change offers developers the option of using
any existing logging frameworks that support this interface.
Note:
This change adds the NuGet dependency
Microsoft.Extensions.Logging.Abstractions
to QuickFIX/n.
Let's Get Our Terms Straight
Unfortunately, the terminology between the legacy QuickFIX/n logging framework and this new framework is similar, so let's make sure nobody's confused:
| New Logging Framework | Legacy QF/n Logging Framework | |
|---|---|---|
| namespace |
Microsoft.Extensions.Logging
|
QuickFIX.Logger
|
| factory interface |
ILoggerFactory
|
ILogFactory
|
| logger interface |
ILogger
|
ILog
|
What Can I Do With This?
Instead of being limited to the pre-v1.14 built-in loggers or your own custom implementations, you can now use any logger implementation that supports the .NET ILogger API.
Simple example with Microsoft's Console Logger
Here is a simple example that demonstrates creating an acceptor using Microsoft's
Console logger:
(This is taken from the
Executor example application)
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConsole();
});
ThreadedSocketAcceptor acceptor =
new ThreadedSocketAcceptor(executorApp, storeFactory, settings, loggerFactory);
Note: Unfortunately, Microsoft does not provide an implementation for a file logger.
Example App That Uses the Serilog Logging Library
Serilog is one logging library that supports the .NET ILogger API.
See the SerilogLog example app. It demonstrates usage of a few features that the legacy QF/n loggers don't offer.
(This example is not intended to be an explicit endorsement of Serilog over any competitor.)
Implementation Notes
Distinguishing Different Categories of Logs
This section is vital if you are configuring your log filters or implementing your own logger.
QuickFIX/n has three different categories of logs, and certain log properties can be used to distinguish them:
| Log type | Description | Filter identifiers |
|---|---|---|
| Message logs | The raw FIX messages that are sent and received. |
Source:
QuickFix.SessionLogs.<session-id>
EventId: QuickFix.Logger.LogEventIds.IncomingMessage.Id (7702) or .OutgoingMessage.Id (7703) |
| Event logs |
Contextual information about things that happen
in a session |
Source:
QuickFix.SessionLogs.<session-id>
EventId: none |
| Non-session logs |
Unusual errors that cannot be attributed to any
specific session. |
Source:
EventId: none |
The SerilogLog example app demonstrates a log configuration that uses these identifiers to configure its filters. (This example is, of course, Serilog-specific, but should be illustrative enough that it can advice filter implementations with other logging frameworks.)
Log Levels
The new logging system introduces log levels to the engine's internal logging (as you would expect from any modern logging system).
For message logs:
All messages are logged at the Info level, no exceptions.
They are also logged with a scope "MessageType," set to the value of tag 35, if present.
For event logs:
For release v1.14, all existing log messages have been assigned log levels
Info, Warning, or Error as appropriate.
QuickFIX/n's event log has never been very “noisy,” so none of the logger calls were deemed
insignificant enough to count as Debug or Trace, nor was any
existing message deemed severe enough to be critical at this time.
Future releases may add new log events at any level.
Backward compatibility with Legacy Loggers
In v1.14, QuickFIX/n's logging implementation now uses the .NET Logger API internally.
However, the legacy logging interface is preserved so that everyone can
keep using ILogFactory-implementing classes such as
FileLogFactory, ScreenLogFactory, and the like.
If you wish to keep using the legacy logging factories, you should not see a significant change in your log outputs.