-
Notifications
You must be signed in to change notification settings - Fork 41
Trace and span enrichment
Serilog 4.x exposes LogEvent.TraceId and LogEvent.SpanId, populated from the ambient System.Diagnostics.Activity. The sink can write each of them into the JSON log body or as Loki Structured metadata - or leave it out entirely.
traceIdMode and spanIdMode each take a LokiFieldDestination:
| Value | Effect |
|---|---|
None (default) |
The value is not written. |
Body |
Written as a top-level TraceId / SpanId field in the JSON log body. |
StructuredMetadata |
Attached as per-line Structured metadata - recommended for trace IDs (filterable without a parser, no cardinality cost). Requires Loki 3.0+. |
.WriteTo.GrafanaLoki(
"http://localhost:3100",
traceIdMode: LokiFieldDestination.StructuredMetadata,
spanIdMode: LokiFieldDestination.StructuredMetadata)From appsettings.json the mode binds from its name:
{
"Name": "GrafanaLoki",
"Args": {
"uri": "http://localhost:3100",
"traceIdMode": "StructuredMetadata",
"spanIdMode": "StructuredMetadata"
}
}Both default to None.
The sink does not start activities; it reads the trace context already on the LogEvent. That context is populated for you by Serilog.AspNetCore (UseSerilog) and Serilog.Extensions.Logging, which copy the current Activity.TraceId / SpanId onto each event.
Outside those integrations, an Activity must be active - started by ASP.NET Core, HttpClient, or your own ActivitySource - for the fields to be written. If there is no trace context on the event, the fields are simply omitted.
The values are lowercase hex strings. In Body mode they are fields on the JSON line:
{
"Message": "...",
"MessageTemplate": "...",
"TraceId": "0af7651916cd43dd8448eb211c80319c",
"SpanId": "b7ad6b7169203331"
}In Body mode you surface them at query time with | json (see Using LokiJsonTextFormatter and Grafana Loki json parser). In StructuredMetadata mode they are filterable directly ({…} | TraceId="…") and appear as fields in Grafana Explore - see Structured metadata. Either way they can be wired to a tracing backend such as Tempo using Grafana derived fields.