Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions context/skills/tracing/description.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ Consult the documentation for API details and platform-specific patterns.
## Choose the capture path

- **Node.js with `posthog-node` >= 5.52.0**: `posthog-node` creates and exports spans itself, with no OpenTelemetry dependency. Set the `traces` option on the existing client and wrap operations in `withSpan` (or `startSpan` for work that can't wrap a callback).
- **OpenTelemetry already in the project**: point its OTLP trace exporter at `/i/v1/traces` on the PostHog host, with the project token as an `Authorization: Bearer` header. Don't add `posthog-node` spans alongside it.
- **Python with `posthog` >= 7.58.0**: the `posthog` package creates and exports spans itself, with no OpenTelemetry dependency. Set the `traces` option on the existing synchronous `Posthog` client (or `posthog.traces` for the module-level API) and wrap operations in `with posthog.start_span(...)`. `AsyncPosthog` has no span API, so use OpenTelemetry there.
- **OpenTelemetry already in the project**: point its OTLP trace exporter at `/i/v1/traces` on the PostHog host, with the project token as an `Authorization: Bearer` header. Don't add `posthog-node` or `posthog` spans alongside it.
- **Everything else**: use the OpenTelemetry SDK for the language, as the platform reference describes. It is also the only route to auto-instrumentation of HTTP servers, frameworks, and database drivers.

## Where to instrument
Expand All @@ -27,11 +28,11 @@ If the user asks for specific spans, instrument those instead. A few spans at ch
- **Environment variables**: Always use environment variables for the PostHog project token, host, and OTLP endpoint. Never hardcode them.
- **Region**: Take the host from the project's existing PostHog configuration. If there is none, ask whether the project is on US Cloud (`https://us.i.posthog.com`) or EU Cloud (`https://eu.i.posthog.com`). Do not assume US Cloud.
- **Minimal changes**: Add spans alongside existing code. Don't replace existing tracing, and if the project already exports to another tracing backend, ask before adding PostHog as a second destination.
- **Service name**: Set a service name at setup (`traces.serviceName` in `posthog-node`, `service.name` in OpenTelemetry) so spans are attributable in the Tracing UI.
- **Service name**: Set a service name at setup (`traces.serviceName` in `posthog-node`, `traces["service_name"]` in Python `posthog`, `service.name` in OpenTelemetry) so spans are attributable in the Tracing UI.
- **Span names**: Low-cardinality operation names, like `GET /users/:id` rather than `GET /users/123`. Variable values belong in attributes.
- **Attributes**: Never put secrets, tokens, or passwords in attributes. In `posthog-node`, `beforeSpanSend` can scrub or drop spans before export.
- **Attributes**: Never put secrets, tokens, or passwords in attributes. In `posthog-node`, `beforeSpanSend` can scrub or drop spans before export; in Python `posthog`, `before_span_send`.
- **Context propagation**: Pass the W3C `traceparent` header on outbound requests between services, so their spans join one trace instead of starting new ones.
- **People and sessions**: A span joins a person or a Session Replay recording through `posthogDistinctId` and `sessionId` attributes. `posthog-node` sets them for spans created inside a PostHog request context (`withContext`, or the Express middleware). With OpenTelemetry, set them yourself from the `X-POSTHOG-DISTINCT-ID` and `X-POSTHOG-SESSION-ID` headers the browser SDK sends when `tracing_headers` is configured.
- **People and sessions**: A span joins a person or a Session Replay recording through `posthogDistinctId` and `sessionId` attributes. `posthog-node` sets them for spans created inside a PostHog request context (`withContext`, or the Express middleware), and Python `posthog` does the same inside `new_context()` with `identify_context()` / `set_context_session()`, or the Django contexts middleware. With OpenTelemetry, set them yourself from the `X-POSTHOG-DISTINCT-ID` and `X-POSTHOG-SESSION-ID` headers the browser SDK sends when `tracing_headers` is configured.
- **Flushing**: Spans export on an interval. In short-lived processes and serverless handlers, call `flush()` (or the OpenTelemetry provider's `forceFlush()`) before returning, and `shutdown()` only when the process is exiting.

## Framework guidelines
Expand Down
Loading