From 7e09849b3d498db086473eac93ccc5fe86931cad Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Mon, 31 Aug 2026 18:16:44 +0200 Subject: [PATCH 1/2] docs(nextjs): Require experimental_telemetry for Vercel AI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Next.js the SDK cannot auto-enable the Vercel AI SDK's telemetry, so `experimental_telemetry` is required on every call in both the Node and Edge runtimes. The page scoped that requirement to Edge and claimed the Node runtime patches call sites automatically. Also correct the troubleshooting entry for raw span names. It presented `force: true` as the complete fix, but `force: true` alone only registers the span processors — following it as written produced no AI spans at all. Simplify the Next.js runtime split while here: it is kept for setup, where the two runtimes need different config files, and dropped where both runtimes now behave the same. Refs getsentry/sentry-javascript#23773 Co-Authored-By: Claude Opus 5 (1M context) --- .../common/agent-tracing/vercelai.mdx | 78 +++++++------------ 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/docs/platforms/javascript/common/agent-tracing/vercelai.mdx b/docs/platforms/javascript/common/agent-tracing/vercelai.mdx index 3995f4a208f89..d421e3ce03930 100644 --- a/docs/platforms/javascript/common/agent-tracing/vercelai.mdx +++ b/docs/platforms/javascript/common/agent-tracing/vercelai.mdx @@ -44,17 +44,16 @@ Don't use the AI SDK's `registerTelemetry` API (AI SDK v7 and above) together wi -Next.js runs your server code in two runtimes, and Sentry ships a different implementation for each. The Node implementation patches the `ai` module through OpenTelemetry. The Edge runtime can't load OpenTelemetry instrumentation, so it uses a reduced implementation that reads the spans the AI SDK emits on its own. +Next.js runs your server code in two runtimes. In both, you must pass `experimental_telemetry` on every call. See [Turn on telemetry](#turn-on-telemetry). -That difference decides where you configure the integration and which options do anything: +Everything else depends on which runtime you're in: -| | Node runtime | Edge runtime | -| --------------------------------- | --------------------------- | --------------------------------------- | -| Enabled by default | Yes | No — add it to `sentry.edge.config` | -| `experimental_telemetry` per call | Not needed | Required, or no spans are created | -| Record inputs and outputs | Integration or per call | Per call only | -| `force` | Available | Not available — always active | -| AI SDK v7 | Supported | Not supported | +| | Node runtime | Edge runtime | +| ------------------------- | ----------------------- | ----------------------------------- | +| Enabled by default | Yes | No — add it to `sentry.edge.config` | +| Record inputs and outputs | Integration or per call | Per call only | +| `force` | Available | Not available — always active | +| AI SDK v7 | Supported | Not supported | @@ -95,7 +94,7 @@ Prompts and completions are not captured until you opt in. See [Record inputs an ### Node Runtime -The integration is enabled by default. No setup code is needed beyond enabling tracing: +The integration is enabled by default: ```javascript {filename:sentry.server.config.ts} Sentry.init({ @@ -104,8 +103,6 @@ Sentry.init({ }); ``` -If spans are missing here, your build most likely bundled the `ai` package so module detection fails. See [Troubleshooting](#troubleshooting). - ### Edge Runtime The integration is not enabled by default. Add it yourself: @@ -118,7 +115,9 @@ Sentry.init({ }); ``` -Adding the integration is not enough on its own. The Edge runtime can't patch your call sites, so you must also pass `experimental_telemetry` on every call. See [Turn on telemetry](#turn-on-telemetry). +In both runtimes, adding the integration is not enough on its own. You must also pass `experimental_telemetry` on every call. See [Turn on telemetry](#turn-on-telemetry). + +If your spans have raw names like `ai.toolCall`, see [Troubleshooting](#troubleshooting). @@ -237,9 +236,7 @@ const result = await generateText({ -### Node Runtime - -Set the options on the integration to cover every call. Re-adding the integration replaces the default instance and configures it: +Set the options on the integration to cover every call (Node runtime only). Re-adding the integration replaces the default instance and configures it: ```javascript {filename:sentry.server.config.ts} Sentry.init({ @@ -254,26 +251,14 @@ Sentry.init({ }); ``` -To record only some calls, leave the integration options unset and set them per call instead: - -```javascript -const result = await generateText({ - model: openai("gpt-4o"), - experimental_telemetry: { - recordInputs: true, - recordOutputs: true, - }, -}); -``` - -### Edge runtime - The Edge runtime ignores `recordInputs` and `recordOutputs` on the integration. It accepts no error and logs no warning — your prompts are simply missing. Set both per call. +Or set them per call, which works in both runtimes: + ```javascript const result = await generateText({ model: openai("gpt-4o"), @@ -373,7 +358,7 @@ Every instrumented `ai` function takes an `experimental_telemetry` object. Use i -This applies to the **Edge** runtime only. On the Node runtime, Sentry patches your call sites for you. +Required in both the Node and Edge runtimes. @@ -444,12 +429,6 @@ Spans are captured without the `experimental_telemetry` block. Pass it only to s - - -This applies to the **Edge** runtime only. On the Node runtime, Sentry patches your call sites for you — pass `experimental_telemetry` only to set `functionId` or the recording options. - - - ```javascript const agent = new ToolLoopAgent({ model: openai("gpt-4o"), @@ -545,7 +524,7 @@ Sentry.init({ -Not available in the Edge runtime, where the integration is always active once you add it. +`force` only registers the span processors. You still need `experimental_telemetry` on every call. Not available in the Edge runtime, where the integration is always active once you add it. @@ -571,13 +550,7 @@ Spans are captured for these `ai` functions: - - -Spans are captured for these `ai` functions. On the Edge runtime, pass `experimental_telemetry` to each one, as described in [Turn on telemetry](#turn-on-telemetry): - - - - + Spans are captured for these `ai` functions. Pass `experimental_telemetry` to each one, as described in [Turn on telemetry](#turn-on-telemetry): @@ -629,11 +602,9 @@ Plus `generate()` and `stream()` on [`ToolLoopAgent`](#toolloopagent). -When deploying to Vercel, you may notice that AI SDK spans have raw names like `ai.toolCall` or `ai.streamText` instead of the expected semantic names like `gen_ai.execute_tool` or `gen_ai.stream_text`. - -This happens because the `ai` package is bundled (not externalized) in Next.js production builds, which prevents the integration from automatically detecting and instrumenting the module. +Two steps are required. `force: true` on its own is not enough — without the second step you get no AI spans at all. -To fix this, explicitly enable the integration with `force: true` in your `sentry.server.config.ts`: +Add the integration with `force: true`: ```javascript {filename:sentry.server.config.ts} Sentry.init({ @@ -642,7 +613,14 @@ Sentry.init({ }); ``` -The `force` option ensures the integration registers its span processors regardless of module detection. +And pass `experimental_telemetry` on every AI SDK call: + +```javascript +const result = await generateText({ + model: openai("gpt-4o"), + experimental_telemetry: { isEnabled: true }, +}); +``` From c341afeecabb05eacf17b45e94a35c2e2067e014 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Tue, 1 Sep 2026 11:31:07 +0200 Subject: [PATCH 2/2] docs(nextjs): Clarify what raw AI span names actually indicate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Raw `ai.*` span names mean the AI SDK is already emitting telemetry, so `experimental_telemetry` is not the missing step for that symptom — the span processors are. Lead with `force: true` and keep `experimental_telemetry` as something to preserve and extend, not to discover. Co-Authored-By: Claude Opus 5 (1M context) --- docs/platforms/javascript/common/agent-tracing/vercelai.mdx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/platforms/javascript/common/agent-tracing/vercelai.mdx b/docs/platforms/javascript/common/agent-tracing/vercelai.mdx index d421e3ce03930..f298e7400e095 100644 --- a/docs/platforms/javascript/common/agent-tracing/vercelai.mdx +++ b/docs/platforms/javascript/common/agent-tracing/vercelai.mdx @@ -602,9 +602,7 @@ Plus `generate()` and `stream()` on [`ToolLoopAgent`](#toolloopagent). -Two steps are required. `force: true` on its own is not enough — without the second step you get no AI spans at all. - -Add the integration with `force: true`: +Raw names mean the AI SDK's telemetry is already on and emitting spans — Sentry's span processors just aren't registered to rename them. Add `force: true`: ```javascript {filename:sentry.server.config.ts} Sentry.init({ @@ -613,7 +611,7 @@ Sentry.init({ }); ``` -And pass `experimental_telemetry` on every AI SDK call: +Keep `experimental_telemetry` on your calls. It's what produces the spans in the first place, so `force: true` without it leaves you with no AI spans at all. If only some of your spans have raw names, the remaining call sites are missing it: ```javascript const result = await generateText({