Telemetry SourceGenerator
Getting Started
Section titled “Getting Started”This guide gets you up and running with the Purview Telemetry Source Generator in minutes. You will add the package, define a telemetry interface, register it with dependency injection, and start emitting Activities, structured logs, and Metrics.
Installation
Section titled “Installation”Add the analyzer package to your project:
dotnet add package Purview.Telemetry.SourceGeneratorOr reference it in your .csproj or Directory.Build.props:
<PackageReference Include="Purview.Telemetry.SourceGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>analyzers</IncludeAssets></PackageReference>You may also need runtime dependencies depending on which telemetry types you use:
System.Diagnostics.DiagnosticSourcefor ActivitiesMicrosoft.Extensions.Logging.AbstractionsforILoggerSystem.Diagnostics.Metricsfor metrics (built into .NET 8+)
See Installation for the full dependency matrix.
Define a telemetry interface
Section titled “Define a telemetry interface”Create a public interface and decorate it with class-level attributes. The generator creates the implementation and a DI registration extension.
Single-target examples
Section titled “Single-target examples”using Purview.Telemetry;
[Logger]public interface IOrderServiceLogs{ [Info] void OrderPlaced(int orderId, string customerName);
[Warning] void OrderNotFound(int orderId);}[ActivitySource]public interface IOrderServiceTracing{ [Activity] Activity? PlacingOrder(int orderId);
[Event] void OrderValidated(Activity? activity, int orderId);}[Meter]public interface IOrderServiceMetrics{ [Counter] void OrderPlaced(int itemsInOrder);
[Histogram] void OrderProcessingTime(long milliseconds);}Multi-target example
Section titled “Multi-target example”One interface can generate Activities, Logging, and Metrics from the same methods:
[ActivitySource][Logger][Meter]public interface IOrderServiceTelemetry{ [Activity] [Info] [AutoCounter] Activity? PlacingOrder(int orderId, [Baggage] string region);
[Event] [Trace] void OrderProcessed(Activity? activity, long durationMs);
[Warning] void OrderFailed(int orderId, Exception exception);}Register with DI
Section titled “Register with DI”The generator creates an extension method named Add{InterfaceNameWithoutI}():
services.AddOrderServiceTelemetry();Inject the interface into your service:
public class OrderService(IOrderServiceTelemetry telemetry){ public void PlaceOrder(int orderId) { using var activity = telemetry.PlacingOrder(orderId, "EMEA"); // ... telemetry.OrderProcessed(activity, stopwatch.ElapsedMilliseconds); }}A single method call can emit an Activity, a log entry, and a metric simultaneously. See Generation for how registration helpers are produced and how to control them.
Register names with OpenTelemetry
Section titled “Register names with OpenTelemetry”The generator records the generated meter and activity source names in every assembly’s metadata. In the project that registers them, opt into the TelemetryNames class, which aggregates its own names with those of every assembly it references:
// Program.cs or Properties/AssemblyInfo.cs[assembly: TelemetryGeneration(GenerateTelemetryNamesClass = true)]builder.AddServiceDefaults(TelemetryNames.MeterNames, TelemetryNames.ActivitySourceNames);See Generation for the full behaviour across multi-project solutions.
Common patterns
Section titled “Common patterns”Pattern 1: Scoped logging
Section titled “Pattern 1: Scoped logging”Return IDisposable? from a log method to create scoped log entries:
[Logger]interface IOrderTelemetry{ [Info] IDisposable? ProcessingOrder(Guid orderId); // Logs at start and end of scope
[Error] void OrderFailed(Exception ex, Guid orderId);}
public async Task ProcessOrderAsync(Guid orderId){ using (telemetry.ProcessingOrder(orderId)) { // Processing logic here }}Pattern 2: Activity with multiple events
Section titled “Pattern 2: Activity with multiple events”Track multiple stages within a single activity:
[ActivitySource("ShippingService")]interface IShippingTelemetry{ [Activity] Activity? ShippingPackage([Baggage]string trackingNumber);
[Event] void PackageLabeled(Activity? activity);
[Event] void PackageWeighed(Activity? activity, [Tag]decimal weight);
[Event] void PackageShipped(Activity? activity, [Tag]string carrier);}Pattern 3: Auto-incrementing counters
Section titled “Pattern 3: Auto-incrementing counters”Use [AutoCounter] for simple counting without a measurement parameter — every call increments by 1:
[Meter("ApiService")]interface IApiMetrics{ [AutoCounter] void RequestReceived([Tag]string endpoint, [Tag]string method);
[AutoCounter] void RequestFailed([Tag]string endpoint, [Tag]int statusCode);}Viewing generated code
Section titled “Viewing generated code”To inspect the generated source, add this to your .csproj:
<PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles></PropertyGroup>Generated files appear under obj/Debug|Release/<tfm>/generated/Purview.Telemetry.SourceGenerator/Purview.Telemetry.SourceGenerator.TelemetrySourceGenerator/.
Tips and best practices
Section titled “Tips and best practices”- Return
Activity?from Activity-starting methods, notActivityorvoid, so callers can dispose and reuse the activity. - Pass activities explicitly — pass the
Activity?from the starting method to event/context methods rather than relying onActivity.Current. - One namespace — use the single
using Purview.Telemetry;import. - OpenTelemetry naming — v5 defaults to OpenTelemetry conventions (snake_case tags, hierarchical metrics). See Naming conventions.
- DI registration — use the generated
Add{InterfaceName}()extension methods. - Testing — telemetry interfaces are easy to mock in unit tests. See Testing.
Next steps
Section titled “Next steps”- Activities — deep dive into distributed tracing with Activities, Events, and Context
- Logging — structured logging and the v1/v2 generation modes
- Metrics — counters, histograms, and observable instruments
- Multi-Targeting — combine multiple telemetry types in one interface
- Generation Options — control code generation, DI, and naming
- Generated Output — see what code is actually generated
- Migration — convert existing
ILogger/ActivitySource/metrics code using the IDE refactorings