Skip to content

Commit fe07bdf

Browse files
authored
Merge pull request #24620 from getsentry/prepare-release/11.0.0
meta(changelog): Update changelog for 11.0.0
2 parents 0dc1050 + ed38fe7 commit fe07bdf

6,938 files changed

Lines changed: 211504 additions & 183314 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/add-ai-integration/SKILL.md‎

Lines changed: 41 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -6,116 +6,61 @@ argument-hint: <provider-name>
66

77
# Adding a New AI Integration
88

9-
## Decision Tree
9+
## Conventions First
1010

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)
11+
Span ops and attributes are specified outside this repo. Never invent or hardcode either:
4712

48-
## Token Accumulation
13+
- [gen_ai attributes](https://getsentry.github.io/sentry-conventions/attributes/gen_ai/) and [gen_ai ops](https://getsentry.github.io/sentry-conventions/ops/#gen_ai) — normative; import from `@sentry/conventions/attributes` and `@sentry/conventions/op`
14+
- [RFC 0153](https://github.com/getsentry/rfcs/blob/main/text/0153-decoupling-sentrys-generative-ai-conventions-from-open-telemetry.md) — why Sentry's gen-AI conventions diverge from the [OTel gen-ai semconv](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
4915

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/`)
16+
Derive the op with `getGenAiSpanOp()` from `ai/core/utils.ts` rather than picking one by hand. `ai/core/gen-ai-attributes.ts` is for gap-fillers only — keys with no `@sentry/conventions` equivalent — so check it last, not first.
5217

53-
## Pattern 1: OTel Span Processors
18+
## Which Pattern
5419

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.
20+
```
21+
Does the SDK publish its own `diagnostics_channel` telemetry?
22+
|- YES (ai >= 7) -> Pattern 1: Native tracing channel
23+
+- NO -> Does the SDK expose callback/exporter hooks?
24+
|- YES (LangChain, Mastra) -> Pattern 3: Callback/Exporter
25+
+- NO (OpenAI, Anthropic, Google GenAI, ai < 7) -> Pattern 2: Orchestrion-injected channels
26+
```
7927

80-
Reference: `packages/node/src/integrations/tracing/langchain/`
28+
| Pattern | Use when | Reference |
29+
| -------------------------- | ------------------------------------------ | --------------------------------------------------------------- |
30+
| 1 — Native tracing channel | the SDK publishes to `diagnostics_channel` | `integrations/vercel-ai/vercel-ai-dc-subscriber.ts` |
31+
| 2 — Orchestrion channels | the SDK has no telemetry of its own | `integrations/openai.ts` + `orchestrion/config/openai.ts` |
32+
| 3 — Callback/exporter | the SDK exposes hooks or an exporter | `ai/langchain/`, `ai/mastra/` (exporter-shaped agent framework) |
8133

82-
## Auto-Instrumentation (Node.js)
34+
What the reference files won't tell you:
8335

84-
**Mandatory** for Node.js AI integrations. OTel only patches when the package is imported (zero cost if unused).
36+
- A provider can need two patterns at once: `vercelAIIntegration` subscribes to native `ai:telemetry` for `ai` >= 7 _and_ runs orchestrion injection for v4-v6.
37+
- Pattern 1 subscribers are safe to register unconditionally — subscribing is a no-op on SDK versions that never publish.
8538

86-
### Steps
39+
## Where The Code Goes
8740

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}/`
41+
- **Instrumentation** -> `packages/server-utils/src/ai/{provider}/`
42+
- **Integration** -> `packages/server-utils/src/integrations/{provider}.ts`
43+
- Runtime packages (`node`, `cloudflare`, `bun`, ...) re-export from `@sentry/server-utils` — they never define their own
44+
- Exception: Workers AI is client-wrapped in `packages/cloudflare/src/instrumentations/worker/instrumentEnv.ts`
9545

96-
## Key Rules
46+
## Gotchas
9747

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
48+
1. **Detect streaming from the result shape** — an async-iterable or the SDK's stream object — not from `params.stream`. Only the manual `instrument{Provider}Client()` API keys off `params.stream === true`.
49+
2. **Never set streamed response attributes by hand.** Accumulate into a `StreamResponseState` and call `endStreamSpan()` (`ai/openai/streaming.ts` for an async generator, `ai/anthropic-ai/streaming.ts` for a listener-based stream).
50+
3. **Never truncate message payloads.** Truncation was removed in v11 (#23045) and nothing downstream caps them; size limiting is server-side.
51+
4. **Never roll child token usage up onto parent spans.** Tree totals are computed product-side from the full span tree.
52+
5. **Never read `dataCollection.genAI` directly.** Gate input/output recording on `resolveAIRecordingOptions()`.
53+
6. **LangChain must be registered first** in `getTracingIntegrations()`, so it can disable the provider integrations before they instrument.
54+
7. Set `SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = 'auto.ai.{provider}'` (alphanumerics, `_`, `.` only).
10255

10356
## Checklist
10457

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/`
58+
- [ ] Instrumentation in `src/ai/`, integration in `src/integrations/`, registered in `getTracingIntegrations()` (LangChain first)
59+
- [ ] Exported from `packages/server-utils/src/index.ts`, re-exported from the supported runtime packages
60+
- [ ] E2E tests in `dev-packages/node-integration-tests/suites/tracing/{provider}/` (and `cloudflare-integration-tests/` if supported)
61+
- [ ] Ops and attributes from `@sentry/conventions`, op derived via `getGenAiSpanOp()`
62+
- [ ] Recording gated on `resolveAIRecordingOptions()`; no truncation, no token rollup
63+
- [ ] JSDoc names the channels subscribed to, the supported SDK versions, and — for Pattern 2 — that it requires the Sentry runtime hook or bundler plugin
64+
- [ ] Patching happens only once the target package is imported (zero cost if unused)
12065

12166
**When in doubt, follow the pattern of the most similar existing integration.**

0 commit comments

Comments
 (0)