.NET / C# Instrumentation
Attach the OpenTelemetry auto-instrumentation agent to the .NET runtime — HTTP requests, HttpClient, Entity Framework, gRPC, exceptions, and latency captured with zero code changes.
Zero-code setup (recommended)
Install the auto-instrumentation agent once per machine or container:
Windows (PowerShell)
Invoke-WebRequest -Uri https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/OpenTelemetry.DotNet.Auto.psm1 -OutFile OpenTelemetry.DotNet.Auto.psm1
Import-Module ./OpenTelemetry.DotNet.Auto.psm1
Install-OpenTelemetryCore
Register-OpenTelemetryForCurrentSession -OTelServiceName "my-dotnet-service"Linux / macOS
curl -sSfL https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh -O
sh otel-dotnet-auto-install.sh
. $HOME/.otel-dotnet-auto/instrument.shPoint it at Lightarch and run your app:
powershell
$env:OTEL_SERVICE_NAME = "my-dotnet-service"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://la-ingest-gateway.lightarch.workers.dev"
$env:OTEL_EXPORTER_OTLP_HEADERS = "x-la-dsn=la_live_YOUR_TOKEN_HERE"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
dotnet runThat's the whole setup. Unhandled exceptions appear in the Errors page with full stack traces, requests show up as traces with latency, and outbound calls are correlated — no
Program.cs changes.Screenshot needed
Traces page showing .NET service spans with service='my-dotnet-service', ASP.NET Core route spans like 'GET /api/orders', durations in ms.
Verify it's working
bash
la query "SELECT service, severity, body, duration_ms FROM recent_spans WHERE service = 'my-dotnet-service' ORDER BY timestamp DESC LIMIT 10"
la logs tail --service my-dotnet-serviceCode-based setup (more control)
If you prefer configuring in code, add three packages and one block to Program.cs:
bash
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocolProgram.cs
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService("my-dotnet-service"))
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter(o => {
o.Endpoint = new Uri("https://la-ingest-gateway.lightarch.workers.dev/v1/traces");
// Required: the .NET exporter defaults to gRPC, which Lightarch doesn't accept
o.Protocol = OtlpExportProtocol.HttpProtobuf;
o.Headers = "x-la-dsn=la_live_YOUR_TOKEN_HERE";
}));o.Protocol = OtlpExportProtocol.HttpProtobuf is required — the .NET OTLP exporter defaults to gRPC and will silently fail without it.Optional: Entity Framework Core
bash
dotnet add package OpenTelemetry.Instrumentation.EntityFrameworkCorecsharp
.WithTracing(t => t
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddEntityFrameworkCoreInstrumentation()
.AddOtlpExporter(/* same as above */));Custom spans
csharp
using var tracer = TracerProvider.Default.GetTracer("my-dotnet-service");
using var span = tracer.StartActiveSpan("payment.process");
span.SetAttribute("order.id", orderId);
try
{
var result = await ChargeCard(orderId);
span.SetAttribute("payment.status", result.Status);
return result;
}
catch (Exception ex)
{
span.RecordException(ex);
span.SetStatus(Status.Error.WithDescription(ex.Message));
throw;
}