Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sample/Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using System.Threading;
using Serilog;
using Serilog.Core;
using Serilog.Debugging;

SelfLog.Enable(Console.Error);

// By sharing between the Seq sink and logger itself,
// Seq API keys can be used to control the level of the whole logging pipeline.
Expand Down
4 changes: 2 additions & 2 deletions src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="All" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Serilog.Sinks.Seq.Conventions;
/// Maintains verbatim processing of property names. A property named <c>"a.b"</c> will be transmitted to Seq as a
/// scalar value with name <c>"a.b"</c>.
/// </summary>
class PreserveDottedPropertyNames: IDottedPropertyNameConvention
sealed class PreserveDottedPropertyNames: IDottedPropertyNameConvention
{
/// <inheritdoc />
public IReadOnlyDictionary<string, LogEventPropertyValue> ProcessDottedPropertyNames(IReadOnlyDictionary<string, LogEventPropertyValue> maybeDotted)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
namespace Serilog.Sinks.Seq.Conventions;

/// <summary>
/// Experimental. Unflatten property names. A property with name <c>"a.b"</c> will be transmitted to Seq as
/// Nest (un-flatten) properties with dotted names. A property with name <c>"a.b"</c> will be transmitted to Seq as
/// a structure with name <c>"a"</c>, and one member <c>"b"</c>.
/// </summary>
/// <remarks>This behavior is enabled when the <c>Serilog.Parsing.MessageTemplateParser.AcceptDottedPropertyNames</c>
/// <see cref="AppContext"/> switch is set to value <c langword="true"/>.</remarks>
class UnflattenDottedPropertyNames: IDottedPropertyNameConvention
sealed class UnflattenDottedPropertyNames: IDottedPropertyNameConvention
{
const int MaxDepth = 10;

Expand Down
22 changes: 11 additions & 11 deletions src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,27 @@ namespace Serilog.Sinks.Seq;
/// </summary>
/// <remarks>Modified from <c>Serilog.Formatting.Compact.CompactJsonFormatter</c> to add
/// implicit SerilogTracing span support.</remarks>
public class SeqCompactJsonFormatter: ITextFormatter
public sealed class SeqCompactJsonFormatter: ITextFormatter
{
readonly IDottedPropertyNameConvention _dottedPropertyNameConvention;
readonly JsonValueFormatter _valueFormatter;
readonly IFormatProvider _formatProvider;

readonly IDottedPropertyNameConvention _dottedPropertyNameConvention;

/// <summary>
/// Construct a <see cref="SeqCompactJsonFormatter"/>.
/// </summary>
/// <param name="valueFormatter">A value formatter for <see cref="LogEventPropertyValue"/>s on the event.</param>
/// <param name="formatProvider">An <see cref="IFormatProvider"/> that will be used to render log event tokens.</param>
public SeqCompactJsonFormatter(IFormatProvider? formatProvider = null, JsonValueFormatter? valueFormatter = null)
/// <param name="preserveDottedPropertyNames">If <c langword="true"/>, log event property names that
/// contain <c>.</c> will be sent to Seq as-is. Otherwise, properties with dotted names will be converted
/// into nested objects.</param>
public SeqCompactJsonFormatter(IFormatProvider? formatProvider = null, JsonValueFormatter? valueFormatter = null, bool preserveDottedPropertyNames = false)
{
var acceptDottedPropertyNames = AppContext.TryGetSwitch("Serilog.Parsing.MessageTemplateParser.AcceptDottedPropertyNames", out var accept) && accept;

_dottedPropertyNameConvention = acceptDottedPropertyNames ?
new UnflattenDottedPropertyNames() :
new PreserveDottedPropertyNames();

_formatProvider = formatProvider ?? CultureInfo.InvariantCulture;
_valueFormatter = valueFormatter ?? new("$type");
_dottedPropertyNameConvention = preserveDottedPropertyNames
? new PreserveDottedPropertyNames()
: new UnflattenDottedPropertyNames();
}

/// <summary>
Expand Down Expand Up @@ -182,4 +182,4 @@ public void FormatEvent(LogEvent logEvent, TextWriter output)

output.Write('}');
}
}
}
8 changes: 8 additions & 0 deletions test/Serilog.Sinks.Seq.Tests/SeqCompactJsonFormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ public void MultiplePropertiesAreDelimited()
AssertValidJson(log => log.Information("Property {First} and {Second}", "One", "Two"));
}

[Fact]
public void DottedPropertiesAreNested()
{
dynamic evt = AssertValidJson(log => log.Information("Property {a.b} and {a.c}", "One", "Two"));
Assert.Equal("One", (string)evt.a.b);
Assert.Equal("Two", (string)evt.a.c);
}

[Fact]
public void ExceptionsAreFormattedToValidJson()
{
Expand Down