Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions context/marketplace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ plugins:
destination: skills/posthog/metrics
keywords: [posthog, metrics, observability, opentelemetry]

tracing:
name: posthog-tracing
description: Skills for setting up PostHog distributed tracing
destination: skills/posthog/tracing
keywords: [posthog, tracing, observability, opentelemetry]

error-tracking:
name: posthog-error-tracking
description: Skills for setting up PostHog error tracking across frameworks
Expand Down
62 changes: 62 additions & 0 deletions context/skills/tracing/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Tracing skills - docs-only (no example projects)
type: skill
template: description.md
description: PostHog distributed tracing for {display_name}
tags: [tracing]
shared_docs:
- https://posthog.com/docs/distributed-tracing/start-here.md
- https://posthog.com/docs/distributed-tracing/basics.md
variants:
- id: nodejs
display_name: Node.js
tags: [javascript]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/nodejs.md

- id: nextjs
display_name: Next.js
tags: [nextjs, javascript]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/nextjs.md

- id: python
display_name: Python
tags: [python]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/python.md

- id: go
display_name: Go
tags: [go]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/go.md

- id: java
display_name: Java
tags: [java]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/java.md

- id: dotnet
display_name: .NET
tags: [dotnet, csharp]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/dotnet.md

- id: php
display_name: PHP
tags: [php]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/php.md

- id: ruby
display_name: Ruby
tags: [ruby]
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation/ruby.md

- id: other
display_name: Other Languages
tags: []
docs_urls:
- https://posthog.com/docs/distributed-tracing/installation.md
39 changes: 39 additions & 0 deletions context/skills/tracing/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# PostHog distributed tracing for {display_name}

This skill helps you send distributed traces from {display_name} applications to PostHog. A trace is a tree of spans that follows one request across services, queues, and external calls, so you can see where the time went and which step failed.

## Reference files

{references}

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.
- **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

1. **Request entry**: one server span per handled request, created in middleware or an equivalent single choke point, never per route by hand.
2. **Outbound calls**: HTTP clients, database queries, cache lookups, and queue publishes, so the trace shows which dependency was slow.
3. **Background work**: job and queue handlers, as the root span of their own trace or continuing the trace that enqueued them.

If the user asks for specific spans, instrument those instead. A few spans at choke points beat a span around every function.

## Key principles

- **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.
- **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.
- **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.
- **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

{commandments}
35 changes: 35 additions & 0 deletions scripts/lib/tests/tracing-skills.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { describe, expect, it } from 'vitest';
import { join } from 'path';

import { expandSkillGroups, loadSkillsConfig } from '../skill-generator.js';

const CONFIG_DIR = join(process.cwd(), 'context');

const SHARED_DOCS = [
'https://posthog.com/docs/distributed-tracing/start-here.md',
'https://posthog.com/docs/distributed-tracing/basics.md',
];

describe('tracing skill family', () => {
it('ships one variant per platform, each carrying its installation doc', () => {
const config = loadSkillsConfig(CONFIG_DIR);
const skills = expandSkillGroups(config, CONFIG_DIR).filter((s) => s._group === 'tracing');

expect(skills.map((s) => s.id).sort()).toEqual([
'tracing-dotnet',
'tracing-go',
'tracing-java',
'tracing-nextjs',
'tracing-nodejs',
'tracing-other',
'tracing-php',
'tracing-python',
'tracing-ruby',
]);
for (const s of skills) {
expect(s._sharedDocs).toEqual(SHARED_DOCS);
}
const nodejs = skills.find((s) => s.id === 'tracing-nodejs');
expect(nodejs.docs_urls).toEqual(['https://posthog.com/docs/distributed-tracing/installation/nodejs.md']);
});
});
Loading