diff --git a/README.md b/README.md
index 82f7062..ab5f3e8 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,10 @@ A Serilog sink that writes events to the [Seq](https://datalust.co/seq) structur
[
](https://nuget.org/packages/serilog.sinks.seq)
+> [!TIP]
+> If you would like to see timing and dependency information in Seq, [SerilogTracing](https://github.com/serilog-tracing/serilog-tracing) is a Serilog extension that supports both logs and traces.
+
+
### Getting started
Install _Serilog.Sinks.Seq_ into your .NET project:
diff --git a/sample/BlazorWasm/BlazorWasm.csproj b/sample/BlazorWasm/BlazorWasm.csproj
index 4054529..d0fde33 100644
--- a/sample/BlazorWasm/BlazorWasm.csproj
+++ b/sample/BlazorWasm/BlazorWasm.csproj
@@ -7,8 +7,8 @@
-
-
+
+
diff --git a/src/Serilog.Sinks.Seq/SeqLoggerConfigurationExtensions.cs b/src/Serilog.Sinks.Seq/SeqLoggerConfigurationExtensions.cs
index 39b746c..414d536 100644
--- a/src/Serilog.Sinks.Seq/SeqLoggerConfigurationExtensions.cs
+++ b/src/Serilog.Sinks.Seq/SeqLoggerConfigurationExtensions.cs
@@ -19,7 +19,6 @@
using Serilog.Sinks.Seq;
using System.Net.Http;
using Serilog.Formatting;
-using Serilog.Sinks.PeriodicBatching;
using Serilog.Sinks.Seq.Batched;
using Serilog.Sinks.Seq.Audit;
using Serilog.Sinks.Seq.Http;
@@ -98,8 +97,6 @@ public static LoggerConfiguration Seq(
var formatter = payloadFormatter ?? CreateDefaultFormatter();
var ingestionApi = new SeqIngestionApiClient(serverUrl, apiKey, messageHandler);
- ILogEventSink sink;
-
if (bufferBaseFilename == null)
{
var batchedSink = new BatchedSeqSink(
@@ -108,29 +105,29 @@ public static LoggerConfiguration Seq(
eventBodyLimitBytes,
controlledSwitch);
- var options = new PeriodicBatchingSinkOptions
+ var options = new BatchingOptions
{
BatchSizeLimit = batchPostingLimit,
- Period = defaultedPeriod,
+ BufferingTimeLimit = defaultedPeriod,
QueueLimit = queueSizeLimit
};
-
- sink = new PeriodicBatchingSink(batchedSink, options);
- }
- else
- {
- sink = new DurableSeqSink(
- ingestionApi,
- formatter,
- bufferBaseFilename,
- batchPostingLimit,
- defaultedPeriod,
- bufferSizeLimitBytes,
- eventBodyLimitBytes,
- controlledSwitch,
- retainedInvalidPayloadsLimitBytes);
+
+ return loggerSinkConfiguration.Conditional(
+ controlledSwitch.IsIncluded,
+ wt => wt.Sink(batchedSink, options, restrictedToMinimumLevel, levelSwitch: null));
}
-
+
+ var sink = new DurableSeqSink(
+ ingestionApi,
+ formatter,
+ bufferBaseFilename,
+ batchPostingLimit,
+ defaultedPeriod,
+ bufferSizeLimitBytes,
+ eventBodyLimitBytes,
+ controlledSwitch,
+ retainedInvalidPayloadsLimitBytes);
+
return loggerSinkConfiguration.Conditional(
controlledSwitch.IsIncluded,
wt => wt.Sink(sink, restrictedToMinimumLevel, levelSwitch: null));
diff --git a/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj b/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
index 5b5db9a..917f880 100644
--- a/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
+++ b/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
@@ -2,7 +2,7 @@
A Serilog sink that writes events to Seq using newline-delimited JSON and HTTP/HTTPS.
- 7.0.1
+ 8.0.0
Serilog Contributors;Serilog.Sinks.Seq Contributors;Datalust Pty Ltd
Copyright © Serilog Contributors, Serilog.Sinks.Seq Contributors, Datalust Pty Ltd.
netstandard2.0;net6.0
@@ -19,7 +19,7 @@
https://github.com/datalust/serilog-sinks-seq
git
true
- 10
+ 12
enable
README.md
@@ -29,8 +29,7 @@
-
-
+
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Batched/BatchedSeqSink.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Batched/BatchedSeqSink.cs
index 4a4ef79..85c16de 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/Batched/BatchedSeqSink.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Batched/BatchedSeqSink.cs
@@ -15,17 +15,16 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
+using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
-using Serilog.Sinks.PeriodicBatching;
using Serilog.Sinks.Seq.Http;
namespace Serilog.Sinks.Seq.Batched;
///
-/// The default Seq sink, for use in combination with .
+/// The default Seq sink.
///
sealed class BatchedSeqSink : IBatchedLogEventSink, IDisposable
{
@@ -60,11 +59,11 @@ public async Task OnEmptyBatchAsync()
if (_controlledSwitch.IsActive &&
_nextRequiredLevelCheckUtc < DateTime.UtcNow)
{
- await EmitBatchAsync(Enumerable.Empty());
+ await EmitBatchAsync([]);
}
}
- public async Task EmitBatchAsync(IEnumerable events)
+ public async Task EmitBatchAsync(IReadOnlyCollection events)
{
_nextRequiredLevelCheckUtc = DateTime.UtcNow.Add(RequiredLevelCheckInterval);
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs
new file mode 100644
index 0000000..f25107c
--- /dev/null
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs
@@ -0,0 +1,31 @@
+// Copyright © 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.Collections.Generic;
+using Serilog.Events;
+
+namespace Serilog.Sinks.Seq.Conventions;
+
+///
+/// Maintains verbatim processing of property names. A property named "a.b" will be transmitted to Seq as a
+/// scalar value with name "a.b".
+///
+class PreserveDottedPropertyNames: IDottedPropertyNameConvention
+{
+ ///
+ public IReadOnlyDictionary ProcessDottedPropertyNames(IReadOnlyDictionary maybeDotted)
+ {
+ return maybeDotted;
+ }
+}
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs
new file mode 100644
index 0000000..e3406ae
--- /dev/null
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs
@@ -0,0 +1,131 @@
+// Copyright © 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.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Serilog.Events;
+
+namespace Serilog.Sinks.Seq.Conventions;
+
+///
+/// Experimental. Unflatten property names. A property with name "a.b" will be transmitted to Seq as
+/// a structure with name "a", and one member "b".
+///
+/// This behavior is enabled when the Serilog.Parsing.MessageTemplateParser.AcceptDottedPropertyNames
+/// switch is set to value .
+class UnflattenDottedPropertyNames: IDottedPropertyNameConvention
+{
+ const int MaxDepth = 10;
+
+ ///
+ public IReadOnlyDictionary ProcessDottedPropertyNames(IReadOnlyDictionary maybeDotted)
+ {
+ return DottedToNestedRecursive(maybeDotted, 0);
+ }
+
+ static IReadOnlyDictionary DottedToNestedRecursive(IReadOnlyDictionary maybeDotted, int depth)
+ {
+ if (depth == MaxDepth)
+ return maybeDotted;
+
+ // Assume that the majority of entries will be bare or have unique prefixes.
+ var result = new Dictionary(maybeDotted.Count);
+
+ // Sorted for determinism.
+ var dotted = new SortedDictionary(StringComparer.Ordinal);
+
+ // First - give priority to bare names, since these would otherwise be claimed by the parents of further nested
+ // layers and we'd have nowhere to put them when resolving conflicts. (Dotted entries that conflict can keep their dotted keys).
+
+ foreach (var kv in maybeDotted)
+ {
+ if (IsDottedIdentifier(kv.Key))
+ {
+ // Stash for processing in the next stage.
+ dotted.Add(kv.Key, kv.Value);
+ }
+ else
+ {
+ result.Add(kv.Key, kv.Value);
+ }
+ }
+
+ // Then - for dotted keys with a prefix not already present in the result, convert to structured data and add to
+ // the result. Any set of dotted names that collide with a preexisting key will be left as-is.
+
+ string? prefix = null;
+ Dictionary? nested = null;
+ foreach (var kv in dotted)
+ {
+ var (newPrefix, rem) = TakeFirstIdentifier(kv.Key);
+
+ if (prefix != null && prefix != newPrefix)
+ {
+ result.Add(prefix, MakeStructureValue(DottedToNestedRecursive(nested!, depth + 1)));
+ prefix = null;
+ nested = null;
+ }
+
+ if (nested != null && !nested.ContainsKey(rem))
+ {
+ prefix = newPrefix;
+ nested.Add(rem, kv.Value);
+ }
+ else if (nested == null && !result.ContainsKey(newPrefix))
+ {
+ prefix = newPrefix;
+ nested = new () { { rem, kv.Value } };
+ }
+ else
+ {
+ result.Add(kv.Key, kv.Value);
+ }
+ }
+
+ if (prefix != null)
+ {
+ result[prefix] = MakeStructureValue(DottedToNestedRecursive(nested!, depth + 1));
+ }
+
+ return result;
+ }
+
+ static LogEventPropertyValue MakeStructureValue(IReadOnlyDictionary properties)
+ {
+ return new StructureValue(properties.Select(kv => new LogEventProperty(kv.Key, kv.Value)), typeTag: null);
+ }
+
+ internal static bool IsDottedIdentifier(string key) =>
+ key.Contains('.') &&
+ !key.StartsWith(".", StringComparison.Ordinal) &&
+ !key.EndsWith(".", StringComparison.Ordinal) &&
+ key.Split('.').All(IsIdentifier);
+
+ static bool IsIdentifier(string s) => s.Length != 0 &&
+ !char.IsDigit(s[0]) &&
+ s.All(ch => char.IsLetter(ch) || char.IsDigit(ch) || ch == '_');
+
+ static (string, string) TakeFirstIdentifier(string dottedIdentifier)
+ {
+ // We can do this simplistically because keys in `dotted` conform to `IsDottedName`.
+ Debug.Assert(IsDottedIdentifier(dottedIdentifier));
+
+ var firstDot = dottedIdentifier.IndexOf('.');
+ var prefix = dottedIdentifier.Substring(0, firstDot);
+ var rem = dottedIdentifier.Substring(firstDot + 1);
+ return (prefix, rem);
+ }
+}
\ No newline at end of file
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/BookmarkFile.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/BookmarkFile.cs
index e026c62..d0e661a 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/BookmarkFile.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/BookmarkFile.cs
@@ -39,7 +39,7 @@ public FileSetPosition TryReadBookmark()
if (current != null)
{
- var parts = current.Split(new[] { ":::" }, StringSplitOptions.RemoveEmptyEntries);
+ var parts = current.Split([":::"], StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
{
return new FileSetPosition(long.Parse(parts[0]), parts[1]);
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/ExponentialBackoffConnectionSchedule.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/ExponentialBackoffConnectionSchedule.cs
index 3a02311..c5425b6 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/ExponentialBackoffConnectionSchedule.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Durable/ExponentialBackoffConnectionSchedule.cs
@@ -17,7 +17,7 @@
namespace Serilog.Sinks.Seq.Durable;
///
-/// Based on the BatchedConnectionStatus class from .
+/// Based on the BatchedConnectionStatus class from Serilog.Sinks.PeriodicBatching.
///
sealed class ExponentialBackoffConnectionSchedule
{
@@ -30,7 +30,7 @@ sealed class ExponentialBackoffConnectionSchedule
public ExponentialBackoffConnectionSchedule(TimeSpan period)
{
- if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(period), "The connection retry period must be a positive timespan");
+ if (period < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(period), "The connection retry period must be a positive timespan.");
_period = period;
}
@@ -55,7 +55,7 @@ public TimeSpan NextInterval
// Second failure, start ramping up the interval - first 2x, then 4x, ...
var backoffFactor = Math.Pow(2, (_failuresSinceSuccessfulConnection - 1));
- // If the period is ridiculously short, give it a boost so we get some
+ // If the period is ridiculously short, give it a boost so that we get some
// visible backoff.
var backoffPeriod = Math.Max(_period.Ticks, MinimumBackoffPeriod.Ticks);
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/IDottedPropertyNameConvention.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/IDottedPropertyNameConvention.cs
new file mode 100644
index 0000000..9cedffc
--- /dev/null
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/IDottedPropertyNameConvention.cs
@@ -0,0 +1,33 @@
+// Copyright © 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.Collections.Generic;
+using Serilog.Events;
+
+namespace Serilog.Sinks.Seq;
+
+///
+/// Enables switching between the experimental "unflattening" behavior applied to dotted property names, and the
+/// regular verbatim property name handling.
+///
+interface IDottedPropertyNameConvention
+{
+ ///
+ /// Convert the properties in into the form specified by the current property
+ /// name processing convention.
+ ///
+ /// The properties associated with a log event.
+ /// The processed properties.
+ IReadOnlyDictionary ProcessDottedPropertyNames(IReadOnlyDictionary maybeDotted);
+}
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
index 591ae89..9bdfaca 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
@@ -1,4 +1,4 @@
-// Copyright 2016 Serilog Contributors
+// Copyright © Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
using Serilog.Formatting;
using Serilog.Formatting.Json;
using Serilog.Parsing;
+using Serilog.Sinks.Seq.Conventions;
+
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable PossibleMultipleEnumeration
@@ -33,8 +35,13 @@ namespace Serilog.Sinks.Seq;
/// implicit SerilogTracing span support.
public class SeqCompactJsonFormatter: ITextFormatter
{
- readonly JsonValueFormatter _valueFormatter = new("$type");
+ static readonly IDottedPropertyNameConvention DottedPropertyNameConvention =
+ AppContext.TryGetSwitch("Serilog.Parsing.MessageTemplateParser.AcceptDottedPropertyNames", out var accept) && accept ?
+ new UnflattenDottedPropertyNames() :
+ new PreserveDottedPropertyNames();
+ readonly JsonValueFormatter _valueFormatter = new("$type");
+
///
/// Format the log event into the output. Subsequent events will be newline-delimited.
///
@@ -139,8 +146,9 @@ public static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFo
output.Write('\"');
}
}
-
- foreach (var property in logEvent.Properties)
+
+ var properties = DottedPropertyNameConvention.ProcessDottedPropertyNames(logEvent.Properties);
+ foreach (var property in properties)
{
var name = property.Key;
diff --git a/test/Serilog.Sinks.Seq.Tests/Conventions/UnflattenDottedPropertyNamesTests.cs b/test/Serilog.Sinks.Seq.Tests/Conventions/UnflattenDottedPropertyNamesTests.cs
new file mode 100644
index 0000000..e6bbf15
--- /dev/null
+++ b/test/Serilog.Sinks.Seq.Tests/Conventions/UnflattenDottedPropertyNamesTests.cs
@@ -0,0 +1,122 @@
+using System.Collections.Generic;
+using System.Linq;
+using Serilog.Events;
+using Serilog.Sinks.Seq.Conventions;
+using Xunit;
+
+namespace Serilog.Sinks.Seq.Tests.Conventions;
+
+public class UnflattenDottedPropertyNamesTests
+{
+ [Fact]
+ public void DottedToNestedWorks()
+ {
+ var someDotted = new Dictionary
+ {
+ ["dotnet.ilogger.category"] = new ScalarValue("Test.App"),
+ ["environment.name"] = new ScalarValue("Production"),
+ ["environment.region"] = new ScalarValue("us-west-2"),
+ ["environment.beverage.name"] = new ScalarValue("coffee"),
+ ["environment.domains"] = new StructureValue(
+ [
+ new LogEventProperty("example.com", new ScalarValue(42)),
+ new LogEventProperty("datalust.co", new ScalarValue(43))
+ ]),
+ ["scope"] = new StructureValue([]),
+ ["scope.name"] = new ScalarValue("Gerald"),
+ ["vegetable"] = new ScalarValue("Potato"),
+ ["Scope"] = new ScalarValue("Periscope"),
+ [".gitattributes"] = new ScalarValue("Text")
+ };
+
+ var expected = new Dictionary
+ {
+ ["dotnet"] = new StructureValue(
+ [
+ new LogEventProperty("ilogger", new StructureValue(
+ [
+ new LogEventProperty("category", new ScalarValue("Test App"))
+ ]))
+ ]),
+ ["environment"] = new StructureValue(
+ [
+ new LogEventProperty("name", new ScalarValue("Production")),
+ new LogEventProperty("region", new ScalarValue("us-west-2")),
+ new LogEventProperty("beverage", new StructureValue(
+ [
+ new LogEventProperty("name", new ScalarValue("coffee"))
+ ])),
+ new LogEventProperty("domains", new StructureValue(
+ [
+ new LogEventProperty("example.com", new ScalarValue(42)),
+ new LogEventProperty("datalust.co", new ScalarValue(43))
+ ]))
+ ]),
+ ["scope"] = new StructureValue([]),
+ ["scope.name"] = new ScalarValue("Gerald"),
+ ["vegetable"] = new ScalarValue("Potato"),
+ ["Scope"] = new ScalarValue("Periscope"),
+ [".gitattributes"] = new ScalarValue("Text")
+ };
+
+ var actual = new UnflattenDottedPropertyNames().ProcessDottedPropertyNames(someDotted);
+
+ Assert.Equal(expected.Count, actual.Count);
+ foreach (var expectedProperty in expected)
+ {
+ Assert.True(actual.TryGetValue(expectedProperty.Key, out var actualProperty));
+ AssertEquivalentValue(expectedProperty.Value, expectedProperty.Value);
+ }
+ }
+
+ [Theory]
+ [InlineData("", false)]
+ [InlineData(".", false)]
+ [InlineData("..", false)]
+ [InlineData(".a", false)]
+ [InlineData("a.", false)]
+ [InlineData("a..b", false)]
+ [InlineData("a.b..c", false)]
+ [InlineData("a.b.", false)]
+ [InlineData("a. .b", false)]
+ [InlineData("1.0", false)]
+ [InlineData("1", false)]
+ [InlineData("a", false)]
+ [InlineData("abc", false)]
+ [InlineData("a.b", true)]
+ [InlineData("a1.bc._._xd.e_", true)]
+ public void OnlyProcessesValidDottedNames(string key, bool isValid)
+ {
+ var actual = UnflattenDottedPropertyNames.IsDottedIdentifier(key);
+ Assert.Equal(isValid, actual);
+ }
+
+ static void AssertEquivalentValue(LogEventPropertyValue expected, LogEventPropertyValue actual)
+ {
+ switch (expected, actual)
+ {
+ case (ScalarValue expectedScalar, ScalarValue actualScalar):
+ {
+ Assert.Equal(expectedScalar.Value, actualScalar.Value);
+ break;
+ }
+ case (StructureValue expectedStructure, StructureValue actualStructure):
+ {
+ Assert.Equal(expectedStructure.TypeTag, actualStructure.TypeTag);
+ Assert.Equal(expectedStructure.Properties.Count, actualStructure.Properties.Count);
+ var actualProperties = actualStructure.Properties.ToDictionary(p => p.Name, p => p.Value);
+ foreach (var expectedProperty in expectedStructure.Properties)
+ {
+ var actualValue = Assert.Contains(expectedProperty.Name, actualProperties);
+ AssertEquivalentValue(expectedProperty.Value, actualValue);
+ }
+ break;
+ }
+ default:
+ {
+ Assert.Equal(expected, actual);
+ break;
+ }
+ }
+ }
+}
diff --git a/test/Serilog.Sinks.Seq.Tests/Durable/PayloadReaderTests.cs b/test/Serilog.Sinks.Seq.Tests/Durable/PayloadReaderTests.cs
index c1487c6..dbbba44 100644
--- a/test/Serilog.Sinks.Seq.Tests/Durable/PayloadReaderTests.cs
+++ b/test/Serilog.Sinks.Seq.Tests/Durable/PayloadReaderTests.cs
@@ -17,7 +17,9 @@ public void ReadsEventsFromBufferFiles()
{
using var tmp = new TempFolder();
var fn = tmp.AllocateFilename("clef");
- var lines = IOFile.ReadAllText(Path.Combine("Resources", "ThreeBufferedEvents.clef.txt"), Encoding.UTF8).Split(new [] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
+ var lines = IOFile.ReadAllText(Path.Combine("Resources", "ThreeBufferedEvents.clef.txt"), Encoding.UTF8)
+ // ReSharper disable once RedundantCast
+ .Split((char[])['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
using (var f = IOFile.Create(fn))
using (var fw = new StreamWriter(f, Encoding.UTF8))
{
@@ -42,7 +44,9 @@ public void ReadsEventsFromRawBufferFiles()
{
using var tmp = new TempFolder();
var fn = tmp.AllocateFilename("json");
- var lines = IOFile.ReadAllText(Path.Combine("Resources", "ThreeBufferedEvents.json.txt"), Encoding.UTF8).Split(new [] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
+ var lines = IOFile.ReadAllText(Path.Combine("Resources", "ThreeBufferedEvents.json.txt"), Encoding.UTF8)
+ // ReSharper disable once RedundantCast
+ .Split((char[])['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
using (var f = IOFile.Create(fn))
using (var fw = new StreamWriter(f, Encoding.UTF8))
{
diff --git a/test/Serilog.Sinks.Seq.Tests/Serilog.Sinks.Seq.Tests.csproj b/test/Serilog.Sinks.Seq.Tests/Serilog.Sinks.Seq.Tests.csproj
index acb05e2..c429307 100644
--- a/test/Serilog.Sinks.Seq.Tests/Serilog.Sinks.Seq.Tests.csproj
+++ b/test/Serilog.Sinks.Seq.Tests/Serilog.Sinks.Seq.Tests.csproj
@@ -28,13 +28,13 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+