Skip to content

Commit

Permalink
Merge pull request #212 from datalust/dev
Browse files Browse the repository at this point in the history
7.0.0 Release
  • Loading branch information
nblumhardt authored Mar 6, 2024
2 parents c6de2ef + 73a806b commit bf6c2f8
Show file tree
Hide file tree
Showing 12 changed files with 374 additions and 38 deletions.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "7.0.100",
"version": "8.0.201",
"rollForward": "latestFeature"
}
}
10 changes: 5 additions & 5 deletions sample/BlazorWasm/BlazorWasm.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.11" PrivateAssets="all" />
<PackageReference Include="serilog.extensions.logging" Version="7.0.0" />
<PackageReference Include="serilog.sinks.browserconsole" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="serilog.extensions.logging" Version="8.0.0" />
<PackageReference Include="serilog.sinks.browserconsole" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions sample/Sample/Sample.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 2 additions & 3 deletions src/Serilog.Sinks.Seq/SeqLoggerConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using Serilog.Sinks.Seq;
using System.Net.Http;
using Serilog.Formatting;
using Serilog.Formatting.Compact;
using Serilog.Sinks.PeriodicBatching;
using Serilog.Sinks.Seq.Batched;
using Serilog.Sinks.Seq.Audit;
Expand All @@ -36,8 +35,8 @@ public static class SeqLoggerConfigurationExtensions
const int DefaultBatchPostingLimit = 1000;
static readonly TimeSpan DefaultPeriod = TimeSpan.FromSeconds(2);
const int DefaultQueueSizeLimit = 100000;
static ITextFormatter CreateDefaultFormatter() => new CompactJsonFormatter(new("$type"));

static ITextFormatter CreateDefaultFormatter() => new SeqCompactJsonFormatter();
/// <summary>
/// Write log events to a <a href="https://datalust.co/seq">Seq</a> server.
/// </summary>
Expand Down
5 changes: 2 additions & 3 deletions src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Description>A Serilog sink that writes events to Seq using newline-delimited JSON and HTTP/HTTPS.</Description>
<VersionPrefix>6.0.0</VersionPrefix>
<VersionPrefix>7.0.0</VersionPrefix>
<Authors>Serilog Contributors;Serilog.Sinks.Seq Contributors;Datalust Pty Ltd</Authors>
<Copyright>Copyright © Serilog Contributors, Serilog.Sinks.Seq Contributors, Datalust Pty Ltd.</Copyright>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
Expand Down Expand Up @@ -30,8 +30,7 @@

<ItemGroup>
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="3.1.0" />
<PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="4.0.0" />
<PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="All" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
Expand Down
18 changes: 12 additions & 6 deletions src/Serilog.Sinks.Seq/Sinks/Seq/Http/SeqIngestionApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ sealed class SeqIngestionApiClient : SeqIngestionApi
{
const string BulkUploadResource = "api/events/raw";
const string ApiKeyHeaderName = "X-Seq-ApiKey";

readonly string? _apiKey;
readonly HttpClient _httpClient;

Expand All @@ -50,6 +50,7 @@ public SeqIngestionApiClient(string serverUrl, string? apiKey, HttpMessageHandle
_httpClient = new HttpClient();
}
#endif

#if SOCKETS_HTTP_HANDLER_ALWAYS_DEFAULT
else
{
Expand All @@ -59,14 +60,19 @@ public SeqIngestionApiClient(string serverUrl, string? apiKey, HttpMessageHandle
// require that the Seq API be accessed at a different IP address. Setting a timeout here puts
// an upper bound on the duration of DNS-related outages, while hopefully incurring only infrequent
// connection reestablishment costs.
PooledConnectionLifetime = TimeSpan.FromMinutes(5)
PooledConnectionLifetime = TimeSpan.FromMinutes(5),

// Don't trace the sink's own requests. On platforms that use alternative message handler implementations
// by default, the caller needs to do this manually and pass a handler through. Where `SocketsHttpHandler`
// is the default, we can safely set this without inadvertently causing behavior changes.
ActivityHeadersPropagator = null
});
}
#else
else
{
_httpClient = new HttpClient();
}
else
{
_httpClient = new HttpClient();
}
#endif

_httpClient.BaseAddress = new Uri(NormalizeServerBaseAddress(serverUrl));
Expand Down
164 changes: 164 additions & 0 deletions src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright 2016 Serilog 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.Globalization;
using System.IO;
using System.Linq;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Json;
using Serilog.Parsing;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable PossibleMultipleEnumeration

namespace Serilog.Sinks.Seq;

