Skip to content

Commit cd07bd0

Browse files
andrewm4894claude
andcommitted
feat: Add Pydantic AI instrumentation via OpenTelemetry
Add OpenTelemetry-based instrumentation for Pydantic AI agents: - PostHogSpanExporter: Generic OTel exporter that translates spans to PostHog events - PydanticAISpanExporter: Wrapper that normalizes Pydantic AI message formats and tool attributes - instrument_pydantic_ai(): One-liner setup function for easy integration Usage: from posthog.ai.pydantic_ai import instrument_pydantic_ai instrument_pydantic_ai(posthog_client, distinct_id="user_123") agent = Agent("openai:gpt-4") result = await agent.run("Hello") # Automatically traced Co-Authored-By: Claude <[email protected]>
1 parent c253e41 commit cd07bd0

File tree

13 files changed

+2201
-0
lines changed

13 files changed

+2201
-0
lines changed

posthog/ai/otel/README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# PostHog OpenTelemetry Integration
2+
3+
This module provides a generic OpenTelemetry `SpanExporter` that translates OTel spans into PostHog AI analytics events.
4+
5+
## Overview
6+
7+
Many AI/LLM frameworks use OpenTelemetry for instrumentation. This exporter allows PostHog to receive telemetry from any OTel-instrumented framework by converting spans to PostHog events.
8+
9+
```
10+
┌─────────────────┐ ┌──────────────┐ ┌─────────────────────┐ ┌─────────┐
11+
│ AI Framework │────>│ OTel Spans │────>│ PostHogSpanExporter │────>│ PostHog │
12+
│ (Pydantic AI, │ │ (native) │ │ (translates spans) │ │ Events │
13+
│ LlamaIndex...) │ └──────────────┘ └─────────────────────┘ └─────────┘
14+
└─────────────────┘
15+
```
16+
17+
## Usage
18+
19+
```python
20+
from opentelemetry.sdk.trace import TracerProvider
21+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
22+
from posthog import Posthog
23+
from posthog.ai.otel import PostHogSpanExporter
24+
25+
# Create PostHog client
26+
posthog = Posthog(project_api_key="phc_xxx", host="https://us.i.posthog.com")
27+
28+
# Create exporter and tracer provider
29+
exporter = PostHogSpanExporter(
30+
client=posthog,
31+
distinct_id="user_123",
32+
privacy_mode=False, # Set True to exclude message content
33+
)
34+
35+
provider = TracerProvider()
36+
provider.add_span_processor(BatchSpanProcessor(exporter))
37+
38+
# Use this provider with your OTel-instrumented framework
39+
```
40+
41+
## Span to Event Mapping
42+
43+
The exporter classifies spans and maps them to PostHog events:
44+
45+
| Span Type | PostHog Event | Detection |
46+
|-----------|---------------|-----------|
47+
| Model request | `$ai_generation` | Span name starts with "chat" or has `gen_ai.request.model` |
48+
| Tool execution | `$ai_span` | Span name contains "tool" or has `gen_ai.tool.name` |
49+
| Agent orchestration | (skipped) | Span name contains "agent" |
50+
51+
## GenAI Semantic Conventions
52+
53+
The exporter follows [OpenTelemetry GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/):
54+
55+
| OTel Attribute | PostHog Property |
56+
|----------------|------------------|
57+
| `gen_ai.request.model` | `$ai_model` |
58+
| `gen_ai.system` | `$ai_provider` |
59+
| `gen_ai.usage.input_tokens` | `$ai_input_tokens` |
60+
| `gen_ai.usage.output_tokens` | `$ai_output_tokens` |
61+
| `gen_ai.input.messages` | `$ai_input` |
62+
| `gen_ai.output.messages` | `$ai_output_choices` |
63+
| `gen_ai.tool.name` | `$ai_span_name` |
64+
| `gen_ai.tool.call.arguments` | `$ai_tool_arguments` |
65+
| `gen_ai.tool.call.result` | `$ai_tool_result` |
66+
67+
## Configuration Options
68+
69+
| Parameter | Type | Description |
70+
|-----------|------|-------------|
71+
| `client` | `Posthog` | PostHog client instance |
72+
| `distinct_id` | `str` | User identifier (falls back to trace ID if not set) |
73+
| `privacy_mode` | `bool` | Exclude message content from events |
74+
| `properties` | `dict` | Additional properties to include in all events |
75+
| `groups` | `dict` | PostHog groups for all events |
76+
| `debug` | `bool` | Enable debug logging |
77+
78+
## Framework-Specific Exporters
79+
80+
For frameworks with non-standard attribute names or message formats, use the framework-specific exporter wrapper:
81+
82+
- **Pydantic AI**: Use `posthog.ai.pydantic_ai.PydanticAISpanExporter` or the simpler `instrument_pydantic_ai()` function
83+
84+
These wrappers normalize framework-specific formats before passing spans to `PostHogSpanExporter`.

posthog/ai/otel/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""
2+
OpenTelemetry integration for PostHog AI observability.
3+
4+
This module provides a SpanExporter that translates OpenTelemetry spans
5+
(particularly GenAI semantic convention spans) into PostHog AI events.
6+
"""
7+
8+
from posthog.ai.otel.exporter import PostHogSpanExporter
9+
10+
__all__ = ["PostHogSpanExporter"]

0 commit comments

Comments
 (0)