Quick Start
Quick Start Guide
Section titled “Quick Start Guide”Get started with Purview Telemetry Source Generator in 5 minutes! This guide walks you through creating your first telemetry-enabled application.
Prerequisites
Section titled “Prerequisites”- .NET 8.0 or higher (or .NET Framework 4.8+)
- Your favourite IDE (Visual Studio, Visual Studio Code, or Rider)
Step 1: Install the Package
Section titled “Step 1: Install the Package”Add the NuGet package to your project:
Option A: .NET CLI
Section titled “Option A: .NET CLI”dotnet add package Purview.Telemetry.SourceGenerator --version 5.0.0-prerelease.1Option B: Package Manager Console
Section titled “Option B: Package Manager Console”Install-Package Purview.Telemetry.SourceGenerator -Version 5.0.0-prerelease.1Option C: Edit .csproj directly
Section titled “Option C: Edit .csproj directly”<ItemGroup> <PackageReference Include="Purview.Telemetry.SourceGenerator" Version="5.0.0-prerelease.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>analyzers</IncludeAssets> </PackageReference></ItemGroup>Step 2: Create Your First Telemetry Interface
Section titled “Step 2: Create Your First Telemetry Interface”Create a new file IOrderServiceTelemetry.cs:
using System.Diagnostics;using Purview.Telemetry;
[ActivitySource("QuickStart.OrderService")] // For distributed tracing[Logger] // For structured logging[Meter("QuickStart.OrderService")] // For metricspublic interface IOrderServiceTelemetry{ // Multi-target method: Creates Activity + Logs Info + Increments Counter [Activity] [Info] [AutoCounter] Activity? ProcessingOrder([Baggage] int orderId, [Tag] string customerName);
// Event + Log [Event] [Debug] void OrderValidated(Activity? activity, [Tag] decimal totalAmount);
// Event + Log [Event(ActivityStatusCode.Ok)] [Info] void OrderCompleted(Activity? activity, [Tag] TimeSpan processingTime);
// Error logging [Error] [AutoCounter] void OrderFailed(Exception ex, int orderId);}What just happened?
[ActivitySource],[Logger],[Meter]- Tells the generator to create implementations for all three telemetry types[Activity],[Info],[AutoCounter]- Multi-target attributes that generate code for all three types from a single method[Baggage]- Data propagates across service boundaries[Tag]- Local activity data (doesn’t propagate)
Step 3: Register with Dependency Injection
Section titled “Step 3: Register with Dependency Injection”In your Program.cs or Startup.cs:
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register the telemetry interface// The generator creates this extension method automatically!builder.Services.AddOrderServiceTelemetry();
var app = builder.Build();Step 4: Use It in Your Service
Section titled “Step 4: Use It in Your Service”Create OrderService.cs:
public class OrderService{ private readonly IOrderServiceTelemetry _telemetry; private readonly IOrderRepository _repository;
public OrderService(IOrderServiceTelemetry telemetry, IOrderRepository repository) { _telemetry = telemetry; _repository = repository; }
public async Task<Order?> ProcessOrderAsync(int orderId, string customerName) { // Single call creates Activity + Logs + Increments counter! using var activity = _telemetry.ProcessingOrder(orderId, customerName);
try { // Validate order var order = await _repository.GetOrderAsync(orderId); if (order == null) { _telemetry.OrderFailed(new Exception("Order not found"), orderId); return null; }
// Add event to activity + log debug message _telemetry.OrderValidated(activity, order.TotalAmount);
// Process payment, shipping, etc... await Task.Delay(100); // Simulated work
var stopwatch = Stopwatch.StartNew(); // ... more processing ... stopwatch.Stop();
// Add event + log completion _telemetry.OrderCompleted(activity, stopwatch.Elapsed);
return order; } catch (Exception ex) { // Log error + increment error counter _telemetry.OrderFailed(ex, orderId); throw; } }}Step 5: Configure OpenTelemetry (Optional but Recommended)
Section titled “Step 5: Configure OpenTelemetry (Optional but Recommended)”To view your telemetry, add OpenTelemetry exporters:
dotnet add package OpenTelemetry.Exporter.Consoledotnet add package OpenTelemetry.Extensions.HostingConfigure in Program.cs:
using OpenTelemetry.Logs;using OpenTelemetry.Metrics;using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
// Add OpenTelemetrybuilder.Services.AddOpenTelemetry() .WithTracing(tracing => tracing .AddSource("QuickStart.OrderService") // Match your ActivitySource name .AddConsoleExporter()) .WithMetrics(metrics => metrics .AddMeter("QuickStart.OrderService") // Match your Meter name - this defaults to the assembly name if not specified .AddConsoleExporter()) .WithLogging(logging => logging .AddConsoleExporter());
builder.Services.AddOrderServiceTelemetry();
var app = builder.Build();Step 6: Run and See It Work
Section titled “Step 6: Run and See It Work”Run your application and call the ProcessOrderAsync method. You’ll see:
Console Output (Activity Trace):
Activity.TraceId: 80000000-0000-0000-0000-000000000001Activity.SpanId: 8000000000000001Activity.DisplayName: ProcessingOrderActivity.Kind: InternalActivity.StartTime: 2026-02-14T10:30:00.0000000ZActivity.Duration: 00:00:00.1234567Activity.Tags: order_id: 42 customer_name: John Doe (Baggage)Activity.Events: OrderValidated [10:30:00.050] total_amount: 99.99 OrderCompleted [10:30:00.123] processing_time: 00:00:00.123Console Output (Logging):
info: IOrderServiceTelemetry[0] ProcessingOrder: OrderId = 42, CustomerName = John Doe
dbug: IOrderServiceTelemetry[0] OrderValidated: TotalAmount = 99.99
info: IOrderServiceTelemetry[0] OrderCompleted: ProcessingTime = 00:00:00.123Console Output (Metrics):
Meter: QuickStart.OrderService Instrument: order_service.processing_order (Counter) Value: 1What’s Next?
Section titled “What’s Next?”Learn More About Each Feature
Section titled “Learn More About Each Feature”- Activities - Deep dive into distributed tracing
- Logging - Structured logging with Generation v2
- Metrics - Counters, histograms, and observables
- Multi-Targeting - Combine telemetry types
Common Next Steps
Section titled “Common Next Steps”1. Add More Telemetry
Section titled “1. Add More Telemetry”[ActivitySource("QuickStart.PaymentService")][Logger][Meter("QuickStart.PaymentService")]public interface IPaymentServiceTelemetry{ [Activity(ActivityKind.Client)] [Info] [AutoCounter] Activity? ProcessingPayment([Baggage] Guid paymentId, [Tag] decimal amount);
[Event] [Debug] void PaymentValidated(Activity? activity);
[Event(ActivityStatusCode.Error)] [Error] void PaymentDeclined(Activity? activity, string reason);
[Histogram] void PaymentDuration([InstrumentMeasurement] int milliseconds, [Tag] bool success);}2. Use Scoped Logging
Section titled “2. Use Scoped Logging”[Logger]public interface IDataServiceTelemetry{ // Returns IDisposable for automatic start/end logging [Info] IDisposable? FetchingDataFromDatabase(int recordId);
[Debug] void RecordFetched(string recordType);}
// Usagepublic async Task<Data> GetDataAsync(int id){ using (_telemetry.FetchingDataFromDatabase(id)) // Logs at start and end { var data = await _repository.GetAsync(id); _telemetry.RecordFetched(data.Type); return data; }}3. Add Metrics Only
Section titled “3. Add Metrics Only”[Meter("QuickStart.CacheService")]public interface ICacheMetrics{ [AutoCounter] void CacheHit([Tag] string cacheKey);
[AutoCounter] void CacheMiss([Tag] string cacheKey);
[Histogram] void CacheLookupDuration([InstrumentMeasurement] int milliseconds);}4. Export to Real Observability Platform
Section titled “4. Export to Real Observability Platform”Replace console exporters with:
Jaeger (Traces):
dotnet add package OpenTelemetry.Exporter.Jaeger.WithTracing(tracing => tracing .AddSource("QuickStart.*") .AddJaegerExporter())Prometheus (Metrics):
dotnet add package OpenTelemetry.Exporter.Prometheus.AspNetCore.WithMetrics(metrics => metrics .AddMeter("QuickStart.*") .AddPrometheusExporter())
app.MapPrometheusScrapingEndpoint();Azure Monitor (All):
dotnet add package Azure.Monitor.OpenTelemetry.Exporter.UseAzureMonitor()Inspecting Generated Code
Section titled “Inspecting Generated Code”Want to see what code the generator creates?
Add to your .csproj:
<PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles></PropertyGroup>Generated files appear in:
obj/Debug/net8.0/generated/Purview.Telemetry.SourceGenerator/You’ll find:
{Namespace}.OrderServiceTelemetryCore.Activity.g.cs- Activity implementation{Namespace}.OrderServiceTelemetryCore.Logging.g.cs- Logging implementation{Namespace}.OrderServiceTelemetryCore.Metric.g.cs- Metrics implementation{Namespace}.OrderServiceTelemetryCoreDIExtension.DependencyInjection.g.cs- DI registration
Complete Working Example
Section titled “Complete Working Example”Here’s a complete minimal application you can copy and run:
Program.cs:
using System.Diagnostics;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using OpenTelemetry.Logs;using OpenTelemetry.Metrics;using OpenTelemetry.Trace;using Purview.Telemetry;
var builder = Host.CreateApplicationBuilder(args);
// Configure OpenTelemetrybuilder.Services.AddOpenTelemetry() .WithTracing(t => t.AddSource("QuickStart").AddConsoleExporter()) .WithMetrics(m => m.AddMeter("QuickStart").AddConsoleExporter()) .WithLogging(l => l.AddConsoleExporter());
// Register telemetrybuilder.Services.AddOrderServiceTelemetry();
// Register application servicebuilder.Services.AddSingleton<OrderService>();
var app = builder.Build();
// Run a testvar service = app.Services.GetRequiredService<OrderService>();await service.ProcessOrderAsync(42, "John Doe");
Console.WriteLine("\nDone! Check the output above for telemetry.");
// Telemetry interface[ActivitySource("QuickStart")][Logger][Meter("QuickStart")]public interface IOrderServiceTelemetry{ [Activity] [Info] [AutoCounter] Activity? ProcessingOrder([Baggage] int orderId, [Tag] string customerName);
[Event(ActivityStatusCode.Ok)] [Info] void OrderCompleted(Activity? activity, [Tag] TimeSpan duration);}
// Application servicepublic class OrderService{ private readonly IOrderServiceTelemetry _telemetry;
public OrderService(IOrderServiceTelemetry telemetry) { _telemetry = telemetry; }
public async Task ProcessOrderAsync(int orderId, string customerName) { var sw = Stopwatch.StartNew();
using var activity = _telemetry.ProcessingOrder(orderId, customerName);
// Simulate work await Task.Delay(100);
_telemetry.OrderCompleted(activity, sw.Elapsed); }}Run it:
dotnet runTroubleshooting
Section titled “Troubleshooting”“Type or namespace ‘ActivitySourceAttribute’ could not be found”
Section titled ““Type or namespace ‘ActivitySourceAttribute’ could not be found””Solution: Add the using statement:
using Purview.Telemetry;“No extension method ‘Add{InterfaceName}’”
Section titled ““No extension method ‘Add{InterfaceName}’””Solution: Rebuild the project to trigger source generation:
dotnet build“No telemetry appears in console”
Section titled ““No telemetry appears in console””Solution: Ensure OpenTelemetry is configured with the correct source/meter names that match your interface attributes.
“Build warnings about unbounded enumeration”
Section titled ““Build warnings about unbounded enumeration””Solution: Add [ExpandEnumerable] attribute with maximumValueCount:
[Info]void LogItems([ExpandEnumerable(maximumValueCount: 100)] string[] items);Next Steps
Section titled “Next Steps”- Getting Started Guide - Comprehensive walkthrough with more examples
- Sample Application - Full .NET Aspire sample with all features
- Breaking Changes - Migrating from v3 to v4
- Migration Guides - Migrate from manual ILogger or ActivitySource
- Activities, Logging, Metrics - Complete per-telemetry-type attribute reference
Need Help?
Section titled “Need Help?”- Check the FAQ for common questions
- Review Diagnostics for analyzer warnings and errors
- See Generated Output for code examples
- Explore the Sample Application for real-world usage