Subchapter 93.3
references/dotnet.mdMarkdown6 KBView on GitHub
AI agents: this is one page from PostHog’s docs. Full index of Markdown docs for LLMs: https://posthog.com/llms.txt (opens in a new tab)
Canonical URL: https://posthog.com/docs/distributed-tracing/installation/dotnet (opens in a new tab)
Cloud region: This page uses US Cloud hosts. For an EU Cloud project, use
https://eu.i.posthog.cominstead ofhttps://us.i.posthog.com(ingestion host), and usehttps://eu.posthog.cominstead ofhttps://app.posthog.com(app host for links).
1
Required
For the complete SDK reference, see the OpenTelemetry .NET docs (opens in a new tab).
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Extensions.HostingOpenTelemetry.Extensions.Hosting wires OpenTelemetry into the host builder. For a plain console app using Sdk.CreateTracerProviderBuilder(), you can leave it out.
2
Required
You’ll need your PostHog project token to authenticate trace requests. This is the same token you use for capturing events with the PostHog SDK.
Important: Use your project token which starts with
phc_. Do not use a personal API key (which starts withphx_).
You can find your project token in Project settings (opens in a new tab).
3
Required
Set up OpenTelemetry to export spans to PostHog over OTLP HTTP. The AddSource name must match the ActivitySource you create in the next step.
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry
4
Required
.NET uses the built-in ActivitySource API for tracing. The source name must match the AddSource call above.
using System.Diagnostics;
static readonly ActivitySource MyActivitySource = new("MyCompany.MyApp");
public void ProcessOrder(string
5
Recommended
For ASP.NET Core on .NET 8 or later, use the PostHog request-context integration (opens in a new tab). Add PostHog to your existing host builder and put the middleware before your routes:
builder.AddPostHog();
var app = builder.Build();
app.UsePostHogRequestContext();Configure for your backend hostname in the browser SDK. The middleware adds missing and tags to the active request . The host-owned listener adds those tags to child activities when they start. Keep your existing OpenTelemetry provider, exporter, and sampling configuration.
6
Recommended
Once everything is configured, confirm spans are reaching PostHog:
Checkpoint
What you can do with your traces
| Action | Description |
|---|---|
| Why you need distributed tracing (opens in a new tab) | What a trace shows you that nothing else does |
| Explore traces | Read a trace as a waterfall to see where time goes |
| Filter spans | Narrow down by service, status, duration, and attributes |
| Propagate context | Pass trace context across services so spans join the same trace |
Alternatively, configure the exporter with environment variables and call AddOtlpExporter() with no arguments:
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://us.i.posthog.com/i/v1/traces"
OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer <ph_project_token>"
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
OTEL_SERVICE_NAME="my-service"Note: With
HttpProtobuf, theEndpointis used as-is, so include the full/i/v1/tracespath. Don’t use the baseOTEL_EXPORTER_OTLP_ENDPOINTvariable, which appends its own/v1/traces.
StartActivity returns null when nothing is listening to the source, so use the null-conditional activity?. operator.
tracing_headerssessionIdposthogDistinctIdActivityExisting sessionId and posthogDistinctId tags take precedence. Set authenticated application identity with posthogDistinctId. Missing IDs stay absent. Tracing headers are untrusted analytics context. Use authenticated application identity for access decisions.
Activities that already started keep their tags after the request ends. New activities in detached work do not receive the ended request’s IDs. Background jobs need their own context transfer. The core PostHog SDK does not provide a native span API or a trace exporter.