Skip to content

Commit

Permalink
Enable configuration of RFC 5424 timestamp fractional digits (#237 cl…
Browse files Browse the repository at this point in the history
…oses #224)
  • Loading branch information
luigiberrettini committed Jun 14, 2020
1 parent e3d8814 commit 7e0a921
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ The maximum length of a message is detailed in many RFCs that can be summarized
* `hostname` ([Layout](http://github.com/NLog/NLog/wiki/Layouts)) - the HOSTNAME field of the HEADER part (default: the hostname of the computer that is creating the message)
* `tag` ([Layout](http://github.com/NLog/NLog/wiki/Layouts)) - the TAG field of the MSG part (default: the name of the assembly that is creating the message)
* `rfc5424` - settings related to RFC 5424:
* `timestampFractionalDigits` - the number of fractional digits for the TIMESTAMP field of the HEADER part (default: 6, max: 16 as per ISO 8601 but since .NET is limited to 7 the other digits will be zeroed)
* `hostname` ([Layout](http://github.com/NLog/NLog/wiki/Layouts)) - the HOSTNAME field of the HEADER part (default: the hostname of the computer that is creating the message)
* `appName` ([Layout](http://github.com/NLog/NLog/wiki/Layouts)) - the APPNAME field of the HEADER part (default: the name of the assembly that is creating the message)
* `procId` ([Layout](http://github.com/NLog/NLog/wiki/Layouts)) - the PROCID field of the HEADER part (default: `-`)
Expand Down
2 changes: 2 additions & 0 deletions src/NLog.Targets.Syslog.Schema/NLog.Targets.Syslog.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<xs:element name="rfc5424" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="timestampFractionalDigits" type="xs:integer" minOccurs="0" maxOccurs="1" />
<xs:element name="hostname" type="nlog:Layout" minOccurs="0" maxOccurs="1" />
<xs:element name="appName" type="nlog:Layout" minOccurs="0" maxOccurs="1" />
<xs:element name="procId" type="nlog:Layout" minOccurs="0" maxOccurs="1" />
Expand Down Expand Up @@ -115,6 +116,7 @@
</xs:element>
<xs:element name="disableBom" type="xs:boolean" minOccurs="0" maxOccurs="1" />
</xs:choice>
<xs:attribute name="timestampFractionalDigits" type="xs:integer" />
<xs:attribute name="hostname" type="nlog:SimpleLayoutAttribute" />
<xs:attribute name="appName" type="nlog:SimpleLayoutAttribute" />
<xs:attribute name="procId" type="nlog:SimpleLayoutAttribute" />
Expand Down
29 changes: 27 additions & 2 deletions src/NLog.Targets.Syslog/MessageCreation/Rfc5424.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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;
Expand All @@ -12,10 +13,13 @@ namespace NLog.Targets.Syslog.MessageCreation
{
internal class Rfc5424 : MessageBuilder
{
private const string TimestampFormat = "{0:yyyy-MM-ddTHH:mm:ss.ffffffK}";
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;
Expand All @@ -31,6 +35,7 @@ internal class Rfc5424 : MessageBuilder
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;
Expand All @@ -55,9 +60,29 @@ protected override void PrepareMessage(ByteArray buffer, LogEventInfo logEvent,
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 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));
Expand Down
10 changes: 10 additions & 0 deletions src/NLog.Targets.Syslog/Settings/Rfc5424Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ namespace NLog.Targets.Syslog.Settings
public class Rfc5424Config : NotifyPropertyChanged, IDisposable
{
private const string DefaultVersion = "1";
private const int DefaultTimestampFractionalDigits = 6;
private const string NilValue = "-";
private int timestampFractionalDigits;
private Layout hostname;
private Layout appName;
private Layout procId;
Expand All @@ -30,6 +32,13 @@ public class Rfc5424Config : NotifyPropertyChanged, IDisposable
/// <summary>The VERSION field of the HEADER part</summary>
public string Version { get; }

/// <summary>The number of fractional digits for the TIMESTAMP field of the HEADER part</summary>
public int TimestampFractionalDigits
{
get => timestampFractionalDigits;
set => SetProperty(ref timestampFractionalDigits, value);
}

/// <summary>The default HOSTNAME if no value is provided</summary>
public string DefaultHostname { get; }

Expand Down Expand Up @@ -83,6 +92,7 @@ public bool DisableBom
public Rfc5424Config()
{
Version = DefaultVersion;
TimestampFractionalDigits = DefaultTimestampFractionalDigits;
DefaultHostname = HostFqdn();
hostname = DefaultHostname;
DefaultAppName = UniversalAssembly.EntryAssembly().Name();
Expand Down

0 comments on commit 7e0a921

Please sign in to comment.