Skip to content

Commit

Permalink
Avoid boxing and delegate capture in StructuredData (#259 closes #268)
Browse files Browse the repository at this point in the history
 - Avoid boxing of enumerators (https://stackoverflow.com/questions/3168311) and delegate capture
 - Fix line ending issues

Co-authored-by: Luigi Berrettini <[email protected]>
  • Loading branch information
snakefoot and luigiberrettini authored Oct 19, 2020
1 parent 98b824d commit ccd1b7f
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 155 deletions.
18 changes: 18 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
* text=auto

*.md text eol=crlf

*.yml text eol=crlf
*.ps1 text eol=crlf
*.sh text eol=lf

*.sln text eol=crlf
*.csproj text eol=crlf
*.cs text eol=crlf
*.config text eol=crlf
*.json text eol=crlf
*.xsd text eol=crlf
*.txt text eol=crlf

*.png binary
*.snk binary
230 changes: 115 additions & 115 deletions src/NLog.Targets.Syslog/MessageCreation/Rfc5424.cs
Original file line number Diff line number Diff line change
@@ -1,116 +1,116 @@
// Licensed under the BSD license
// See the LICENSE file in the project root for more information

using System;
using NLog.Layouts;
using NLog.Targets.Syslog.Policies;
using System.Globalization;
using System.Text;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Settings;

namespace NLog.Targets.Syslog.MessageCreation
{
internal class Rfc5424 : MessageBuilder
{
private const string BaseTimestampFormat = "yyyy-MM-ddTHH:mm:ss";
private const int Iso8601MaxTimestampFractionalDigits = 16;
private const int DotNetDateTimeMaxFractionalDigits = 7;
private static readonly byte[] SpaceBytes = { 0x20 };

private readonly string version;
private readonly string timestampFormat;
private readonly Layout hostnameLayout;
private readonly Layout appNameLayout;
private readonly Layout procIdLayout;
private readonly Layout msgIdLayout;
private readonly StructuredData structuredData;
private readonly byte[] preamble;
private readonly FqdnHostnamePolicySet hostnamePolicySet;
private readonly AppNamePolicySet appNamePolicySet;
private readonly ProcIdPolicySet procIdPolicySet;
private readonly MsgIdPolicySet msgIdPolicySet;
private readonly Utf8MessagePolicy utf8MessagePolicy;

public Rfc5424(Facility facility, LogLevelSeverityConfig logLevelSeverityConfig, Rfc5424Config rfc5424Config, EnforcementConfig enforcementConfig) : base(facility, logLevelSeverityConfig, enforcementConfig)
{
version = rfc5424Config.Version;
timestampFormat = $"{{0:{TimestampFormat(rfc5424Config.TimestampFractionalDigits)}}}";
hostnameLayout = rfc5424Config.Hostname;
appNameLayout = rfc5424Config.AppName;
procIdLayout = rfc5424Config.ProcId;
msgIdLayout = rfc5424Config.MsgId;
structuredData = new StructuredData(rfc5424Config.StructuredData, enforcementConfig);
preamble = rfc5424Config.DisableBom ? new byte[0] : Encoding.UTF8.GetPreamble();
hostnamePolicySet = new FqdnHostnamePolicySet(enforcementConfig, rfc5424Config.DefaultHostname);
appNamePolicySet = new AppNamePolicySet(enforcementConfig, rfc5424Config.DefaultAppName);
procIdPolicySet = new ProcIdPolicySet(enforcementConfig);
msgIdPolicySet = new MsgIdPolicySet(enforcementConfig);
utf8MessagePolicy = new Utf8MessagePolicy(enforcementConfig);
}

protected override void PrepareMessage(ByteArray buffer, LogEventInfo logEvent, string pri, string logEntry)
{
AppendHeader(buffer, pri, logEvent);
buffer.AppendBytes(SpaceBytes);
AppendStructuredData(buffer, logEvent);
buffer.AppendBytes(SpaceBytes);
AppendMsg(buffer, logEntry);

utf8MessagePolicy.Apply(buffer);
}

private static StringBuilder TimestampFormat(int fractionalDigits)
{
// BaseTimestampFormat.Length + 1 decimal point + 1 K + Iso8601MaxTimestampFractionalDigits
var maxTimestampFormatLength = BaseTimestampFormat.Length + 2 + Iso8601MaxTimestampFractionalDigits;
var formatSb = new StringBuilder(BaseTimestampFormat, maxTimestampFormatLength);

if (fractionalDigits <= 0)
return formatSb.Append("K");

var fRepeatCount = Math.Min(fractionalDigits, DotNetDateTimeMaxFractionalDigits);
var requestedMinusDotNet = fractionalDigits - DotNetDateTimeMaxFractionalDigits;
const int isoMinusDotNet = Iso8601MaxTimestampFractionalDigits - DotNetDateTimeMaxFractionalDigits;
var zeroRepeatCount = Math.Max(0, Math.Min(requestedMinusDotNet, isoMinusDotNet));
return formatSb
.Append('.')
.Append('f', fRepeatCount)
.Append('0', Math.Max(0, zeroRepeatCount))
.Append("K");
}

private void AppendHeader(ByteArray buffer, string pri, LogEventInfo logEvent)
{
var timestamp = string.Format(CultureInfo.InvariantCulture, timestampFormat, logEvent.TimeStamp);
var hostname = hostnamePolicySet.Apply(hostnameLayout.Render(logEvent));
var appName = appNamePolicySet.Apply(appNameLayout.Render(logEvent));
var procId = procIdPolicySet.Apply(procIdLayout.Render(logEvent));
var msgId = msgIdPolicySet.Apply(msgIdLayout.Render(logEvent));

buffer.AppendAscii(pri);
buffer.AppendAscii(version);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(timestamp);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(hostname);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(appName);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(procId);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(msgId);
}

private void AppendStructuredData(ByteArray buffer, LogEventInfo logEvent)
{
structuredData.Append(buffer, logEvent);
}

private void AppendMsg(ByteArray buffer, string logEntry)
{
buffer.AppendBytes(preamble);
buffer.AppendUtf8(logEntry);
}
}
// Licensed under the BSD license
// See the LICENSE file in the project root for more information

using NLog.Layouts;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Policies;
using NLog.Targets.Syslog.Settings;
using System;
using System.Globalization;
using System.Text;

namespace NLog.Targets.Syslog.MessageCreation
{
internal class Rfc5424 : MessageBuilder
{
private const string BaseTimestampFormat = "yyyy-MM-ddTHH:mm:ss";
private const int Iso8601MaxTimestampFractionalDigits = 16;
private const int DotNetDateTimeMaxFractionalDigits = 7;
private static readonly byte[] SpaceBytes = { 0x20 };

private readonly string version;
private readonly string timestampFormat;
private readonly Layout hostnameLayout;
private readonly Layout appNameLayout;
private readonly Layout procIdLayout;
private readonly Layout msgIdLayout;
private readonly StructuredData structuredData;
private readonly byte[] preamble;
private readonly FqdnHostnamePolicySet hostnamePolicySet;
private readonly AppNamePolicySet appNamePolicySet;
private readonly ProcIdPolicySet procIdPolicySet;
private readonly MsgIdPolicySet msgIdPolicySet;
private readonly Utf8MessagePolicy utf8MessagePolicy;

public Rfc5424(Facility facility, LogLevelSeverityConfig logLevelSeverityConfig, Rfc5424Config rfc5424Config, EnforcementConfig enforcementConfig) : base(facility, logLevelSeverityConfig, enforcementConfig)
{
version = rfc5424Config.Version;
timestampFormat = $"{{0:{TimestampFormat(rfc5424Config.TimestampFractionalDigits)}}}";
hostnameLayout = rfc5424Config.Hostname;
appNameLayout = rfc5424Config.AppName;
procIdLayout = rfc5424Config.ProcId;
msgIdLayout = rfc5424Config.MsgId;
structuredData = new StructuredData(rfc5424Config.StructuredData, enforcementConfig);
preamble = rfc5424Config.DisableBom ? new byte[0] : Encoding.UTF8.GetPreamble();
hostnamePolicySet = new FqdnHostnamePolicySet(enforcementConfig, rfc5424Config.DefaultHostname);
appNamePolicySet = new AppNamePolicySet(enforcementConfig, rfc5424Config.DefaultAppName);
procIdPolicySet = new ProcIdPolicySet(enforcementConfig);
msgIdPolicySet = new MsgIdPolicySet(enforcementConfig);
utf8MessagePolicy = new Utf8MessagePolicy(enforcementConfig);
}

protected override void PrepareMessage(ByteArray buffer, LogEventInfo logEvent, string pri, string logEntry)
{
AppendHeader(buffer, pri, logEvent);
buffer.AppendBytes(SpaceBytes);
AppendStructuredData(buffer, logEvent);
buffer.AppendBytes(SpaceBytes);
AppendMsg(buffer, logEntry);

utf8MessagePolicy.Apply(buffer);
}

private static StringBuilder TimestampFormat(int fractionalDigits)
{
// BaseTimestampFormat.Length + 1 decimal point + 1 K + Iso8601MaxTimestampFractionalDigits
var maxTimestampFormatLength = BaseTimestampFormat.Length + 2 + Iso8601MaxTimestampFractionalDigits;
var formatSb = new StringBuilder(BaseTimestampFormat, maxTimestampFormatLength);

if (fractionalDigits <= 0)
return formatSb.Append("K");

var fRepeatCount = Math.Min(fractionalDigits, DotNetDateTimeMaxFractionalDigits);
var requestedMinusDotNet = fractionalDigits - DotNetDateTimeMaxFractionalDigits;
const int isoMinusDotNet = Iso8601MaxTimestampFractionalDigits - DotNetDateTimeMaxFractionalDigits;
var zeroRepeatCount = Math.Max(0, Math.Min(requestedMinusDotNet, isoMinusDotNet));
return formatSb
.Append('.')
.Append('f', fRepeatCount)
.Append('0', zeroRepeatCount)
.Append("K");
}

private void AppendHeader(ByteArray buffer, string pri, LogEventInfo logEvent)
{
var timestamp = string.Format(CultureInfo.InvariantCulture, timestampFormat, logEvent.TimeStamp);
var hostname = hostnamePolicySet.Apply(hostnameLayout.Render(logEvent));
var appName = appNamePolicySet.Apply(appNameLayout.Render(logEvent));
var procId = procIdPolicySet.Apply(procIdLayout.Render(logEvent));
var msgId = msgIdPolicySet.Apply(msgIdLayout.Render(logEvent));

buffer.AppendAscii(pri);
buffer.AppendAscii(version);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(timestamp);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(hostname);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(appName);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(procId);
buffer.AppendBytes(SpaceBytes);
buffer.AppendAscii(msgId);
}

private void AppendStructuredData(ByteArray buffer, LogEventInfo logEvent)
{
structuredData.Append(buffer, logEvent);
}

private void AppendMsg(ByteArray buffer, string logEntry)
{
buffer.AppendBytes(preamble);
buffer.AppendUtf8(logEntry);
}
}
}
34 changes: 16 additions & 18 deletions src/NLog.Targets.Syslog/MessageCreation/SdElement.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
// Licensed under the BSD license
// See the LICENSE file in the project root for more information

using NLog.Targets.Syslog.Policies;
using System.Collections.Generic;
using System.Linq;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Policies;
using NLog.Targets.Syslog.Settings;

namespace NLog.Targets.Syslog.MessageCreation
{
internal class SdElement
{
private static readonly InternalLogDuplicatesPolicy LogDuplicatesPolicy = new InternalLogDuplicatesPolicy();
private static readonly byte[] LeftBracketBytes = { 0x5B };
private static readonly byte[] RightBracketBytes = { 0x5D };

private readonly SdId sdId;
private readonly IList<SdParam> sdParams;
private readonly List<SdParam> sdParams;

public SdElement(SdElementConfig sdElementConfig, EnforcementConfig enforcementConfig)
{
sdId = new SdId(sdElementConfig.SdId, enforcementConfig);
sdParams = sdElementConfig.SdParams.Select(sdParamConfig => new SdParam(sdParamConfig, enforcementConfig)).ToList();
}

public static void Append(ByteArray message, IEnumerable<SdElement> sdElements, LogEventInfo logEvent)
public static void Append(ByteArray message, List<SdElement> sdElements, LogEventInfo logEvent)
{
var elements = sdElements
.Select(x => new { SdId = x.sdId, RenderedSdId = x.sdId.Render(logEvent), SdParams = x.sdParams })
.ToList();

InternalLogDuplicatesPolicy.Apply(elements, x => x.RenderedSdId);

elements
.ForEach(elem =>
{
message.AppendBytes(LeftBracketBytes);
elem.SdId.Append(message, elem.RenderedSdId);
SdParam.Append(message, elem.SdParams, logEvent, SdIdToInvalidParamNamePattern.Map(elem.RenderedSdId));
message.AppendBytes(RightBracketBytes);
});
if (LogDuplicatesPolicy.IsApplicable())
LogDuplicatesPolicy.Apply(sdElements, x => x.sdId.Render(logEvent));

foreach (var sdElement in sdElements)
{
var renderedSdId = sdElement.sdId.Render(logEvent);
message.AppendBytes(LeftBracketBytes);
sdElement.sdId.Append(message, renderedSdId);
SdParam.Append(message, sdElement.sdParams, logEvent, SdIdToInvalidParamNamePattern.Map(renderedSdId));
message.AppendBytes(RightBracketBytes);
}
}

public static string ToString(IEnumerable<SdElement> sdElements)
{
return sdElements.Aggregate(string.Empty, (acc, curr) => acc.ToString() + curr.ToString());
return sdElements.Aggregate(string.Empty, (acc, curr) => acc + curr);
}

public override string ToString()
Expand Down
1 change: 0 additions & 1 deletion src/NLog.Targets.Syslog/MessageCreation/SdId.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Licensed under the BSD license
// See the LICENSE file in the project root for more information

using System.Text;
using NLog.Layouts;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Policies;
Expand Down
12 changes: 5 additions & 7 deletions src/NLog.Targets.Syslog/MessageCreation/SdParam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
// See the LICENSE file in the project root for more information

using NLog.Layouts;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Policies;
using NLog.Targets.Syslog.Settings;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog.Targets.Syslog.Extensions;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Settings;

namespace NLog.Targets.Syslog.MessageCreation
{
Expand All @@ -31,13 +29,13 @@ public SdParam(SdParamConfig sdParamConfig, EnforcementConfig enforcementConfig)
paramValuePolicySet = new ParamValuePolicySet(enforcementConfig);
}

public static void Append(ByteArray message, IEnumerable<SdParam> sdParams, LogEventInfo logEvent, string invalidNamesPattern)
public static void Append(ByteArray message, List<SdParam> sdParams, LogEventInfo logEvent, string invalidNamesPattern)
{
sdParams.ForEach(sdParam =>
foreach (var sdParam in sdParams)
{
message.AppendBytes(SpaceBytes);
sdParam.Append(message, logEvent, invalidNamesPattern);
});
}
}

public static string ToString(IEnumerable<SdParam> sdParams)
Expand Down
7 changes: 3 additions & 4 deletions src/NLog.Targets.Syslog/MessageCreation/StructuredData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// See the LICENSE file in the project root for more information

using NLog.Layouts;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog.Targets.Syslog.MessageStorage;
using NLog.Targets.Syslog.Settings;
using System.Collections.Generic;
using System.Linq;

namespace NLog.Targets.Syslog.MessageCreation
{
Expand All @@ -16,7 +15,7 @@ internal class StructuredData
private static readonly byte[] NilValueBytes = { 0x2D };

private readonly Layout fromEventProperties;
private readonly IList<SdElement> sdElements;
private readonly List<SdElement> sdElements;

public StructuredData(StructuredDataConfig sdConfig, EnforcementConfig enforcementConfig)
{
Expand Down
Loading

0 comments on commit ccd1b7f

Please sign in to comment.