Follow one request across every service
When a request passes through an API, a queue and two background workers, you need one ID that ties all the logs together. .NET already creates it for you.
A customer reports that their order "just disappeared". The order went through an API, a Service Bus queue, a worker that called a CRM, and another that sent an email. Each one wrote logs. Without something to link them, you're matching timestamps by eye across four services.
What you need is a correlation ID: one identifier that travels with the work and appears in every log entry along the way.
You probably already have one
.NET uses System.Diagnostics.Activity for distributed tracing, following the W3C Trace Context standard. ASP.NET Core starts an activity for each incoming request, and that activity has a trace ID:
var traceId = Activity.Current?.TraceId.ToString();
HttpClient automatically sends it to downstream services in the traceparent header, and an ASP.NET Core service on the other end picks it up and continues the same trace. The Azure SDK clients, including Service Bus, also carry trace context in message properties, so it can survive the trip through a queue.
Make sure it's in your logs
Application Insights and the Azure Monitor OpenTelemetry distro record the trace ID for every request, dependency call and log entry. In Application Insights it's the operation_Id field:
union requests, dependencies, traces, exceptions
| where operation_Id == "4bf92f3577b34da6a3ce929d0e0e4736"
| order by timestamp asc
That one query shows everything that happened for the request, across every service that sent telemetry.
If you write logs somewhere else, such as files or a third-party tool, include the trace ID explicitly. The built-in logging can add it to every entry's scope:
builder.Logging.Configure(options =>
options.ActivityTrackingOptions = ActivityTrackingOptions.TraceId | ActivityTrackingOptions.SpanId);
Give it to the caller
When something goes wrong, return the trace ID in the error response, so a support ticket can include it. ASP.NET Core's problem details responses include a traceId field by default:
builder.Services.AddProblemDetails();
When the trail breaks
- Custom transports. If you hand work across something that doesn't propagate trace context, such as a database table polled by a job, store the trace ID with the work and start a new activity linked to it when you pick it up.
- Fire-and-forget code loses the current activity's context easily. Another reason to avoid it.
- Third-party systems won't carry your trace ID. Log their request or reference IDs next to yours, so you can join the two.
Takeaway
Use the trace ID that .NET and Azure already create and propagate. Make sure it's in every log entry, return it in error responses, and you can follow one request across every service with a single query.