Documentation for QuickFIX/n

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: not QuickFix.SessionLogs.*
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.