diff --git a/src/Serilog.Expressions/Expressions/BuiltInProperty.cs b/src/Serilog.Expressions/Expressions/BuiltInProperty.cs index d6892d8..c306662 100644 --- a/src/Serilog.Expressions/Expressions/BuiltInProperty.cs +++ b/src/Serilog.Expressions/Expressions/BuiltInProperty.cs @@ -25,4 +25,6 @@ static class BuiltInProperty public const string Properties = "p"; public const string Renderings = "r"; public const string EventId = "i"; + public const string TraceId = "tr"; + public const string SpanId = "sp"; } \ No newline at end of file diff --git a/src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs b/src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs index e20c2c6..389aaa1 100644 --- a/src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs +++ b/src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs @@ -206,6 +206,10 @@ protected override ExpressionBody Transform(AmbientNameExpression px) BuiltInProperty.Message => Splice(context => new ScalarValue(Intrinsics.RenderMessage(formatter, context))), BuiltInProperty.Exception => Splice(context => context.LogEvent.Exception == null ? null : new ScalarValue(context.LogEvent.Exception)), + BuiltInProperty.TraceId => Splice(context => + context.LogEvent.TraceId == null ? null : new ScalarValue(context.LogEvent.TraceId.Value)), + BuiltInProperty.SpanId => Splice(context => + context.LogEvent.SpanId == null ? null : new ScalarValue(context.LogEvent.SpanId.Value)), BuiltInProperty.Timestamp => Splice(context => new ScalarValue(context.LogEvent.Timestamp)), BuiltInProperty.MessageTemplate => Splice(context => new ScalarValue(context.LogEvent.MessageTemplate.Text)), BuiltInProperty.Properties => Splice(context => diff --git a/src/Serilog.Expressions/Expressions/Runtime/Coerce.cs b/src/Serilog.Expressions/Expressions/Runtime/Coerce.cs index 27d67f8..b6a3af7 100644 --- a/src/Serilog.Expressions/Expressions/Runtime/Coerce.cs +++ b/src/Serilog.Expressions/Expressions/Runtime/Coerce.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Serilog.Events; @@ -77,6 +78,18 @@ public static bool String(LogEventPropertyValue? value, [MaybeNullWhen(false)] o str = sv.Value.ToString()!; return true; } + + if (sv.Value is ActivityTraceId traceId) + { + str = traceId.ToHexString(); + return true; + } + + if (sv.Value is ActivitySpanId spanId) + { + str = spanId.ToHexString(); + return true; + } } str = default; diff --git a/src/Serilog.Expressions/Serilog.Expressions.csproj b/src/Serilog.Expressions/Serilog.Expressions.csproj index 59ad15d..e153087 100644 --- a/src/Serilog.Expressions/Serilog.Expressions.csproj +++ b/src/Serilog.Expressions/Serilog.Expressions.csproj @@ -14,15 +14,17 @@ Apache-2.0 https://github.com/serilog/serilog-expressions git + README.md - + + diff --git a/test/Serilog.Expressions.Tests/Cases/expression-evaluation-cases.asv b/test/Serilog.Expressions.Tests/Cases/expression-evaluation-cases.asv index ec85ec1..7c0a43b 100644 --- a/test/Serilog.Expressions.Tests/Cases/expression-evaluation-cases.asv +++ b/test/Serilog.Expressions.Tests/Cases/expression-evaluation-cases.asv @@ -304,3 +304,12 @@ undefined() = undefined() ci ⇶ undefined() 'test' like '%' ⇶ true 'test' like '' ⇶ false '' like '' ⇶ true + +// Built-ins + +@m ⇶ 'Hello, World!' +@mt ⇶ 'Hello, {Name}!' +tostring(@x) like 'System.DivideByZeroException%' ⇶ true +@l ⇶ 'Warning' +@sp ⇶ 'bb1111820570b80e' +@tr ⇶ '1befc31e94b01d1a473f63a7905f6c9b' diff --git a/test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs b/test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs index 896efd3..6a95839 100644 --- a/test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs +++ b/test/Serilog.Expressions.Tests/ExpressionEvaluationTests.cs @@ -1,7 +1,9 @@ +using System.Diagnostics; using System.Globalization; using Serilog.Events; using Serilog.Expressions.Runtime; using Serilog.Expressions.Tests.Support; +using Serilog.Parsing; using Xunit; namespace Serilog.Expressions.Tests; @@ -15,14 +17,22 @@ public class ExpressionEvaluationTests [MemberData(nameof(ExpressionEvaluationCases))] public void ExpressionsAreCorrectlyEvaluated(string expr, string result) { - var evt = Some.InformationEvent(); - - evt.AddPropertyIfAbsent( - new("User", new StructureValue(new[] + var evt = new LogEvent( + new DateTimeOffset(2025, 5, 15, 13, 12, 11, 789, TimeSpan.FromHours(10)), + LogEventLevel.Warning, + new DivideByZeroException(), + new MessageTemplateParser().Parse("Hello, {Name}!"), + new [] { - new LogEventProperty("Id", new ScalarValue(42)), - new LogEventProperty("Name", new ScalarValue("nblumhardt")), - }))); + new LogEventProperty("Name", new ScalarValue("World")), + new LogEventProperty("User", new StructureValue(new[] + { + new LogEventProperty("Id", new ScalarValue(42)), + new LogEventProperty("Name", new ScalarValue("nblumhardt")), + })) + }, + ActivityTraceId.CreateFromString("1befc31e94b01d1a473f63a7905f6c9b"), + ActivitySpanId.CreateFromString("bb1111820570b80e")); var frFr = CultureInfo.GetCultureInfoByIetfLanguageTag("fr-FR"); var testHelpers = new TestHelperNameResolver();