From 0f8ccf2b9c27fa38dccfb8e7b07a79de1769ec5e Mon Sep 17 00:00:00 2001 From: Nicholas Blumhardt Date: Wed, 11 Oct 2023 18:47:04 +1000 Subject: [PATCH] Support TraceId and SpanId output template tokens --- sample/ConsoleDemo/ConsoleDemo.csproj | 2 +- sample/SyncWritesDemo/SyncWritesDemo.csproj | 2 +- .../Serilog.Sinks.Console.csproj | 80 ++++++++++--------- .../Output/NewLineTokenRenderer.cs | 2 +- .../Output/OutputTemplateRenderer.cs | 10 ++- .../Output/SpanIdTokenRenderer.cs | 34 ++++++++ .../Output/TraceIdTokenRenderer.cs | 34 ++++++++ .../Output/OutputTemplateRendererTests.cs | 28 ++++++- .../Serilog.Sinks.Console.Tests.csproj | 3 +- 9 files changed, 152 insertions(+), 43 deletions(-) create mode 100644 src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/SpanIdTokenRenderer.cs create mode 100644 src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TraceIdTokenRenderer.cs diff --git a/sample/ConsoleDemo/ConsoleDemo.csproj b/sample/ConsoleDemo/ConsoleDemo.csproj index 81b1a1f..de9024a 100644 --- a/sample/ConsoleDemo/ConsoleDemo.csproj +++ b/sample/ConsoleDemo/ConsoleDemo.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net452;net462;net472;net48;net5.0 + net7.0 diff --git a/sample/SyncWritesDemo/SyncWritesDemo.csproj b/sample/SyncWritesDemo/SyncWritesDemo.csproj index a72595e..de9024a 100644 --- a/sample/SyncWritesDemo/SyncWritesDemo.csproj +++ b/sample/SyncWritesDemo/SyncWritesDemo.csproj @@ -2,7 +2,7 @@ Exe - net5.0 + net7.0 diff --git a/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj b/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj index a15a82c..c1aeaf1 100644 --- a/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj +++ b/src/Serilog.Sinks.Console/Serilog.Sinks.Console.csproj @@ -1,42 +1,50 @@ + + A Serilog sink that writes log events to the console/terminal. + 5.0.0 + Serilog Contributors + net462;net471 + $(TargetFrameworks);netstandard2.1;netstandard2.0;net5.0;net6.0;net7.0 + enable + ../../assets/Serilog.snk + true + true + serilog;console;terminal + icon.png + https://github.com/serilog/serilog-sinks-console + Apache-2.0 + https://github.com/serilog/serilog-sinks-console + git + true + True + Serilog + latest + README.md + - - A Serilog sink that writes log events to the console/terminal. - 4.2.0 - Serilog Contributors - net45;netstandard1.3;netstandard2.0;net5.0 - 8.0 - enable - ../../assets/Serilog.snk - true - true - serilog;console;terminal - icon.png - https://github.com/serilog/serilog-sinks-console - Apache-2.0 - https://github.com/serilog/serilog-sinks-console - git - true - True - - Serilog - latest - + + $(DefineConstants);RUNTIME_INFORMATION + - - $(DefineConstants);RUNTIME_INFORMATION - - - - $(DefineConstants);FEATURE_SPAN - + + $(DefineConstants);FEATURE_SPAN + + + + $(DefineConstants);FEATURE_SPAN + + + + $(DefineConstants);FEATURE_SPAN + - - - - + + + + - - - + + + + diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/NewLineTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/NewLineTokenRenderer.cs index c7174e8..4b072c3 100644 --- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/NewLineTokenRenderer.cs +++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/NewLineTokenRenderer.cs @@ -37,4 +37,4 @@ public override void Render(LogEvent logEvent, TextWriter output) output.WriteLine(); } } -} \ No newline at end of file +} diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs index c62ab67..f922290 100644 --- a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs +++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/OutputTemplateRenderer.cs @@ -50,6 +50,14 @@ public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormat { renderers.Add(new NewLineTokenRenderer(pt.Alignment)); } + else if (pt.PropertyName == OutputProperties.TraceIdPropertyName) + { + renderers.Add(new TraceIdTokenRenderer(theme, pt)); + } + else if (pt.PropertyName == OutputProperties.SpanIdPropertyName) + { + renderers.Add(new SpanIdTokenRenderer(theme, pt)); + } else if (pt.PropertyName == OutputProperties.ExceptionPropertyName) { renderers.Add(new ExceptionTokenRenderer(theme, pt)); @@ -62,7 +70,7 @@ public OutputTemplateRenderer(ConsoleTheme theme, string outputTemplate, IFormat { renderers.Add(new TimestampTokenRenderer(theme, pt, formatProvider)); } - else if (pt.PropertyName == "Properties") + else if (pt.PropertyName == OutputProperties.PropertiesPropertyName) { renderers.Add(new PropertiesTokenRenderer(theme, pt, template, formatProvider)); } diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/SpanIdTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/SpanIdTokenRenderer.cs new file mode 100644 index 0000000..394a7da --- /dev/null +++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/SpanIdTokenRenderer.cs @@ -0,0 +1,34 @@ +using System.IO; +using Serilog.Events; +using Serilog.Parsing; +using Serilog.Sinks.SystemConsole.Rendering; +using Serilog.Sinks.SystemConsole.Themes; + +namespace Serilog.Sinks.SystemConsole.Output; + +class SpanIdTokenRenderer : OutputTemplateTokenRenderer +{ + readonly ConsoleTheme _theme; + readonly Alignment? _alignment; + + public SpanIdTokenRenderer(ConsoleTheme theme, PropertyToken spanIdToken) + { + _theme = theme; + _alignment = spanIdToken.Alignment; + } + + public override void Render(LogEvent logEvent, TextWriter output) + { + if (logEvent.SpanId is not { } spanId) + return; + + var _ = 0; + using (_theme.Apply(output, ConsoleThemeStyle.Text, ref _)) + { + if (_alignment is {} alignment) + Padding.Apply(output, spanId.ToString(), alignment); + else + output.Write(spanId); + } + } +} \ No newline at end of file diff --git a/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TraceIdTokenRenderer.cs b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TraceIdTokenRenderer.cs new file mode 100644 index 0000000..c2be4d0 --- /dev/null +++ b/src/Serilog.Sinks.Console/Sinks/SystemConsole/Output/TraceIdTokenRenderer.cs @@ -0,0 +1,34 @@ +using System.IO; +using Serilog.Events; +using Serilog.Parsing; +using Serilog.Sinks.SystemConsole.Rendering; +using Serilog.Sinks.SystemConsole.Themes; + +namespace Serilog.Sinks.SystemConsole.Output; + +class TraceIdTokenRenderer : OutputTemplateTokenRenderer +{ + readonly ConsoleTheme _theme; + readonly Alignment? _alignment; + + public TraceIdTokenRenderer(ConsoleTheme theme, PropertyToken traceIdToken) + { + _theme = theme; + _alignment = traceIdToken.Alignment; + } + + public override void Render(LogEvent logEvent, TextWriter output) + { + if (logEvent.TraceId is not { } traceId) + return; + + var _ = 0; + using (_theme.Apply(output, ConsoleThemeStyle.Text, ref _)) + { + if (_alignment is {} alignment) + Padding.Apply(output, traceId.ToString(), alignment); + else + output.Write(traceId); + } + } +} \ No newline at end of file diff --git a/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs b/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs index 9dd5d5f..59bbedc 100644 --- a/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs +++ b/test/Serilog.Sinks.Console.Tests/Output/OutputTemplateRendererTests.cs @@ -1,8 +1,10 @@ using System; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using Serilog.Events; +using Serilog.Parsing; using Serilog.Sinks.Console.Tests.Support; using Serilog.Sinks.SystemConsole.Output; using Serilog.Sinks.SystemConsole.Themes; @@ -188,7 +190,7 @@ public SizeFormatter(IFormatProvider innerFormatProvider) _innerFormatProvider = innerFormatProvider; } - public object? GetFormat(Type? formatType) + public object GetFormat(Type? formatType) { return formatType == typeof(ICustomFormatter) ? this : _innerFormatProvider.GetFormat(formatType) ?? this; } @@ -374,5 +376,29 @@ public void FormatProviderWithDestructuredProperties(string format, bool shouldU Assert.Contains(expectedFormattedDate, sw.ToString()); Assert.Contains(expectedFormattedNumber, sw.ToString()); } + + [Fact] + public void TraceAndSpanAreEmptyWhenAbsent() + { + var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{TraceId}/{SpanId}", CultureInfo.InvariantCulture); + var evt = DelegatingSink.GetLogEvent(l => l.Information("Hello, world")); + var sw = new StringWriter(); + formatter.Format(evt, sw); + Assert.Equal("/", sw.ToString()); + } + + [Fact] + public void TraceAndSpanAreIncludedWhenPresent() + { + var traceId = ActivityTraceId.CreateRandom(); + var spanId = ActivitySpanId.CreateRandom(); + var formatter = new OutputTemplateRenderer(ConsoleTheme.None, "{TraceId}/{SpanId}", CultureInfo.InvariantCulture); + var evt = new LogEvent(DateTimeOffset.Now, LogEventLevel.Debug, null, + new MessageTemplate(Enumerable.Empty()), Enumerable.Empty(), + traceId, spanId); + var sw = new StringWriter(); + formatter.Format(evt, sw); + Assert.Equal($"{traceId}/{spanId}", sw.ToString()); + } } } diff --git a/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj b/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj index 57b8025..472965f 100644 --- a/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj +++ b/test/Serilog.Sinks.Console.Tests/Serilog.Sinks.Console.Tests.csproj @@ -1,12 +1,11 @@  - netcoreapp2.1;netcoreapp2.2;netcoreapp3.0;netcoreapp3.1;net452;net462;net472;net48;net5.0 + net7.0 true ../../assets/Serilog.snk true true - 8.0 enable