In this lesson, you will learn how to instrument your asynchronous workflows to visualize request flow and identify performance bottlenecks using ActivitySource.
As systems scale and move toward asynchronous, distributed architectures, simple logging often fails to capture the "full story" of a request. When a single user request spans multiple threads or microservices, you need a way to correlate those operations. This is where the System.Diagnostics.Activity API and its source, ActivitySource, come into play.
The Power of Distributed Tracing
Think of an Activity as a "span" of work. It captures a specific unit of execution, recording its start time, end time, and metadata (tags). When you nest these activities, you create a parent-child relationship that forms a trace.
Unlike standard logging, which provides discrete snapshots, ActivitySource allows tools (like Jaeger, Zipkin, or Application Insights) to stitch these spans together into a timeline. This is crucial for pinpointing exactly which part of an asynchronous call chain is causing latency.
Implementing an Activity
To track a block of code, you define an ActivitySource once and use it to start an activity:
// Define at the class level
private static readonly ActivitySource MySource = new("MyCompany.MyService");
public async Task ProcessOrderAsync(Guid orderId)
{
using (Activity? activity = MySource.StartActivity("ProcessOrder"))
{
activity?.SetTag("order.id", orderId);
// Simulate async work
await _paymentService.ChargeAsync(orderId);
// Activity ends automatically when disposed
}
}
When you wrap your await calls within these activities, the Activity object keeps track of the context. Even if the code execution jumps between threads, the trace remains intact. By tagging your activities with relevant identifiers like orderId or userId, you turn abstract performance data into actionable business diagnostics. This is essential for visualizing how your asynchronous state machines behave under load, helping you bridge the gap between "something is slow" and "this specific dependency is causing a 200ms delay."
Key Takeaway: ActivitySource transforms opaque asynchronous code into a transparent timeline, enabling you to correlate performance costs across thread boundaries and distributed service calls.