Skip to content
7 changes: 6 additions & 1 deletion MIGRATION.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These need to go into docs/migration/v11-end-state.md I think

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, #23510!

Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,8 @@ The LangGraph instrumentation no longer emits `gen_ai.create_agent` spans when a

**Tracing removed from generated templates:** Tracing was removed from the generated Pages Router API handler, Edge API handler, and Middleware wrapper templates. Route handlers and middleware are still instrumented automatically, so no action is required for most users.

**Vercel AI no longer supported on Edge runtime:** We now rely on diagnostics channels for our Vercel AI instrumentation, which does not work on the Edge runtime. Because of this, monitoring of the `ai` package is no longer supported on Edge. Note that Edge is deprecated.

### Cloudflare: `nodejs_compat` compatibility flag is now required

Affected SDKs: `@sentry/cloudflare`.
Expand Down Expand Up @@ -871,7 +873,10 @@ Sentry.init({
- The internal `sentry.sdk_meta.gen_ai.input.messages.original_length` span attribute was removed.
- (Vercel AI) The internal JSON-stringify workaround for array span attributes was removed.
- AI integrations are no longer available in the browser SDK. They remain available in the server-side SDKs.
- The AI instrumentation code moved out of `@sentry/core` into `@sentry/server-utils`. If you imported any AI helper **directly from `@sentry/core`**, import it from `@sentry/server-utils` instead (or keep importing it from your platform SDK, e.g. `@sentry/node`, if it re-exported that helper before — platform SDK availability is unchanged from v10). Affected helpers: `instrumentOpenAiClient`, `instrumentAnthropicAiClient`, `instrumentGoogleGenAIClient`, `instrumentWorkersAiClient`, `createLangChainCallbackHandler`, `instrumentLangChainEmbeddings`, `instrumentStateGraph`, `instrumentStateGraphCompile`, `instrumentCreateReactAgent`, `addVercelAiProcessors`.
- The AI instrumentation code moved out of `@sentry/core` into `@sentry/server-utils`. If you imported any AI helper **directly from `@sentry/core`**, import it from `@sentry/server-utils` instead (or keep importing it from your platform SDK, e.g. `@sentry/node`, if it re-exported that helper before — platform SDK availability is unchanged from v10). Affected helpers: `instrumentOpenAiClient`, `instrumentAnthropicAiClient`, `instrumentGoogleGenAIClient`, `instrumentWorkersAiClient`, `createLangChainCallbackHandler`, `instrumentLangChainEmbeddings`, `instrumentStateGraph`, `instrumentStateGraphCompile`, `instrumentCreateReactAgent`.
- The `addVercelAiProcessors` helper was removed. It was an internal building block for setting up Vercel AI span processing by hand; `vercelAIIntegration()` now wires this up on its own, so add that integration instead of calling `addVercelAiProcessors` directly.
- (Vercel Edge) `vercelAIIntegration` was removed from `@sentry/vercel-edge`; Vercel AI is not instrumented on the Edge runtime. `@sentry/nextjs` keeps the export on its Edge build as a no-op (so `import { vercelAIIntegration }` from `@sentry/nextjs` still resolves in edge-compiled instrumentation files), with the real instrumentation running only in the Node runtime.
- (Cloudflare & Deno) `vercelAIIntegration` no longer post-processes the OpenTelemetry spans emitted by the `ai` SDK. Instrumentation now goes solely through the channel-based instrumentation, the same as the other server SDKs.
- The following low-level AI exports are no longer part of the public API (they were provider-instrumentation internals exported from `@sentry/core`):
- Attribute/stream/util helpers: `extractOpenAiRequestAttributes`, `addOpenAiRequestAttributes`, `addOpenAiResponseAttributes`, `extractOpenAiRequestParameters`, `instrumentOpenAiStream`, `extractAnthropicRequestAttributes`, `addAnthropicRequestAttributes`, `addAnthropicResponseAttributes`, `instrumentAsyncIterableStream`, `instrumentMessageStream`, `extractGoogleGenAIRequestAttributes`, `addGoogleGenAIRequestAttributes`, `addGoogleGenAIResponseAttributes`, `instrumentGoogleGenAIStream`, `getProviderMetadataAttributes`, `getTruncatedJsonString`, `shouldEnableTruncation`, `resolveAIRecordingOptions`, `wrapToolsWithSpans`, `extractLLMFromParams`, `extractAgentNameFromParams`, `instrumentCompiledGraphInvoke`.
- Integration-name constants: `OPENAI_INTEGRATION_NAME`, `ANTHROPIC_AI_INTEGRATION_NAME`, `GOOGLE_GENAI_INTEGRATION_NAME`, `LANGCHAIN_INTEGRATION_NAME`, `LANGGRAPH_INTEGRATION_NAME`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ export default Sentry.withSentry(
dsn: env.SENTRY_DSN,
traceLifecycle: 'static',
tracesSampleRate: 1,
// The Vercel AI SDK emits its spans through `@opentelemetry/api`, so they are only picked up when
// the Cloudflare OpenTelemetry tracer provider is set up.
enableOpenTelemetrySetup: true,
}),
{
async fetch(_request, _env, _ctx) {
await generateText({
experimental_telemetry: { isEnabled: true },
model: new MockLanguageModelV3({
doGenerate: async () => ({
finishReason: { unified: 'stop', raw: 'stop' },
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export { getDefaultIntegrations } from './sdk';
export { httpServerIntegration } from './integrations/httpServer';
export { fetchIntegration } from './integrations/fetch';
export { spotlightIntegration } from './integrations/spotlight';
export { vercelAIIntegration } from './integrations/tracing/vercelai';
export {
otlpIntegration,
getOtlpTracesEndpoint,
Expand All @@ -135,6 +134,7 @@ export {
instrumentStateGraph,
instrumentCreateReactAgent,
} from '@sentry/server-utils';
export { vercelAIIntegration } from '@sentry/server-utils/orchestrion';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The exported vercelAIIntegration for Cloudflare will fail if the nodejs_compat flag is not enabled, as it lacks a guard for the node:diagnostics_channel dependency.
Severity: HIGH

Suggested Fix

Add a guard in the orchestrion version of vercelAIIntegration (packages/server-utils/src/integrations/vercel-ai.ts) to check if dc.tracingChannel is available before using it, similar to the guard in the base integration. This will prevent crashes in environments without Node.js compatibility, like default Cloudflare Workers. Alternatively, do not export this integration from the @sentry/cloudflare package.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/cloudflare/src/index.ts#L137

Potential issue: The `vercelAIIntegration` exported from `@sentry/cloudflare`
(re-exported from `@sentry/server-utils/orchestrion`) unconditionally imports and uses
`node:diagnostics_channel`. However, this module is only available in Cloudflare Workers
when the `nodejs_compat` compatibility flag is enabled. Unlike the base integration,
this version lacks a runtime guard to check for the existence of `dc.tracingChannel`.
Consequently, any Cloudflare user who uses this integration without enabling
`nodejs_compat` will experience a runtime error when the application attempts to load
the missing Node.js module.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can be ignored.


export { instrumentWorkflowWithSentry } from './workflows';

Expand Down
56 changes: 0 additions & 56 deletions packages/cloudflare/src/integrations/tracing/vercelai.ts

This file was deleted.

4 changes: 0 additions & 4 deletions packages/cloudflare/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import type { CloudflareClient, CloudflareOptions } from './client';

/**
* Get the default integrations for the Cloudflare SDK.
*
* This is the full set and requires the `nodejs_compat` compatibility flag. Runtimes that cannot
* enable it (e.g. Shopify Oxygen) go through `wrapRequestHandler`, which only sets up
* `getBaseDefaultIntegrations`.
*/
export function getDefaultIntegrations(options: CloudflareOptions): Integration[] {
return getBaseDefaultIntegrations(options);
Expand Down
51 changes: 1 addition & 50 deletions packages/deno/src/integrations/tracing/vercelai.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1 @@
/**
* This is a copy of the Vercel AI integration from the cloudflare SDK.
*/

import type { IntegrationFn } from '@sentry/core';
import { defineIntegration, extendIntegration } from '@sentry/core';
import {
addVercelAiProcessors,
vercelAIIntegration as serverUtilsVercelAiIntegration,
type VercelAiOptions,
} from '@sentry/server-utils';

const _vercelAIIntegration = ((options: VercelAiOptions = {}) => {
const inner = serverUtilsVercelAiIntegration(options);

return extendIntegration(inner, {
options,
setup(client) {
addVercelAiProcessors(client);
},
});
}) satisfies IntegrationFn;

/**
* Adds Sentry tracing instrumentation for the [ai](https://www.npmjs.com/package/ai) library.
* This integration is not enabled by default, you need to manually add it.
*
* For more information, see the [`ai` documentation](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).
*
* You need to enable collecting spans for a specific call by setting
* `experimental_telemetry.isEnabled` to `true` in the first argument of the function call.
*
* ```javascript
* const result = await generateText({
* model: openai('gpt-4-turbo'),
* experimental_telemetry: { isEnabled: true },
* });
* ```
*
* If you want to collect inputs and outputs for a specific call, you must specifically opt-in to each
* function call by setting `experimental_telemetry.recordInputs` and `experimental_telemetry.recordOutputs`
* to `true`.
*
* ```javascript
* const result = await generateText({
* model: openai('gpt-4-turbo'),
* experimental_telemetry: { isEnabled: true, recordInputs: true, recordOutputs: true },
* });
*/
export const vercelAIIntegration = defineIntegration(_vercelAIIntegration);
export { vercelAIIntegration } from '@sentry/server-utils/orchestrion';
12 changes: 12 additions & 0 deletions packages/nextjs/src/common/vercelAIIntegrationShim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineIntegration } from '@sentry/core';

/**
* Shim for the edge build so named imports from `@sentry/nextjs` stay resolvable in
* edge-compiled instrumentation modules. The real implementation ships in the server build;
* Vercel AI is not instrumented on the edge runtime.
*/
export const vercelAIIntegration = defineIntegration(() => {
return {
name: 'VercelAI',
};
});
1 change: 1 addition & 0 deletions packages/nextjs/src/edge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export * from '../common';
export { captureUnderscoreErrorException } from '../common/pages-router-instrumentation/_error';

export { pinoIntegration } from '../common/pinoIntegrationShim';
export { vercelAIIntegration } from '../common/vercelAIIntegrationShim';

// Override core span methods with Next.js-specific implementations that support Cache Components
export { startSpan, startSpanManual, startInactiveSpan } from '../common/utils/nextSpan';
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import { maybeCleanupQueueSpan } from './vercelQueuesMonitoring';

export * from '@sentry/node';

// Explicitly re-export so it is statically detectable by turbopack
export { pinoIntegration } from '@sentry/node';
// Explicitly re-export so these are statically detectable by turbopack
export { pinoIntegration, vercelAIIntegration } from '@sentry/node';

export { captureUnderscoreErrorException } from '../common/pages-router-instrumentation/_error';

Expand Down
15 changes: 10 additions & 5 deletions packages/nextjs/test/serverExports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ import { beforeAll, describe, expect, it } from 'vitest';
/**
* Node-only exports must be statically resolvable from the server AND edge builds, since Next.js compiles
* instrumentation modules for the edge runtime too. Otherwise named imports from `@sentry/nextjs` fail to compile
* under Turbopack/webpack.
* under Turbopack/webpack. Exports that are Node-only get a no-op shim on the edge build (e.g. `vercelAIIntegration`).
*
*
* Regression test for https://github.com/getsentry/sentry-javascript/issues/21317
*/
describe('`pinoIntegration` is a statically detectable export from every runtime build', () => {
describe('Node-only integrations are statically detectable exports from every runtime build', () => {
const builds = {
server: resolve(__dirname, '../build/cjs/index.server.js'),
edge: resolve(__dirname, '../build/cjs/edge/index.js'),
};

const dualRuntimeExports = ['pinoIntegration', 'vercelAIIntegration'];

const staticExports: Record<string, string[]> = {};

beforeAll(async () => {
Expand All @@ -26,7 +28,10 @@ describe('`pinoIntegration` is a statically detectable export from every runtime
}
});

it.each(Object.keys(builds))('statically exports `pinoIntegration` from the %s build', runtime => {
expect(staticExports[runtime]).toContain('pinoIntegration');
});
it.each(Object.keys(builds).flatMap(runtime => dualRuntimeExports.map(name => ({ runtime, name }))))(
'statically exports `$name` from the $runtime build',
({ runtime, name }) => {
expect(staticExports[runtime]).toContain(name);
},
);
});
1 change: 0 additions & 1 deletion packages/server-utils/src/ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ export { instrumentGoogleGenAIClient } from './google-genai';
export { instrumentWorkersAiClient } from './workers-ai';
export { createLangChainCallbackHandler, instrumentLangChainEmbeddings } from './langchain';
export { instrumentStateGraph, instrumentStateGraphCompile, instrumentCreateReactAgent } from './langgraph';
export { addVercelAiProcessors } from './vercel-ai';
22 changes: 0 additions & 22 deletions packages/server-utils/src/ai/vercel-ai/constants.ts

This file was deleted.

Loading
Loading