diff --git a/sample/Sample/Program.cs b/sample/Sample/Program.cs
index 898cddc..f2f15b5 100644
--- a/sample/Sample/Program.cs
+++ b/sample/Sample/Program.cs
@@ -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.
diff --git a/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj b/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
index 74e1f0c..6ffec04 100644
--- a/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
+++ b/src/Serilog.Sinks.Seq/Serilog.Sinks.Seq.csproj
@@ -29,9 +29,9 @@
-
+
-
+
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs
index f25107c..523a84f 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/PreserveDottedPropertyNames.cs
@@ -21,7 +21,7 @@ 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
+sealed class PreserveDottedPropertyNames: IDottedPropertyNameConvention
{
///
public IReadOnlyDictionary ProcessDottedPropertyNames(IReadOnlyDictionary maybeDotted)
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs
index e3406ae..11fd55e 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/Conventions/UnflattenDottedPropertyNames.cs
@@ -21,12 +21,12 @@
namespace Serilog.Sinks.Seq.Conventions;
///
-/// Experimental. Unflatten property names. A property with name "a.b" will be transmitted to Seq as
+/// Nest (un-flatten) properties with dotted 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
+sealed class UnflattenDottedPropertyNames: IDottedPropertyNameConvention
{
const int MaxDepth = 10;
diff --git a/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs b/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
index 22b059f..03e40fb 100644
--- a/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
+++ b/src/Serilog.Sinks.Seq/Sinks/Seq/SeqCompactJsonFormatter.cs
@@ -32,27 +32,27 @@ namespace Serilog.Sinks.Seq;
///
/// Modified from Serilog.Formatting.Compact.CompactJsonFormatter to add
/// implicit SerilogTracing span support.
-public class SeqCompactJsonFormatter: ITextFormatter
+public sealed class SeqCompactJsonFormatter: ITextFormatter
{
- readonly IDottedPropertyNameConvention _dottedPropertyNameConvention;
readonly JsonValueFormatter _valueFormatter;
readonly IFormatProvider _formatProvider;
-
+ readonly IDottedPropertyNameConvention _dottedPropertyNameConvention;
+
///
/// Construct a .
///
/// A value formatter for s on the event.
/// An that will be used to render log event tokens.
- public SeqCompactJsonFormatter(IFormatProvider? formatProvider = null, JsonValueFormatter? valueFormatter = null)
+ /// If , log event property names that
+ /// contain . will be sent to Seq as-is. Otherwise, properties with dotted names will be converted
+ /// into nested objects.
+ 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();
}
///
@@ -182,4 +182,4 @@ public void FormatEvent(LogEvent logEvent, TextWriter output)
output.Write('}');
}
-}
\ No newline at end of file
+}
diff --git a/test/Serilog.Sinks.Seq.Tests/SeqCompactJsonFormatterTests.cs b/test/Serilog.Sinks.Seq.Tests/SeqCompactJsonFormatterTests.cs
index 8ef87e6..c35b829 100644
--- a/test/Serilog.Sinks.Seq.Tests/SeqCompactJsonFormatterTests.cs
+++ b/test/Serilog.Sinks.Seq.Tests/SeqCompactJsonFormatterTests.cs
@@ -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()
{