Skip to content

Commit 9b1030f

Browse files
committed
ai integrations
1 parent f323baa commit 9b1030f

2 files changed

Lines changed: 121 additions & 403 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
name: add-ai-integration
3+
description: Add a new AI provider integration to the Sentry JavaScript SDK. Use when contributing a new AI instrumentation (OpenAI, Anthropic, Vercel AI, LangChain, etc.) or modifying an existing one.
4+
argument-hint: <provider-name>
5+
---
6+
7+
# Adding a New AI Integration
8+
9+
## Decision Tree
10+
11+
```
12+
Does the AI SDK have native OpenTelemetry support?
13+
|- YES -> Does it emit OTel spans automatically?
14+
| |- YES (like Vercel AI) -> Pattern 1: OTel Span Processors
15+
| +- NO -> Pattern 2: OTel Instrumentation (wrap client)
16+
+- NO -> Does the SDK provide hooks/callbacks?
17+
|- YES (like LangChain) -> Pattern 3: Callback/Hook Based
18+
+- NO -> Pattern 4: Client Wrapping
19+
```
20+
21+
## Runtime-Specific Placement
22+
23+
If an AI SDK only works in one runtime, code lives exclusively in that runtime's package. Do NOT add it to `packages/core/`.
24+
25+
- **Node.js-only** -> `packages/node/src/integrations/tracing/{provider}/`
26+
- **Cloudflare-only** -> `packages/cloudflare/src/integrations/tracing/{provider}.ts`
27+
- **Browser-only** -> `packages/browser/src/integrations/tracing/{provider}/`
28+
- **Multi-runtime** -> shared core in `packages/core/src/tracing/{provider}/` with runtime-specific wrappers
29+
30+
## Span Hierarchy
31+
32+
- `gen_ai.invoke_agent` — parent/pipeline spans (chains, agents, orchestration)
33+
- `gen_ai.chat`, `gen_ai.generate_text`, etc. — child spans (actual LLM calls)
34+
35+
## Shared Utilities (`packages/core/src/tracing/ai/`)
36+
37+
- `gen-ai-attributes.ts` — OTel Semantic Convention attribute constants. **Always use these, never hardcode.**
38+
- `utils.ts``setTokenUsageAttributes()`, `getTruncatedJsonString()`, `truncateGenAiMessages()`, `buildMethodPath()`
39+
- Only use attributes from [Sentry Gen AI Conventions](https://getsentry.github.io/sentry-conventions/attributes/gen_ai/).
40+
41+
## Streaming
42+
43+
- **Non-streaming:** `startSpan()`, set attributes from response
44+
- **Streaming:** `startSpanManual()`, accumulate state via async generator or event listeners, set `GEN_AI_RESPONSE_STREAMING_ATTRIBUTE: true`, call `span.end()` in finally block
45+
- Detect via `params.stream === true`
46+
- References: `openai/streaming.ts` (async generator), `anthropic-ai/streaming.ts` (event listeners)
47+
48+
## Token Accumulation
49+
50+
- **Child spans:** Set tokens directly from API response via `setTokenUsageAttributes()`
51+
- **Parent spans (`invoke_agent`):** Accumulate from children using event processor (see `vercel-ai/`)
52+
53+
## Pattern 1: OTel Span Processors
54+
55+
**Use when:** SDK emits OTel spans automatically (Vercel AI)
56+
57+
1. **Core:** Create `add{Provider}Processors()` in `packages/core/src/tracing/{provider}/index.ts` — registers `spanStart` listener + event processor
58+
2. **Node.js:** Add `callWhenPatched()` optimization in `packages/node/src/integrations/tracing/{provider}/index.ts` — defers registration until package is imported
59+
3. **Edge:** Direct registration in `packages/cloudflare/src/integrations/tracing/{provider}.ts` — no OTel, call processors immediately
60+
61+
Reference: `packages/node/src/integrations/tracing/vercelai/`
62+
63+
## Pattern 2: OTel Instrumentation (Client Wrapping)
64+
65+
**Use when:** SDK has no native OTel support (OpenAI, Anthropic, Google GenAI)
66+
67+
1. **Core:** Create `instrument{Provider}Client()` in `packages/core/src/tracing/{provider}/index.ts` — Proxy to wrap client methods, create spans manually
68+
2. **Node.js `instrumentation.ts`:** Patch module exports, wrap client constructor. Check `_INTERNAL_shouldSkipAiProviderWrapping()` for LangChain compatibility.
69+
3. **Node.js `index.ts`:** Export integration function using `generateInstrumentOnce()` helper
70+
71+
Reference: `packages/node/src/integrations/tracing/openai/`
72+
73+
## Pattern 3: Callback/Hook Based
74+
75+
**Use when:** SDK provides lifecycle hooks (LangChain, LangGraph)
76+
77+
1. **Core:** Create `create{Provider}CallbackHandler()` — implement SDK's callback interface, create spans in callbacks
78+
2. **Node.js `instrumentation.ts`:** Auto-inject callbacks by patching runnable methods. Disable underlying AI provider wrapping.
79+
80+
Reference: `packages/node/src/integrations/tracing/langchain/`
81+
82+
## Auto-Instrumentation (Node.js)
83+
84+
**Mandatory** for Node.js AI integrations. OTel only patches when the package is imported (zero cost if unused).
85+
86+
### Steps
87+
88+
1. **Add to `getAutoPerformanceIntegrations()`** in `packages/node/src/integrations/tracing/index.ts` — LangChain MUST come first
89+
2. **Add to `getOpenTelemetryInstrumentationToPreload()`** for OTel-based integrations
90+
3. **Export from `packages/node/src/index.ts`**: integration function + options type
91+
4. **Add E2E tests:**
92+
- Node.js: `dev-packages/node-integration-tests/suites/tracing/{provider}/`
93+
- Cloudflare: `dev-packages/cloudflare-integration-tests/suites/tracing/{provider}/`
94+
- Browser: `dev-packages/browser-integration-tests/suites/tracing/ai-providers/{provider}/`
95+
96+
## Key Rules
97+
98+
1. Respect `sendDefaultPii` for `recordInputs`/`recordOutputs`
99+
2. Set `SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = 'auto.ai.{provider}'` (alphanumerics, `_`, `.` only)
100+
3. Truncate large data with helper functions from `utils.ts`
101+
4. `gen_ai.invoke_agent` for parent ops, `gen_ai.chat` for child ops
102+
103+
## Checklist
104+
105+
- [ ] Runtime-specific code placed only in that runtime's package
106+
- [ ] Added to `getAutoPerformanceIntegrations()` in correct order (Node.js)
107+
- [ ] Added to `getOpenTelemetryInstrumentationToPreload()` (Node.js with OTel)
108+
- [ ] Exported from appropriate package index
109+
- [ ] E2E tests added and verifying auto-instrumentation
110+
- [ ] Only used attributes from [Sentry Gen AI Conventions](https://getsentry.github.io/sentry-conventions/attributes/gen_ai/)
111+
- [ ] JSDoc says "enabled by default" or "not enabled by default"
112+
- [ ] Documented how to disable (if auto-enabled)
113+
- [ ] Verified OTel only patches when package imported (Node.js)
114+
115+
## Reference Implementations
116+
117+
- **Pattern 1 (Span Processors):** `packages/node/src/integrations/tracing/vercelai/`
118+
- **Pattern 2 (Client Wrapping):** `packages/node/src/integrations/tracing/openai/`
119+
- **Pattern 3 (Callback/Hooks):** `packages/node/src/integrations/tracing/langchain/`
120+
121+
**When in doubt, follow the pattern of the most similar existing integration.**

0 commit comments

Comments
 (0)