/// <summary>
/// An <see cref="ITextFormatter"/> that writes events in a compact JSON format.
/// </summary>
/// <remarks>Modified from <c>Serilog.Formatting.Compact.CompactJsonFormatter</c> to add
/// implicit SerilogTracing span support.</remarks>
public class SeqCompactJsonFormatter: ITextFormatter
{
readonly JsonValueFormatter _valueFormatter = new("$type");

/// <summary>
/// Format the log event into the output. Subsequent events will be newline-delimited.
/// </summary>
/// <param name="logEvent">The event to format.</param>
/// <param name="output">The output.</param>
public void Format(LogEvent logEvent, TextWriter output)
{
FormatEvent(logEvent, output, _valueFormatter);
output.WriteLine();
}

/// <summary>
/// Format the log event into the output.
/// </summary>
/// <param name="logEvent">The event to format.</param>
/// <param name="output">The output.</param>
/// <param name="valueFormatter">A value formatter for <see cref="LogEventPropertyValue"/>s on the event.</param>
public static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter valueFormatter)
{
if (logEvent == null) throw new ArgumentNullException(nameof(logEvent));
if (output == null) throw new ArgumentNullException(nameof(output));
if (valueFormatter == null) throw new ArgumentNullException(nameof(valueFormatter));

output.Write("{\"@t\":\"");
output.Write(logEvent.Timestamp.UtcDateTime.ToString("O"));
output.Write("\",\"@mt\":");
JsonValueFormatter.WriteQuotedJsonString(logEvent.MessageTemplate.Text, output);

var tokensWithFormat = logEvent.MessageTemplate.Tokens
.OfType<PropertyToken>()
.Where(pt => pt.Format != null);

// Better not to allocate an array in the 99.9% of cases where this is false
// ReSharper disable once PossibleMultipleEnumeration
if (tokensWithFormat.Any())
{
output.Write(",\"@r\":[");
var delim = "";
foreach (var r in tokensWithFormat)
{
output.Write(delim);
delim = ",";
var space = new StringWriter();
r.Render(logEvent.Properties, space, CultureInfo.InvariantCulture);
JsonValueFormatter.WriteQuotedJsonString(space.ToString(), output);
}
output.Write(']');
}

if (logEvent.Level != LogEventLevel.Information)
{
output.Write(",\"@l\":\"");
output.Write(logEvent.Level);
output.Write('\"');
}

if (logEvent.Exception != null)
{
output.Write(",\"@x\":");
JsonValueFormatter.WriteQuotedJsonString(logEvent.Exception.ToString(), output);
}

if (logEvent.TraceId != null)
{
output.Write(",\"@tr\":\"");
output.Write(logEvent.TraceId.Value.ToHexString());
output.Write('\"');
}

if (logEvent.SpanId != null)
{
output.Write(",\"@sp\":\"");
output.Write(logEvent.SpanId.Value.ToHexString());
output.Write('\"');
}

var skipSpanProperties = false;
if (logEvent is {TraceId: not null, SpanId: not null} &&
logEvent.Properties.TryGetValue("SpanStartTimestamp", out var st) &&
st is ScalarValue { Value: DateTime spanStartTimestamp })
{
skipSpanProperties = true;

output.Write(",\"@st\":\"");
output.Write(spanStartTimestamp.ToString("o"));
output.Write('\"');

if (logEvent.Properties.TryGetValue("ParentSpanId", out var ps) &&
ps is ScalarValue { Value: ActivitySpanId parentSpanId })
{
output.Write(",\"@ps\":\"");
output.Write(parentSpanId.ToHexString());
output.Write('\"');
}

if (logEvent.Properties.TryGetValue("SpanKind", out var sk) &&
sk is ScalarValue { Value: ActivityKind spanKind } &&
spanKind != ActivityKind.Internal)
{
output.Write(",\"@sk\":\"");
output.Write(spanKind);
output.Write('\"');
}
}

foreach (var property in logEvent.Properties)
{
var name = property.Key;

if (skipSpanProperties && name is "SpanStartTimestamp" or "ParentSpanId" or "SpanKind")
continue;

if (name.Length > 0 && name[0] == '@')
{
// Escape first '@' by doubling
name = '@' + name;
}

output.Write(',');
JsonValueFormatter.WriteQuotedJsonString(name, output);
output.Write(':');
valueFormatter.Format(property.Value, output);
}

output.Write('}');
}
}
7 changes: 3 additions & 4 deletions test/Serilog.Sinks.Seq.Tests/Audit/SeqAuditSinkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Threading.Tasks;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting.Compact;
using Serilog.Sinks.Seq.Audit;
using Serilog.Sinks.Seq.Tests.Support;
using Xunit;
Expand Down Expand Up @@ -40,7 +39,7 @@ public void RemoteCommunicationErrorsPropagateToCallerWhenAuditing()
public void AuditSinkDisposesIngestionApi()
{
var api = new TestIngestionApi();
var sink = new SeqAuditSink(api, new CompactJsonFormatter());
var sink = new SeqAuditSink(api, new SeqCompactJsonFormatter());
Assert.False(api.IsDisposed);

sink.Dispose();
Expand All @@ -54,7 +53,7 @@ public async Task AuditSinkEmitsIndividualEvents()
LogEvent evt1 = Some.InformationEvent("first"), evt2 = Some.InformationEvent("second");

var api = new TestIngestionApi();
var sink = new SeqAuditSink(api, new CompactJsonFormatter());
var sink = new SeqAuditSink(api, new SeqCompactJsonFormatter());

sink.Emit(evt1);
sink.Emit(evt2);
Expand All @@ -71,7 +70,7 @@ public void AuditSinkPropagatesExceptions()
{
var expected = new Exception("Test");
var api = new TestIngestionApi(_ => throw expected);
var sink = new SeqAuditSink(api, new CompactJsonFormatter());
var sink = new SeqAuditSink(api, new SeqCompactJsonFormatter());

var thrown = Assert.Throws<AggregateException>(() => sink.Emit(Some.InformationEvent()));

Expand Down
7 changes: 3 additions & 4 deletions test/Serilog.Sinks.Seq.Tests/Batched/BatchedSeqSinkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Threading.Tasks;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Compact;
using Serilog.Sinks.Seq.Batched;
using Serilog.Sinks.Seq.Http;
using Serilog.Sinks.Seq.Tests.Support;
Expand All @@ -16,7 +15,7 @@ public class BatchedSeqSinkTests
public void BatchedSinkDisposesIngestionApi()
{
var api = new TestIngestionApi();
var sink = new BatchedSeqSink(api, new CompactJsonFormatter(), null, new ControlledLevelSwitch());
var sink = new BatchedSeqSink(api, new SeqCompactJsonFormatter(), null, new ControlledLevelSwitch());
Assert.False(api.IsDisposed);

sink.Dispose();
Expand All @@ -28,7 +27,7 @@ public void BatchedSinkDisposesIngestionApi()
public async Task EventsAreFormattedIntoPayloads()
{
var api = new TestIngestionApi();
var sink = new BatchedSeqSink(api, new CompactJsonFormatter(), null, new ControlledLevelSwitch());
var sink = new BatchedSeqSink(api, new SeqCompactJsonFormatter(), null, new ControlledLevelSwitch());

await sink.EmitBatchAsync(new[]
{
Expand All @@ -48,7 +47,7 @@ public async Task MinimumLevelIsControlled()
const LogEventLevel originalLevel = LogEventLevel.Debug, newLevel = LogEventLevel.Error;
var levelSwitch = new LoggingLevelSwitch(originalLevel);
var api = new TestIngestionApi(_ => Task.FromResult(new IngestionResult(true, HttpStatusCode.Accepted, newLevel)));
var sink = new BatchedSeqSink(api, new CompactJsonFormatter(), null, new ControlledLevelSwitch(levelSwitch));
var sink = new BatchedSeqSink(api, new SeqCompactJsonFormatter(), null, new ControlledLevelSwitch(levelSwitch));

await sink.EmitBatchAsync(new[] { Some.InformationEvent() });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.IO;
using Serilog.Formatting.Compact;
using Serilog.Sinks.Seq.Tests.Support;
using Xunit;

Expand All @@ -11,7 +10,7 @@ public class ConstrainedBufferedFormatterTests
public void EventsAreFormattedIntoCompactJsonPayloads()
{
var evt = Some.LogEvent("Hello, {Name}!", "Alice");
var formatter = new ConstrainedBufferedFormatter(null, new CompactJsonFormatter());
var formatter = new ConstrainedBufferedFormatter(null, new SeqCompactJsonFormatter());
var json = new StringWriter();
formatter.Format(evt, json);
Assert.Contains("Name\":\"Alice", json.ToString());
Expand All @@ -21,7 +20,7 @@ public void EventsAreFormattedIntoCompactJsonPayloads()
public void PlaceholdersAreLoggedWhenCompactJsonRenderingFails()
{
var evt = Some.LogEvent(new NastyException(), "Hello, {Name}!", "Alice");
var formatter = new ConstrainedBufferedFormatter(null, new CompactJsonFormatter());
var formatter = new ConstrainedBufferedFormatter(null, new SeqCompactJsonFormatter());
var json = new StringWriter();
formatter.Format(evt, json);
var jsonString = json.ToString();
Expand All @@ -33,7 +32,7 @@ public void PlaceholdersAreLoggedWhenCompactJsonRenderingFails()
public void PlaceholdersAreLoggedWhenTheEventSizeLimitIsExceeded()
{
var evt = Some.LogEvent("Hello, {Name}!", new string('a', 10000));
var formatter = new ConstrainedBufferedFormatter(2000, new CompactJsonFormatter());
var formatter = new ConstrainedBufferedFormatter(2000, new SeqCompactJsonFormatter());
var json = new StringWriter();
formatter.Format(evt, json);
var jsonString = json.ToString();
Expand Down
Loading

0 comments on commit bf6c2f8

Please sign in to comment.