diff --git a/MIGRATION.md b/MIGRATION.md index 9582bf374888..da52af69448c 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -256,6 +256,7 @@ Affected SDKs: All SDKs. - The `gen_ai.request.available_tools` span attribute was renamed to `gen_ai.tool.definitions` across all AI integrations. - The `gen_ai.tool.input` span attribute was renamed to `gen_ai.tool.call.arguments` across all AI integrations. - The `gen_ai.tool.output` span attribute was renamed to `gen_ai.tool.call.result` across all AI integrations. +- The Vercel AI token attributes `gen_ai.usage.input_tokens.cached`, `gen_ai.usage.input_tokens.cache_write`, and `gen_ai.usage.output_tokens.reasoning` were renamed to `gen_ai.usage.cache_read.input_tokens`, `gen_ai.usage.cache_creation.input_tokens`, and `gen_ai.usage.reasoning.output_tokens`. - Span attributes now use the shared `@sentry/conventions` package under the hood. If you reference these attributes in custom instrumentation, `beforeSendSpan`, dashboards, or alerts, update them to the new names. diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7/test.ts index 17ca077a0422..6aa2280e57a3 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/v6_v7/test.ts @@ -16,9 +16,10 @@ import { GEN_AI_TOOL_DESCRIPTION, GEN_AI_TOOL_NAME, GEN_AI_TOOL_TYPE, + GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS, - GEN_AI_USAGE_INPUT_TOKENS_CACHED, GEN_AI_USAGE_OUTPUT_TOKENS, + GEN_AI_USAGE_REASONING_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; import { GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; @@ -793,8 +794,8 @@ describe.each(matrix)('Vercel AI integration (version %s)', (version, vercelAiVe // Cache/reasoning token breakdown and conversation id are derived from the model's // `providerMetadata` — by the OTel processor on v6 and by the channel subscriber on v7, // both via the shared `getProviderMetadataAttributes` helper, so the shape is identical. - expect(generateContent.attributes[GEN_AI_USAGE_INPUT_TOKENS_CACHED]?.value).toBe(5); - expect(generateContent.attributes['gen_ai.usage.output_tokens.reasoning']?.value).toBe(7); + expect(generateContent.attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS]?.value).toBe(5); + expect(generateContent.attributes[GEN_AI_USAGE_REASONING_OUTPUT_TOKENS]?.value).toBe(7); expect(generateContent.attributes[GEN_AI_CONVERSATION_ID]?.value).toBe('resp_abc123'); const invokeAgent = container.items.find( diff --git a/packages/core/src/tracing/vercel-ai/index.ts b/packages/core/src/tracing/vercel-ai/index.ts index 12a02030db3e..0ac89af81399 100644 --- a/packages/core/src/tracing/vercel-ai/index.ts +++ b/packages/core/src/tracing/vercel-ai/index.ts @@ -24,10 +24,11 @@ import { GEN_AI_TOOL_DESCRIPTION, GEN_AI_TOOL_NAME, GEN_AI_TOOL_TYPE, + GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, + GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, GEN_AI_USAGE_INPUT_TOKENS, - GEN_AI_USAGE_INPUT_TOKENS_CACHED, - GEN_AI_USAGE_INPUT_TOKENS_CACHE_WRITE, GEN_AI_USAGE_OUTPUT_TOKENS, + GEN_AI_USAGE_REASONING_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; import { GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../ai/gen-ai-attributes'; @@ -256,7 +257,7 @@ function buildOutputMessages(attributes: Record): void { export function processVercelAiSpanAttributes(attributes: Record): void { renameAttributeKey(attributes, AI_USAGE_COMPLETION_TOKENS_ATTRIBUTE, GEN_AI_USAGE_OUTPUT_TOKENS); renameAttributeKey(attributes, AI_USAGE_PROMPT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS); - renameAttributeKey(attributes, AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_INPUT_TOKENS_CACHED); + renameAttributeKey(attributes, AI_USAGE_CACHED_INPUT_TOKENS_ATTRIBUTE, GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS); // Parent spans (ai.streamText, ai.streamObject, etc.) use inputTokens/outputTokens instead of promptTokens/completionTokens renameAttributeKey(attributes, 'ai.usage.inputTokens', GEN_AI_USAGE_INPUT_TOKENS); @@ -276,10 +277,10 @@ export function processVercelAiSpanAttributes(attributes: Record { }); expect(span.data?.['gen_ai.usage.input_tokens']).toBe(150); - expect(span.data?.['gen_ai.usage.input_tokens.cached']).toBe(50); + expect(span.data?.['gen_ai.usage.cache_read.input_tokens']).toBe(50); expect(span.data?.['gen_ai.usage.total_tokens']).toBe(150); }); @@ -57,7 +57,7 @@ describe('vercel-ai cached tokens', () => { }); expect(span.data?.['gen_ai.usage.input_tokens']).toBe(9500); - expect(span.data?.['gen_ai.usage.input_tokens.cached']).toBe(8000); + expect(span.data?.['gen_ai.usage.cache_read.input_tokens']).toBe(8000); expect(span.data?.['gen_ai.usage.output_tokens']).toBe(300); expect(span.data?.['gen_ai.usage.total_tokens']).toBe(9800); });