using System.Diagnostics; using Serilog; using Serilog.Core; using Serilog.Events; using Serilog.Sinks.InMemory; using ZB.MOM.WW.Telemetry; using ZB.MOM.WW.Telemetry.Serilog; namespace ZB.MOM.WW.Telemetry.Serilog.Tests; public sealed class TraceContextEnricherTests { private const string SourceName = "ZB.MOM.WW.Telemetry.Serilog.Tests.TraceContext"; private static Logger BuildLogger(InMemorySink sink) => new LoggerConfiguration() .Enrich.With(new TraceContextEnricher()) .WriteTo.Sink(sink) .CreateLogger(); private static string? ScalarOrNull(LogEvent logEvent, string propertyName) => logEvent.Properties.TryGetValue(propertyName, out var value) && value is ScalarValue scalar ? scalar.Value?.ToString() : null; [Fact] public void Active_activity_stamps_trace_id_and_span_id() { using var listener = new ActivityListener { ShouldListenTo = source => source.Name == SourceName, Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded, }; ActivitySource.AddActivityListener(listener); using var activitySource = new ActivitySource(SourceName); var sink = new InMemorySink(); using var logger = BuildLogger(sink); using var activity = activitySource.StartActivity("unit-test"); Assert.NotNull(activity); Assert.NotNull(Activity.Current); logger.Information("traced"); var logEvent = Assert.Single(sink.LogEvents); Assert.Equal(Activity.Current!.TraceId.ToString(), ScalarOrNull(logEvent, "trace_id")); Assert.Equal(Activity.Current!.SpanId.ToString(), ScalarOrNull(logEvent, "span_id")); } [Fact] public void No_active_activity_omits_trace_id_and_span_id() { Assert.Null(Activity.Current); var sink = new InMemorySink(); using var logger = BuildLogger(sink); logger.Information("untraced"); var logEvent = Assert.Single(sink.LogEvents); Assert.False(logEvent.Properties.ContainsKey("trace_id")); Assert.False(logEvent.Properties.ContainsKey("span_id")); } }