From 812c5930d1db4b5001acc3c63481dfdb5551feb4 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 11 Jan 2024 08:49:48 +1000 Subject: [PATCH 1/8] Dev version bump [skip ci] --- src/NLog.Targets.Seq/NLog.Targets.Seq.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj index 71aa3b4..bbd5462 100644 --- a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj +++ b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj @@ -3,7 +3,7 @@ An NLog target that writes structured log events to Seq Datalust;Contributors - 3.1.0 + 3.1.1 net45;net462;netstandard2.0;net6.0 true true From cc394e897916b3a71088dc5a42c37228fd46e459 Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Thu, 14 Mar 2024 19:36:57 +0100 Subject: [PATCH 2/8] Support override of mapping from NLog LogLevel to Seq Level --- src/NLog.Targets.Seq/CompactJsonLayout.cs | 2 ++ src/NLog.Targets.Seq/SeqTarget.cs | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/NLog.Targets.Seq/CompactJsonLayout.cs b/src/NLog.Targets.Seq/CompactJsonLayout.cs index 96e1445..534a079 100644 --- a/src/NLog.Targets.Seq/CompactJsonLayout.cs +++ b/src/NLog.Targets.Seq/CompactJsonLayout.cs @@ -28,6 +28,8 @@ readonly JsonAttribute _messageAttribute = new JsonAttribute("@m", new FormattedMessageLayout()), _messageTemplateAttribute = new JsonAttribute("@mt", new SimpleLayout("${onhasproperties:${message:raw=true}}")); + public Layout LogLevel { get => _levelAttribute.Layout; set => _levelAttribute.Layout = value; } + public CompactJsonLayout() { Attributes.Add(_timestampAttribute); diff --git a/src/NLog.Targets.Seq/SeqTarget.cs b/src/NLog.Targets.Seq/SeqTarget.cs index 32a6c02..60d6269 100644 --- a/src/NLog.Targets.Seq/SeqTarget.cs +++ b/src/NLog.Targets.Seq/SeqTarget.cs @@ -35,13 +35,13 @@ public sealed class SeqTarget : Target Layout _serverUrl; Layout _apiKey; Layout _proxyAddress; - readonly JsonLayout _compactLayout = new CompactJsonLayout(); + readonly CompactJsonLayout _compactLayout = new CompactJsonLayout(); readonly char[] _reusableEncodingBuffer = new char[32 * 1024]; // Avoid large-object-heap Uri _webRequestUri; string _headerApiKey; HttpClient _httpClient; - LogLevel _minimumLevel = LogLevel.Trace; + LogLevel _minimumLevel = NLog.LogLevel.Trace; static readonly UTF8Encoding Utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); @@ -76,6 +76,11 @@ public sealed class SeqTarget : Target /// public string ProxyAddress { get => (_proxyAddress as SimpleLayout)?.Text; set => _proxyAddress = value ?? string.Empty; } + /// + /// Override the mapping from NLog LogLevel to Seq LogLevel. Default output is ${level} + /// + public Layout SeqLevel { get => _compactLayout.LogLevel; set => _compactLayout.LogLevel = value; } + /// /// Use default credentials /// From 8a501e2e20499e252710e28f82084f5410ac5089 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 20 Mar 2024 17:01:41 +1000 Subject: [PATCH 3/8] Support additional HTTP header
target configuration items --- src/NLog.Targets.Seq/SeqHttpHeaderItem.cs | 25 ++++++++ src/NLog.Targets.Seq/SeqTarget.cs | 70 +++++++++++++---------- 2 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 src/NLog.Targets.Seq/SeqHttpHeaderItem.cs diff --git a/src/NLog.Targets.Seq/SeqHttpHeaderItem.cs b/src/NLog.Targets.Seq/SeqHttpHeaderItem.cs new file mode 100644 index 0000000..32d5203 --- /dev/null +++ b/src/NLog.Targets.Seq/SeqHttpHeaderItem.cs @@ -0,0 +1,25 @@ +using NLog.Config; +using NLog.Layouts; + +namespace NLog.Targets.Seq +{ + /// + /// Represents an additional HTTP header that wil be attached to outgoing HTTP requests made by + /// . + /// + [NLogConfigurationItem] + public sealed class SeqHttpHeaderItem + { + /// + /// The name of the HTTP header to add. + /// + [RequiredParameter] + public string Name { get; set; } + + /// + /// The value of the HTTP header. + /// + [RequiredParameter] + public Layout Value { get; set; } + } +} \ No newline at end of file diff --git a/src/NLog.Targets.Seq/SeqTarget.cs b/src/NLog.Targets.Seq/SeqTarget.cs index 60d6269..54aa93e 100644 --- a/src/NLog.Targets.Seq/SeqTarget.cs +++ b/src/NLog.Targets.Seq/SeqTarget.cs @@ -21,7 +21,8 @@ using NLog.Common; using NLog.Config; using NLog.Layouts; - +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global namespace NLog.Targets.Seq @@ -39,9 +40,8 @@ public sealed class SeqTarget : Target readonly char[] _reusableEncodingBuffer = new char[32 * 1024]; // Avoid large-object-heap Uri _webRequestUri; - string _headerApiKey; HttpClient _httpClient; - LogLevel _minimumLevel = NLog.LogLevel.Trace; + LogLevel _minimumLevel = LogLevel.Trace; static readonly UTF8Encoding Utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); @@ -90,7 +90,7 @@ public sealed class SeqTarget : Target /// A list of properties that will be attached to the events. /// [ArrayParameter(typeof(SeqPropertyItem), "property")] - public IList Properties { get; } + public IList Properties { get; } = new List(); /// /// How far should the JSON serializer follow object references before backing off @@ -122,12 +122,17 @@ public ISet ExcludeProperties set => _compactLayout.ExcludeProperties = value; } + /// + /// Additional HTTP headers to attach to outgoing HTTP requests made by the sink. + /// + [ArrayParameter(typeof(SeqHttpHeaderItem), "header")] + public IList AdditionalHeaders { get; } = new List(); + /// /// Construct a . /// public SeqTarget() { - Properties = new List(); MaxRecursionLimit = 0; // Default behavior for Serilog JsonPayloadMaxLength = 128 * 1024; } @@ -152,7 +157,8 @@ protected override void InitializeTarget() uri += SeqApi.BulkUploadResource; _webRequestUri = new Uri(uri); - _headerApiKey = _apiKey?.Render(LogEventInfo.CreateNullEvent()) ?? string.Empty; + var nullEvent = LogEventInfo.CreateNullEvent(); + var headerApiKey = _apiKey?.Render(nullEvent) ?? string.Empty; HttpClientHandler handler = null; @@ -172,6 +178,14 @@ protected override void InitializeTarget() } _httpClient = handler == null ? new HttpClient() : new HttpClient(handler); + + if (!string.IsNullOrWhiteSpace(headerApiKey)) + _httpClient.DefaultRequestHeaders.Add(SeqApi.ApiKeyHeaderName, headerApiKey); + + foreach (var additionalHeader in AdditionalHeaders) + { + _httpClient.DefaultRequestHeaders.Add(additionalHeader.Name, additionalHeader.Value.Render(nullEvent)); + } } base.InitializeTarget(); @@ -270,11 +284,9 @@ async Task PostBatch(IList logEvents) } } - private async Task SendPayload(StringBuilder payload) + async Task SendPayload(StringBuilder payload) { var request = new HttpRequestMessage(HttpMethod.Post, _webRequestUri); - if (!string.IsNullOrWhiteSpace(_headerApiKey)) - request.Headers.Add(SeqApi.ApiKeyHeaderName, _headerApiKey); var httpContent = new ByteArrayContent(EncodePayload(Utf8, payload)); httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(SeqApi.CompactLogEventFormatMediaType) { CharSet = Utf8.WebName }; @@ -283,41 +295,37 @@ private async Task SendPayload(StringBuilder payload) // Even if no events are above `_minimumLevel`, we'll send a batch to make sure we observe minimum // level changes sent by the server. - using (var response = await _httpClient.SendAsync(request).ConfigureAwait(false)) + using var response = await _httpClient.SendAsync(request).ConfigureAwait(false); + if ((int)response.StatusCode > 299) { - if ((int)response.StatusCode > 299) - { - var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new WebException($"Received failed response {response.StatusCode} from Seq server: {data}"); - } + var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new WebException($"Received failed response {response.StatusCode} from Seq server: {data}"); + } - if ((int)response.StatusCode == (int)HttpStatusCode.Created) + if ((int)response.StatusCode == (int)HttpStatusCode.Created) + { + var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var serverRequestedLevel = LevelMapping.ToNLogLevel(SeqApi.ReadMinimumAcceptedLevel(data)); + if (serverRequestedLevel != _minimumLevel) { - var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var serverRequestedLevel = LevelMapping.ToNLogLevel(SeqApi.ReadMinimumAcceptedLevel(data)); - if (serverRequestedLevel != _minimumLevel) - { - InternalLogger.Info("Seq(Name={0}): Setting minimum log level to {1} per server request", Name, serverRequestedLevel); - _minimumLevel = serverRequestedLevel; - } + InternalLogger.Info("Seq(Name={0}): Setting minimum log level to {1} per server request", Name, serverRequestedLevel); + _minimumLevel = serverRequestedLevel; } } } - private byte[] EncodePayload(Encoding encoder, StringBuilder payload) + byte[] EncodePayload(Encoding encoder, StringBuilder payload) { lock (_reusableEncodingBuffer) { - int totalLength = payload.Length; + var totalLength = payload.Length; if (totalLength < _reusableEncodingBuffer.Length) { payload.CopyTo(0, _reusableEncodingBuffer, 0, payload.Length); return encoder.GetBytes(_reusableEncodingBuffer, 0, totalLength); } - else - { - return encoder.GetBytes(payload.ToString()); - } + + return encoder.GetBytes(payload.ToString()); } } @@ -334,9 +342,9 @@ internal void TestInitialize() InitializeTarget(); } - private static void AddJsonAttribute(JsonLayout jsonLayout, JsonAttribute jsonAttribute) + static void AddJsonAttribute(JsonLayout jsonLayout, JsonAttribute jsonAttribute) { - for (int i = jsonLayout.Attributes.Count - 1; i >= 0; --i) + for (var i = jsonLayout.Attributes.Count - 1; i >= 0; --i) { if (jsonLayout.Attributes[i].Name == jsonAttribute.Name) { From 006af03c5aa7fff605b746589ee1ab9b5c4c84d6 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 21 Mar 2024 08:16:43 +1000 Subject: [PATCH 4/8] Remove obsolete Gitter link [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2a5123..1e0c693 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NLog.Targets.Seq [![NuGet Pre Release](https://img.shields.io/nuget/vpre/NLog.Targets.Seq.svg)](https://nuget.org/packages/NLog.Targets.Seq) [![Build status](https://ci.appveyor.com/api/projects/status/o22e6dq0mkftaggc?svg=true)](https://ci.appveyor.com/project/datalust/nlog-targets-seq) [![Join the chat at https://gitter.im/datalust/seq](https://img.shields.io/gitter/room/datalust/seq.svg)](https://gitter.im/datalust/seq) +# NLog.Targets.Seq [![NuGet Pre Release](https://img.shields.io/nuget/vpre/NLog.Targets.Seq.svg)](https://nuget.org/packages/NLog.Targets.Seq) [![Build status](https://ci.appveyor.com/api/projects/status/o22e6dq0mkftaggc?svg=true)](https://ci.appveyor.com/project/datalust/nlog-targets-seq) An NLog target that writes events to [Seq](https://datalust.co/seq). The target takes full advantage of the structured logging support in **NLog 4.5** to provide hassle-free filtering, searching and analysis. From 3226a50badebde10ad013140eaf77574ba947f1a Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Tue, 2 Apr 2024 10:03:16 +1000 Subject: [PATCH 5/8] Minor version bump; new features incoming --- src/NLog.Targets.Seq/NLog.Targets.Seq.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj index bbd5462..af64194 100644 --- a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj +++ b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj @@ -3,7 +3,7 @@ An NLog target that writes structured log events to Seq Datalust;Contributors - 3.1.1 + 3.2.0 net45;net462;netstandard2.0;net6.0 true true From bfcc2d9f74f753e63bc5927411055c3c834fa3fc Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 4 Apr 2024 10:25:19 +1000 Subject: [PATCH 6/8] Collect trace and span id when present (#74) --- global.json | 2 +- sample/Example/Example.csproj | 4 +- sample/Example/NLog.config | 2 +- sample/Example/Program.cs | 2 - .../{ => Layouts}/CompactJsonLayout.cs | 18 ++++--- .../Layouts/CurrentW3CActivityLayout.cs | 45 +++++++++++++++++ .../{ => Layouts}/FormattedMessageLayout.cs | 2 +- .../{ => Layouts}/RenderingsLayout.cs | 2 +- src/NLog.Targets.Seq/NLog.Targets.Seq.csproj | 9 ++-- src/NLog.Targets.Seq/SeqTarget.cs | 2 + test/NLog.Targets.Seq.Tests/SeqTargetTests.cs | 49 ++++++++++++++++--- 11 files changed, 111 insertions(+), 26 deletions(-) rename src/NLog.Targets.Seq/{ => Layouts}/CompactJsonLayout.cs (66%) create mode 100644 src/NLog.Targets.Seq/Layouts/CurrentW3CActivityLayout.cs rename src/NLog.Targets.Seq/{ => Layouts}/FormattedMessageLayout.cs (97%) rename src/NLog.Targets.Seq/{ => Layouts}/RenderingsLayout.cs (98%) diff --git a/global.json b/global.json index 08fc58c..989a69c 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.100", + "version": "8.0.100", "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/sample/Example/Example.csproj b/sample/Example/Example.csproj index 05036d6..279bcea 100644 --- a/sample/Example/Example.csproj +++ b/sample/Example/Example.csproj @@ -1,7 +1,7 @@ - net472;net6.0 + net472;net8.0 true Example Exe @@ -9,6 +9,7 @@ false false false + latest @@ -18,6 +19,7 @@ + diff --git a/sample/Example/NLog.config b/sample/Example/NLog.config index 581bd37..7fd9f7b 100644 --- a/sample/Example/NLog.config +++ b/sample/Example/NLog.config @@ -8,7 +8,7 @@ diff --git a/sample/Example/Program.cs b/sample/Example/Program.cs index b368601..a1dd900 100644 --- a/sample/Example/Program.cs +++ b/sample/Example/Program.cs @@ -25,8 +25,6 @@ public static void Main() // As are objects Logger.Info(new object()); - - Console.ReadKey(); } } } diff --git a/src/NLog.Targets.Seq/CompactJsonLayout.cs b/src/NLog.Targets.Seq/Layouts/CompactJsonLayout.cs similarity index 66% rename from src/NLog.Targets.Seq/CompactJsonLayout.cs rename to src/NLog.Targets.Seq/Layouts/CompactJsonLayout.cs index 534a079..d4f65d0 100644 --- a/src/NLog.Targets.Seq/CompactJsonLayout.cs +++ b/src/NLog.Targets.Seq/Layouts/CompactJsonLayout.cs @@ -16,17 +16,19 @@ using NLog.Config; using NLog.Layouts; -namespace NLog.Targets.Seq +namespace NLog.Targets.Seq.Layouts { [ThreadAgnostic] class CompactJsonLayout : JsonLayout { readonly JsonAttribute - _timestampAttribute = new JsonAttribute("@t", new SimpleLayout("${date:format=o}")), - _levelAttribute = new JsonAttribute("@l", new SimpleLayout("${level}")), - _exceptionAttribute = new JsonAttribute("@x", new SimpleLayout("${exception:format=toString}")), - _messageAttribute = new JsonAttribute("@m", new FormattedMessageLayout()), - _messageTemplateAttribute = new JsonAttribute("@mt", new SimpleLayout("${onhasproperties:${message:raw=true}}")); + _timestampAttribute = new("@t", new SimpleLayout("${date:format=o}")), + _levelAttribute = new("@l", new SimpleLayout("${level}")), + _exceptionAttribute = new("@x", new SimpleLayout("${exception:format=toString}")), + _messageAttribute = new("@m", new FormattedMessageLayout()), + _messageTemplateAttribute = new("@mt", new SimpleLayout("${onhasproperties:${message:raw=true}}")), + _traceIdAttribute = new("@tr", new CurrentW3CActivityLayout(a => a.TraceId.ToHexString())), + _spanIdAttribute = new("@sp", new CurrentW3CActivityLayout(a => a.SpanId.ToHexString())); public Layout LogLevel { get => _levelAttribute.Layout; set => _levelAttribute.Layout = value; } @@ -39,7 +41,9 @@ public CompactJsonLayout() var renderingsAttribute = new JsonAttribute("@r", new RenderingsLayout(new Lazy(ResolveService)), encode: false); Attributes.Add(renderingsAttribute); Attributes.Add(_messageAttribute); - + Attributes.Add(_traceIdAttribute); + Attributes.Add(_spanIdAttribute); + IncludeEventProperties = true; IncludeScopeProperties = true; SuppressSpaces = true; diff --git a/src/NLog.Targets.Seq/Layouts/CurrentW3CActivityLayout.cs b/src/NLog.Targets.Seq/Layouts/CurrentW3CActivityLayout.cs new file mode 100644 index 0000000..c705f1f --- /dev/null +++ b/src/NLog.Targets.Seq/Layouts/CurrentW3CActivityLayout.cs @@ -0,0 +1,45 @@ +// Seq Target for NLog - Copyright © Datalust and contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Diagnostics; +using System.Text; +using NLog.Layouts; + +namespace NLog.Targets.Seq.Layouts +{ + /// + /// Formats elements of for inclusion in log events. Non-W3C-format activities are + /// ignored (Seq does not support the older Microsoft-proprietary hierarchical activity id format). + /// + class CurrentW3CActivityLayout: Layout + { + readonly Func _format; + + public CurrentW3CActivityLayout(Func format) + { + _format = format; + } + + protected override void RenderFormattedMessage(LogEventInfo logEvent, StringBuilder target) + { + target.Append(GetFormattedMessage(logEvent)); + } + + protected override string GetFormattedMessage(LogEventInfo logEvent) + { + return Activity.Current is { IdFormat: ActivityIdFormat.W3C } activity ? _format(activity) : null; + } + } +} \ No newline at end of file diff --git a/src/NLog.Targets.Seq/FormattedMessageLayout.cs b/src/NLog.Targets.Seq/Layouts/FormattedMessageLayout.cs similarity index 97% rename from src/NLog.Targets.Seq/FormattedMessageLayout.cs rename to src/NLog.Targets.Seq/Layouts/FormattedMessageLayout.cs index 7dc623f..dbad7d2 100644 --- a/src/NLog.Targets.Seq/FormattedMessageLayout.cs +++ b/src/NLog.Targets.Seq/Layouts/FormattedMessageLayout.cs @@ -16,7 +16,7 @@ using NLog.Config; using NLog.Layouts; -namespace NLog.Targets.Seq +namespace NLog.Targets.Seq.Layouts { [ThreadAgnostic] class FormattedMessageLayout : Layout diff --git a/src/NLog.Targets.Seq/RenderingsLayout.cs b/src/NLog.Targets.Seq/Layouts/RenderingsLayout.cs similarity index 98% rename from src/NLog.Targets.Seq/RenderingsLayout.cs rename to src/NLog.Targets.Seq/Layouts/RenderingsLayout.cs index ed471d3..5f66696 100644 --- a/src/NLog.Targets.Seq/RenderingsLayout.cs +++ b/src/NLog.Targets.Seq/Layouts/RenderingsLayout.cs @@ -18,7 +18,7 @@ using NLog.Layouts; using NLog.MessageTemplates; -namespace NLog.Targets.Seq +namespace NLog.Targets.Seq.Layouts { [ThreadAgnostic] class RenderingsLayout : Layout diff --git a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj index af64194..e5d1a75 100644 --- a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj +++ b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj @@ -3,8 +3,8 @@ An NLog target that writes structured log events to Seq Datalust;Contributors - 3.2.0 - net45;net462;netstandard2.0;net6.0 + 4.0.0 + net462;netstandard2.0;net6.0 true true ../../asset/nlog-targets-seq.snk @@ -17,7 +17,7 @@ https://github.com/datalust/nlog-targets-seq.git git false - 8.0 + 9.0 @@ -34,9 +34,10 @@ - + + diff --git a/src/NLog.Targets.Seq/SeqTarget.cs b/src/NLog.Targets.Seq/SeqTarget.cs index 54aa93e..942e92b 100644 --- a/src/NLog.Targets.Seq/SeqTarget.cs +++ b/src/NLog.Targets.Seq/SeqTarget.cs @@ -21,6 +21,8 @@ using NLog.Common; using NLog.Config; using NLog.Layouts; +using NLog.Targets.Seq.Layouts; + // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global diff --git a/test/NLog.Targets.Seq.Tests/SeqTargetTests.cs b/test/NLog.Targets.Seq.Tests/SeqTargetTests.cs index e2dc773..2e433fa 100644 --- a/test/NLog.Targets.Seq.Tests/SeqTargetTests.cs +++ b/test/NLog.Targets.Seq.Tests/SeqTargetTests.cs @@ -3,15 +3,22 @@ using NLog.Targets.Seq.Tests.Support; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using Xunit; +// ReSharper disable UseObjectOrCollectionInitializer namespace NLog.Targets.Seq.Tests { public class SeqTargetTests { + static SeqTargetTests() + { + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + } + static void ToCompactJson(LogEventInfo evt, TextWriter output, IEnumerable properties, int? maxRecursionLimit = null) { var target = new SeqTarget(); @@ -63,8 +70,8 @@ public void ANonInfoLevelEventIsValid() public void AMinimalEventIsValidJson() { var evt = AssertValidJson(log => log.Info("One {Property}", 42)); - Assert.Equal(42, evt["Property"].Value()); - Assert.Equal("One {Property}", evt["@mt"].Value()); + Assert.Equal(42, evt["Property"]!.Value()); + Assert.Equal("One {Property}", evt["@mt"]!.Value()); } [Fact] @@ -73,8 +80,8 @@ public void APositionalEventIsValidJson() var logEvent = LogEventInfo.Create(LogLevel.Info, null, null, 42); logEvent.Properties["Property"] = 42; var evt = AssertValidJson(log => log.Log(logEvent)); - Assert.Equal(42, evt["Property"].Value()); - Assert.Equal("42", evt["@m"].Value()); + Assert.Equal(42, evt["Property"]!.Value()); + Assert.Equal("42", evt["@m"]!.Value()); } [Fact] @@ -83,8 +90,8 @@ public void SimpleEventPropertiesAreRenderedIntoJson() var logEvent = new LogEventInfo { Message = "Hello " }; logEvent.Properties["Answer"] = 42; var evt = AssertValidJson(log => log.Info(logEvent)); - Assert.Equal(42, evt["Answer"].Value()); - Assert.Equal("Hello ", evt["@mt"].Value()); + Assert.Equal(42, evt["Answer"]!.Value()); + Assert.Equal("Hello ", evt["@mt"]!.Value()); } [Fact] @@ -94,7 +101,7 @@ public void DefaultRecursionLimitStringifiesComplexProperties() logEvent.Properties["Result"] = new { A = 1, B = 2, C = 3 }; var result = logEvent.Properties["Result"].ToString(); var evt = AssertValidJson(log => log.Info(logEvent)); - Assert.Equal(result, evt["Result"].Value()); + Assert.Equal(result, evt["Result"]!.Value()); } [Fact] @@ -103,7 +110,7 @@ public void DeeperRecursionLimitSerializesComplexProperties() var logEvent = new LogEventInfo { Message = "Hello " }; logEvent.Properties["Result"] = new { A = 1, B = 2, C = 3 }; var evt = AssertValidJson(log => log.Info(logEvent), maxRecursionLimit: 1); - Assert.Equal(3, evt["Result"].ToList().Count); + Assert.Equal(3, evt["Result"]!.ToList().Count); } [Fact] @@ -188,5 +195,31 @@ public void IncorrectlyFormattedSerializedPropertiesAreCharitablyIncluded() Assert.Equal("A", (string)evt.StringData.Data); Assert.Single((JArray)evt["@r"]); } + + [Fact] + public void TraceAndSpanIdAreIgnoredWhenMissing() + { + Assert.Null(Activity.Current); + var evt = AssertValidJson(log => log.Info("Hello")); + Assert.False(evt.ContainsKey("@tr")); + Assert.False(evt.ContainsKey("@sp")); + } + + [Fact] + public void TraceAndSpanIdAreCollectedWhenPresent() + { + using var listener = new ActivityListener(); + listener.ShouldListenTo = _ => true; + listener.Sample = delegate { return ActivitySamplingResult.AllData; }; + ActivitySource.AddActivityListener(listener); + + var source = new ActivitySource("Example"); + using var activity = source.StartActivity()!; + + dynamic evt = AssertValidJson(log => log.Info("Hello")); + + Assert.Equal(activity.TraceId.ToHexString(), (string)evt["@tr"]); + Assert.Equal(activity.SpanId.ToHexString(), (string)evt["@sp"]); + } } } From c1605b2fe4cb4433794f5b15ea775703fec0edf5 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 4 Apr 2024 10:40:42 +1000 Subject: [PATCH 7/8] Revert TFM change from #74 --- src/NLog.Targets.Seq/NLog.Targets.Seq.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj index e5d1a75..aff3920 100644 --- a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj +++ b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj @@ -3,8 +3,8 @@ An NLog target that writes structured log events to Seq Datalust;Contributors - 4.0.0 - net462;netstandard2.0;net6.0 + 3.2.0 + net45;net462;netstandard2.0;net6.0 true true ../../asset/nlog-targets-seq.snk From e53c0a964598c133c40e6cb15b8f99a8e0e9f172 Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Thu, 4 Apr 2024 10:42:21 +1000 Subject: [PATCH 8/8] Revert-the-revert: need to drop `net45` for System.Diagnostics.DiagnosticSource --- src/NLog.Targets.Seq/NLog.Targets.Seq.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj index aff3920..e5d1a75 100644 --- a/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj +++ b/src/NLog.Targets.Seq/NLog.Targets.Seq.csproj @@ -3,8 +3,8 @@ An NLog target that writes structured log events to Seq Datalust;Contributors - 3.2.0 - net45;net462;netstandard2.0;net6.0 + 4.0.0 + net462;netstandard2.0;net6.0 true true ../../asset/nlog-targets-seq.snk