Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion AcceptanceTest/cfg/at_40.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store

[SESSION]
# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.0
DataDictionary=spec\fix\FIX40.xml
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_41.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.1
DataDictionary=spec\fix\FIX41.xml
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_42.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.2
DataDictionary=spec\fix\FIX42.xml
4 changes: 4 additions & 0 deletions AcceptanceTest/cfg/at_42.misc.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ FileStorePath=store
EnableLastMsgSeqNumProcessed=Y
MaxMessagesInResendRequest=2500
SendLogoutBeforeDisconnectFromTimeout=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.2
DataDictionary=spec\fix\FIX42.xml
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_43.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.3
DataDictionary=spec\fix\FIX43.xml
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_44.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.4
DataDictionary=spec\fix\FIX44.xml
3 changes: 3 additions & 0 deletions AcceptanceTest/cfg/at_44_enhancedresend.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

# All these settings needed for EnhancedResend
# See README-EnhancedResend.md for details
RequiresOrigSendingTime=N
Expand Down
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_44_noreset.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=N
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.4
DataDictionary=spec\fix\FIX44.xml
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_50.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIXT.1.1
DefaultApplVerID=FIX.5.0
Expand Down
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_50_sp1.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIXT.1.1
DefaultApplVerID=FIX.5.0SP1
Expand Down
6 changes: 5 additions & 1 deletion AcceptanceTest/cfg/at_50_sp2.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ EndTime=00:00:00
SenderCompID=ISLD
TargetCompID=TW
ResetOnLogon=Y
FileStorePath=store
FileStorePath=store

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIXT.1.1
DefaultApplVerID=FIX.5.0SP2
Expand Down
3 changes: 3 additions & 0 deletions Examples/Executor/executor.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ ScreenLogShowIncoming=Y
ScreenLogShowOutgoing=Y
ScreenLogShowEvents=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.0
SenderCompID=EXECUTOR
Expand Down
2 changes: 2 additions & 0 deletions Examples/Executor/executor_ssl.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ScreenLogShowIncoming=Y
ScreenLogShowOutgoing=Y
ScreenLogShowEvents=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

SSLEnable=Y
# It is recommended to install the certificate and refer to it by name instead of using filename + password
Expand Down
3 changes: 3 additions & 0 deletions Examples/SimpleAcceptor/simpleacc.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.0
SenderCompID=SIMPLE
Expand Down
3 changes: 3 additions & 0 deletions Examples/SimpleAcceptor/simpleacc_ssl.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ SSLCertificatePassword=QuickFixn-TestServer
SSLCACertificate=QuickFixn-TestCA.cer
SSLCheckCertificateRevocation=N

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.0
SenderCompID=SIMPLE
Expand Down
3 changes: 3 additions & 0 deletions Examples/Standalone/SerilogLog/Serilog.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ LogoutTimeout=5
ResetOnLogon=Y
HeartBtInt=10

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

[SESSION]
BeginString=FIX.4.0
SenderCompID=CLIENT1
Expand Down
3 changes: 3 additions & 0 deletions Examples/TradeClient/tradeclient.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ SocketConnectPort=5001
SocketIgnoreProxy=Y
ResetOnDisconnect=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

FileLogPath=log
ScreenLogShowIncoming=Y
ScreenLogShowOutgoing=Y
Expand Down
3 changes: 3 additions & 0 deletions Examples/TradeClient/tradeclient_ssl.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ SocketConnectHost=127.0.0.1
SocketConnectPort=5001
SSLEnable=Y

# In message logs, replace non-visible SOH with this character
FieldSeparatorInMessageLogs=|

FileLogPath=log
ScreenLogShowIncoming=Y
ScreenLogShowOutgoing=Y
Expand Down
8 changes: 5 additions & 3 deletions QuickFIXn/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ public TimePrecision TimeStampPrecision
public int[] RedactFieldsInLogs { get; set; } = [];
public string RedactionLogText { get; set; } = "<redacted>";

public char FieldSeparatorInMessageLogs { get; set; } = Message.SOH;

#endregion

internal Session(
Expand Down Expand Up @@ -375,7 +377,7 @@ public bool Send(string message)
}))
{
Log.Log(MessagesLogLevel, LogEventIds.OutgoingMessage, "{Message}",
LogAssist.RedactSensitiveFields(message, RedactFieldsInLogs, RedactionLogText));
LogAssist.PrepareFixMessageForLog(message, this));
}
}

Expand Down Expand Up @@ -549,13 +551,13 @@ private void NextMessage(string msgStr)
}))
{
Log.Log(MessagesLogLevel, LogEventIds.IncomingMessage, "{Message}",
LogAssist.RedactSensitiveFields(msgStr, RedactFieldsInLogs, RedactionLogText));
LogAssist.PrepareFixMessageForLog(msgStr, this));
}
}
} catch (Exception)
{
Log.Log(MessagesLogLevel, LogEventIds.IncomingMessage, "{Message}",
LogAssist.RedactSensitiveFields(msgStr, RedactFieldsInLogs, RedactionLogText));
LogAssist.PrepareFixMessageForLog(msgStr, this));
}

