New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Collect and propagate current trace and span ids through LogEvent
#1955
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
Thanks @cmeeren @bartelink 😊 |
Spent some more time on this and measured the "empty pipeline" cost of a) the larger First up,
The initial implementation:
So, about 14% slower and a little more alloc. If we're prepared to move
Moving
But, I'm not sure these results capture the real performance impact of making the additional small allocation rather growing the So, switching back to the original layout, but using non-nullable trace and span id fields gets to:
The execution time is within the same error bounds, but only 4.3% more space is allocated, improving on the original implementation's 8.5%. -- Learned a little more about how trace and span ids are allocated on .NET Framework (and early .NET Core), which needs a little pondering. |
Pushed use of
Actually getting quite close to the original, now. I think that while passing |
Think this is now about as ready as it will get :-) |
Righto, forging ahead! Here's an incomplete list of remaining/downstream work we need to look at before RTMing this:
I suspect there are yet more scenarios out there that will call for either suppressing or explicitly specifying trace or span ids, but those will come out in the wash :) |
@nblumhardt What version will this be released in? I'd like to point people to this new feature from https://github.com/RehanSaeed/Serilog.Enrichers.Span. |
Hi @RehanSaeed! Thanks for dropping by 👍 The package version that includes this is currently 3.1; I think before we can RTM it we need to add support in prerelease versions of the sinks people want to collect span information in, and get some feedback. I'll push the first round of PRs (linked from the comment just above) and update the sinks I maintain (think that might just be the Seq sink right now), I'll also chime in on the other thread (in Serilog.AspNetCore) and ask what sinks people over there are using. Once we've got a little bit of validation out in the field I don't think there will be much holding this up. |
Great work with this! I'm on below version and can't se the Span and Trace id properties in Seq. I've configured Will these properties be propagated to the Thanks!
|
Hi @joacar! Those package versions do record trace and span ids in Seq for me when writing directly through a Serilog but the UI is a little different from what Seq shows for regular properties, and you need at least Seq 2023.3 (IIRC - I'm using 2023.4). You will need to take a dependency on Seq.Extensions.Logging version Seq exposes an OTLP gRPC endpoint - docs on how to find it are: https://docs.datalust.co/docs/ingestion-with-opentelemetry#grpc-endpoint (the http/protobuf endpoint described one paragraph earlier is available without any additional configuration on all platforms; gRPC requires To quickly check whether trace and span ids are being picked up at all, you can use Still very early days for pulling all of these libraries together so you may find some rough edges; would be great to hear how you go, and if you hit issues please feel free to raise tickets here (or ping Seq support for Seq config help :-)). |
Thanks for quick reply @nblumhardt ! I created a new project targeting .NET 8 {
"Logging": {
"LogLevel": {
"Default": "Warning",
"SpanTrace": "Information"
},
"Console": {
"IncludeScopes": true
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="3.1.0-dev-02078" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
</ItemGroup>
</Project> using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Logging
.AddConfiguration(builder.Configuration.GetSection("Logging"))
.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId;
});
// builder.Host.UseSerilog((_,configuration) =>
// {
// configuration
// .MinimumLevel.Warning()
// .MinimumLevel.Override("SpanTrace", LogEventLevel.Information)
// .WriteTo.Console(new JsonFormatter()); //outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties}}");
// }, writeToProviders: true);
var app = builder.Build();
app.MapGet("/", (ILoggerFactory factory) =>
{
var logger = factory.CreateLogger("SpanTrace");
logger.LogInformation("Hello, world");
return "Hello World!";
});
app.Run(); The code above prints
and if I add the Serilog piece the output looks like this
As you can see, the scope is dropped from the MEL and no properties are written from Serilog. I couldn't find the package Thanks! |
Pretty sure he means |
Thanks for that! Now it displays the
Will move on to testing Seq as well, but as long as I get the version right I should be up and running. Cheers |
@joacar writing directly from the logger is still the way to go, IMHO, since there are fewer moving parts involved. Seq supports OTLP natively now though, so you can use an OTLP logs exporter from the collector or SDK and get log events to Seq. We're working on adding tracing support currently. |
I'll think about that. Historically I've always used ME.ILogger and from the to time questioned it and just use Serilog directly. What is the biggest win in your opinion using Serilog interface directly? Update: Found this which can likely be implemented in Serilog (if it isn't already - wouldn't surprise me!) Thanks |
Added the new standard columns TraceId and SpanId for OpenTelemetry tracing. Those columns are by default not enabled and must be added to the ColumnOptions.Store property to use them (for backwards compatibility). If the columns are activated, the corresponding OpenTracing log event properties from Serilog will be written to those columns (serilog/serilog#1955).
Added the new standard columns TraceId and SpanId for OpenTelemetry tracing. Those columns are by default not enabled and must be added to the ColumnOptions.Store property to use them (for backwards compatibility). If the columns are activated, the corresponding OpenTracing log event properties from Serilog will be written to those columns (serilog/serilog#1955).
Not sure what i'm doing wrong but I can't find the way to add TraceId et SpanId to the log. Is there a configuration I must set somewhere? |
Fixes #1923
Fixes serilog/serilog-aspnetcore#207
Note that trace and span ids will only be collected when at least one activity listener is present - this will be the case in just about all practical implementation scenarios right now, I think, but is still worth bearing in mind.
The addition of
{TraceId}
and{SpanId}
toMessageTemplateTextFormatter
is technically a breaking change; existing user templates with top level trace and span properties will now pull in the values fromLogEvent
rather than identically-named properties. In most cases these will have the same value/representation, so I don't think it justifies a major version bump, though it'd need a prominent call-out in the release notes.The immediate benefit from merging this PR will be the removal of the
ConditionalWeakTable
workaround in Serilog.Sinks.OpenTelemetry, and should hopefully pave the way for better integration with the OpenTelemetry SDK, if/when that happens.Further down the line, most sinks for APMs/log servers/services will be able to pull in these properties for correlation purposes.
Final note, this adds a dependency on System.Diagnostics.DiagnosticSource on older platforms; this is no different from how we support
ValueTuple
, so I've made peace with this :-)