MessageBuilder msgBuilder = new MessageBuilder(
Expand Down
2 changes: 2 additions & 0 deletions QuickFIXn/SessionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ public Session Create(SessionID sessionId, SettingsDictionary settings)
session.RedactFieldsInLogs = settings.GetIntArray(SessionSettings.REDACT_FIELDS_IN_LOGS);
if (settings.Has(SessionSettings.REDACTION_LOG_TEXT))
session.RedactionLogText = settings.GetString(SessionSettings.REDACTION_LOG_TEXT);
if (settings.Has(SessionSettings.FIELD_SEPARATOR_IN_MESSAGE_LOGS))
session.FieldSeparatorInMessageLogs = settings.GetChar(SessionSettings.FIELD_SEPARATOR_IN_MESSAGE_LOGS);

return session;
}
Expand Down
1 change: 1 addition & 0 deletions QuickFIXn/SessionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public class SessionSettings
public const string CME_ENHANCED_RESEND = "CmeEnhancedResend";
public const string REDACT_FIELDS_IN_LOGS = "RedactFieldsInLogs";
public const string REDACTION_LOG_TEXT = "RedactionLogText";
public const string FIELD_SEPARATOR_IN_MESSAGE_LOGS = "FieldSeparatorInMessageLogs";

public const string SSL_ENABLE = "SSLEnable";
public const string SSL_SERVERNAME = "SSLServerName";
Expand Down
10 changes: 10 additions & 0 deletions QuickFIXn/SettingsDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ public String GetString(string key, bool capitalize)
return capitalize ? s.ToUpperInvariant() : s;
}

public char GetChar(string key)
{
string s = GetString(key);
if (string.IsNullOrEmpty(s))
throw new ConfigError($"Value is empty for key: {key}");
if (s.Length > 1)
throw new ConfigError($"Value is not a char for key: {key}");
return s[0];
}

public int GetInt(string key)
{
try
Expand Down
3 changes: 1 addition & 2 deletions QuickFIXn/SocketReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ private void OnMessageFound(string msg)
if (_qfSession.HasResponder)
{
_qfSession.Log.Log(LogLevel.Information, LogEventIds.IncomingMessage, "{Message}",
LogAssist.RedactSensitiveFields(
msg, _qfSession.RedactFieldsInLogs, _qfSession.RedactionLogText));
LogAssist.PrepareFixMessageForLog(msg, _qfSession));
_qfSession.Log.Log(LogLevel.Error,
"Multiple logons/connections for this session are not allowed ({Endpoint})",
_tcpClient.Client.RemoteEndPoint);
Expand Down
29 changes: 27 additions & 2 deletions QuickFIXn/Util/LogAssist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,34 @@

namespace QuickFix.Util;

public class LogAssist
internal class LogAssist
{
public static string RedactSensitiveFields(string msg, int[] tagsToRedact, string redactionText = "<redacted>")
internal static string PrepareFixMessageForLog(string msg, Session sesh)
{
if (string.IsNullOrEmpty(msg) || string.IsNullOrEmpty(msg))
return msg;
if (sesh.RedactFieldsInLogs.Length > 0)
msg = RedactSensitiveFields(msg, sesh.RedactFieldsInLogs, sesh.RedactionLogText);
msg = SwapFieldSeparator(msg, sesh.FieldSeparatorInMessageLogs);

return msg;
}

internal static string SwapFieldSeparator(string msg, char newSeparator)
{
if (newSeparator == Message.SOH)
return msg;
return msg.Replace(Message.SOH, newSeparator);
}

/// <summary>
/// Don't call this after SwapFieldSeparator!
/// </summary>
/// <param name="msg"></param>
/// <param name="tagsToRedact"></param>
/// <param name="redactionText"></param>
/// <returns></returns>
internal static string RedactSensitiveFields(string msg, int[] tagsToRedact, string redactionText = "<redacted>")
{
// This long text processor is much faster than Regex.
// Since this is used on every message log, it needs to be fast.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ To run a specific suite, use ``--filter``, e.g.
* `dotnet test --filter Fix44Test AcceptanceTest`
(`Fix44Test` is the `TestCaseSource` function in Fix44.cs)

AcceptanceTest logs are output to `bin/Debug/net8.0/log`.
AcceptanceTest logs are output to `bin/Debug/net<NN>/log`.


Credits
Expand Down
4 changes: 2 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ What's New
* **There are breaking changes between 1.10 and 1.11! Please review the 1.11.0 notes below.**


### v1.15.0
### upcoming for v1.15.0
* #1021 - remove .NET 8 support; remove expired deprecations (gbirchmeier)
* #1015 - rework DateOnlyField/TimeOnlyField to be backed by DateOnly/TimeOnly types instead of DateTime (gbirchmeier)

* #1023 - new config setting "FieldSeparatorInMessageLogs" (gbirchmeier)


### v1.14.1
Expand Down
11 changes: 7 additions & 4 deletions UnitTests/SessionTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ public void BaseSetup()
var logFactory = new LogFactoryAdapter(new NullLogFactory());

// acceptor
_session = new QuickFix.Session(false, _application, new MemoryStoreFactory(), _sessionId,
new QuickFix.DataDictionaryProvider(),new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah");
_session = new QuickFix.Session(false, _application, new MemoryStoreFactory(),
_sessionId, new QuickFix.DataDictionaryProvider(),new QuickFix.SessionSchedule(_config),
0, logFactory, new QuickFix.DefaultMessageFactory(), "blah");
_session.SetResponder(_responder);
_session.CheckLatency = false;

// initiator
_session2 = new QuickFix.Session(true, _application, new MemoryStoreFactory(), new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"),
new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah");
_session2 = new QuickFix.Session(true, _application, new MemoryStoreFactory(),
new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"),
new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config),
0, logFactory, new QuickFix.DefaultMessageFactory(), "blah");
_session2.SetResponder(_responder);
_session2.CheckLatency = false;

Expand Down
Loading
Loading