From 006be8488598be422d933925227e278a2299ae5c Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 1 Apr 2026 15:13:17 +0200 Subject: [PATCH 1/3] unify --- .../test-applications/deno/tests/ai.test.ts | 2 +- .../nextjs-15/tests/ai-error.test.ts | 2 +- .../nextjs-15/tests/ai-test.test.ts | 2 +- .../nextjs-16/tests/ai-error.test.ts | 2 +- .../nextjs-16/tests/ai-test.test.ts | 2 +- .../tracing/vercelai/test-generate-object.ts | 4 +- .../suites/tracing/vercelai/test.ts | 38 +++++++++---------- .../suites/tracing/vercelai/v5/test.ts | 28 +++++++------- .../suites/tracing/vercelai/v6/test.ts | 28 +++++++------- .../core/src/tracing/ai/gen-ai-attributes.ts | 19 ---------- packages/core/src/tracing/vercel-ai/utils.ts | 9 +---- 11 files changed, 55 insertions(+), 81 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/deno/tests/ai.test.ts b/dev-packages/e2e-tests/test-applications/deno/tests/ai.test.ts index 102ef00c6cd1..d0b824bf9b2f 100644 --- a/dev-packages/e2e-tests/test-applications/deno/tests/ai.test.ts +++ b/dev-packages/e2e-tests/test-applications/deno/tests/ai.test.ts @@ -31,7 +31,7 @@ test('should create AI pipeline spans with Vercel AI SDK', async ({ baseURL }) = const aiSpans = spans.filter( (span: any) => span.op === 'gen_ai.invoke_agent' || - span.op === 'gen_ai.generate_text' || + span.op === 'gen_ai.generate_content' || span.op === 'otel.span' || span.description?.includes('ai.generateText'), ); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-error.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-error.test.ts index 32fd12ee0ed5..a8c39ec032ec 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-error.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-error.test.ts @@ -26,7 +26,7 @@ test('should create AI spans with correct attributes and error linking', async ( // because of this, only spans that are manually opted-in at call time will be captured // this may be fixed by https://github.com/vercel/ai/pull/6716 in the future const aiPipelineSpans = spans.filter(span => span.op === 'gen_ai.invoke_agent'); - const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_text'); + const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_content'); const toolCallSpans = spans.filter(span => span.op === 'gen_ai.execute_tool'); expect(aiPipelineSpans.length).toBeGreaterThanOrEqual(1); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-test.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-test.test.ts index a53f8986512a..42c21e4f8c80 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-test.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ai-test.test.ts @@ -22,7 +22,7 @@ test('should create AI spans with correct attributes', async ({ page }) => { // because of this, only spans that are manually opted-in at call time will be captured // this may be fixed by https://github.com/vercel/ai/pull/6716 in the future const aiPipelineSpans = spans.filter(span => span.op === 'gen_ai.invoke_agent'); - const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_text'); + const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_content'); const toolCallSpans = spans.filter(span => span.op === 'gen_ai.execute_tool'); expect(aiPipelineSpans.length).toBeGreaterThanOrEqual(1); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-error.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-error.test.ts index 65f118165702..39e76bab0dde 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-error.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-error.test.ts @@ -26,7 +26,7 @@ test('should create AI spans with correct attributes and error linking', async ( // because of this, only spans that are manually opted-in at call time will be captured // this may be fixed by https://github.com/vercel/ai/pull/6716 in the future const aiPipelineSpans = spans.filter(span => span.op === 'gen_ai.invoke_agent'); - const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_text'); + const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_content'); const toolCallSpans = spans.filter(span => span.op === 'gen_ai.execute_tool'); expect(aiPipelineSpans.length).toBeGreaterThanOrEqual(1); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-test.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-test.test.ts index 5c519cb89a03..dcd129020035 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-test.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16/tests/ai-test.test.ts @@ -22,7 +22,7 @@ test('should create AI spans with correct attributes', async ({ page }) => { // because of this, only spans that are manually opted-in at call time will be captured // this may be fixed by https://github.com/vercel/ai/pull/6716 in the future const aiPipelineSpans = spans.filter(span => span.op === 'gen_ai.invoke_agent'); - const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_text'); + const aiGenerateSpans = spans.filter(span => span.op === 'gen_ai.generate_content'); const toolCallSpans = spans.filter(span => span.op === 'gen_ai.execute_tool'); expect(aiPipelineSpans.length).toBeGreaterThanOrEqual(1); diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/test-generate-object.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/test-generate-object.ts index 3156a19bb806..39e13d5425c2 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test-generate-object.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test-generate-object.ts @@ -37,7 +37,7 @@ describe('Vercel AI integration - generateObject', () => { expect.objectContaining({ data: expect.objectContaining({ 'sentry.origin': 'auto.vercelai.otel', - 'sentry.op': 'gen_ai.generate_object', + 'sentry.op': 'gen_ai.generate_content', 'gen_ai.operation.name': 'generate_content', 'vercel.ai.operationId': 'ai.generateObject.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -52,7 +52,7 @@ describe('Vercel AI integration - generateObject', () => { 'gen_ai.usage.total_tokens': 40, }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_object', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts index 6b0b0a45fcf8..673887737ee6 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -70,7 +70,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -83,7 +83,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -132,7 +132,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -146,7 +146,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -186,7 +186,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -199,7 +199,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -280,7 +280,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -294,7 +294,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', parent_span_id: expect.any(String), @@ -353,7 +353,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -367,7 +367,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', parent_span_id: expect.any(String), @@ -427,7 +427,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -442,7 +442,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', parent_span_id: expect.any(String), @@ -528,7 +528,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -541,7 +541,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -648,7 +648,7 @@ describe('Vercel AI integration', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', 'vercel.ai.model.provider': 'mock-provider', 'vercel.ai.operationId': 'ai.generateText.doGenerate', @@ -661,7 +661,7 @@ describe('Vercel AI integration', () => { 'vercel.ai.streaming': false, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -757,11 +757,11 @@ describe('Vercel AI integration', () => { // The doGenerate span - name stays as 'generateText.doGenerate' since model ID is missing expect.objectContaining({ description: 'generateText.doGenerate', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', data: expect.objectContaining({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', }), @@ -938,7 +938,7 @@ describe('Vercel AI integration', () => { }), }), expect.objectContaining({ - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', data: expect.objectContaining({ 'gen_ai.conversation.id': 'conv-a', }), diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/v5/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/v5/test.ts index a84b80e9abc5..e59a5545d7cf 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/v5/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/v5/test.ts @@ -59,7 +59,7 @@ describe('Vercel AI integration (V5)', () => { expect.objectContaining({ data: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -80,7 +80,7 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -116,7 +116,7 @@ describe('Vercel AI integration (V5)', () => { expect.objectContaining({ data: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -141,7 +141,7 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -189,11 +189,11 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -277,11 +277,11 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -317,7 +317,7 @@ describe('Vercel AI integration (V5)', () => { expect.objectContaining({ data: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -342,7 +342,7 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -401,11 +401,11 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -513,11 +513,11 @@ describe('Vercel AI integration (V5)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }, description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/v6/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/v6/test.ts index 39ee00254373..27128ff3ac70 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/v6/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/v6/test.ts @@ -59,7 +59,7 @@ describe('Vercel AI integration (V6)', () => { expect.objectContaining({ data: expect.objectContaining({ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -81,7 +81,7 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -117,7 +117,7 @@ describe('Vercel AI integration (V6)', () => { expect.objectContaining({ data: expect.objectContaining({ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -142,7 +142,7 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -192,11 +192,11 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -280,11 +280,11 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 20, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -320,7 +320,7 @@ describe('Vercel AI integration (V6)', () => { expect.objectContaining({ data: expect.objectContaining({ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', 'vercel.ai.operationId': 'ai.generateText.doGenerate', 'vercel.ai.model.provider': 'mock-provider', @@ -345,7 +345,7 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 30, }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -404,11 +404,11 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), @@ -518,11 +518,11 @@ describe('Vercel AI integration (V6)', () => { [GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]: 25, [GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]: 40, [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'generate_content', - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_text', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.generate_content', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.vercelai.otel', }), description: 'generate_content mock-model-id', - op: 'gen_ai.generate_text', + op: 'gen_ai.generate_content', origin: 'auto.vercelai.otel', status: 'ok', }), diff --git a/packages/core/src/tracing/ai/gen-ai-attributes.ts b/packages/core/src/tracing/ai/gen-ai-attributes.ts index f5d3a206116e..9c92f2716d32 100644 --- a/packages/core/src/tracing/ai/gen-ai-attributes.ts +++ b/packages/core/src/tracing/ai/gen-ai-attributes.ts @@ -206,25 +206,6 @@ export const GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = 'gen_ai.usage.input_to */ export const GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE = 'gen_ai.invoke_agent'; -/** - * The span operation name for generating text - */ -export const GEN_AI_GENERATE_TEXT_DO_GENERATE_OPERATION_ATTRIBUTE = 'gen_ai.generate_text'; - -/** - * The span operation name for streaming text - */ -export const GEN_AI_STREAM_TEXT_DO_STREAM_OPERATION_ATTRIBUTE = 'gen_ai.stream_text'; - -/** - * The span operation name for generating object - */ -export const GEN_AI_GENERATE_OBJECT_DO_GENERATE_OPERATION_ATTRIBUTE = 'gen_ai.generate_object'; - -/** - * The span operation name for streaming object - */ -export const GEN_AI_STREAM_OBJECT_DO_STREAM_OPERATION_ATTRIBUTE = 'gen_ai.stream_object'; /** * The embeddings input diff --git a/packages/core/src/tracing/vercel-ai/utils.ts b/packages/core/src/tracing/vercel-ai/utils.ts index e72efde75e18..927a3072a25f 100644 --- a/packages/core/src/tracing/vercel-ai/utils.ts +++ b/packages/core/src/tracing/vercel-ai/utils.ts @@ -4,15 +4,11 @@ import { GEN_AI_EMBED_DO_EMBED_OPERATION_ATTRIBUTE, GEN_AI_EMBED_MANY_DO_EMBED_OPERATION_ATTRIBUTE, GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE, - GEN_AI_GENERATE_OBJECT_DO_GENERATE_OPERATION_ATTRIBUTE, - GEN_AI_GENERATE_TEXT_DO_GENERATE_OPERATION_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, GEN_AI_RERANK_DO_RERANK_OPERATION_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, - GEN_AI_STREAM_OBJECT_DO_STREAM_OPERATION_ATTRIBUTE, - GEN_AI_STREAM_TEXT_DO_STREAM_OPERATION_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE, GEN_AI_TOOL_NAME_ATTRIBUTE, @@ -295,13 +291,10 @@ export function getSpanOpFromName(name: string): string | undefined { case 'ai.streamObject': return GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE; case 'ai.generateText.doGenerate': - return GEN_AI_GENERATE_TEXT_DO_GENERATE_OPERATION_ATTRIBUTE; case 'ai.streamText.doStream': - return GEN_AI_STREAM_TEXT_DO_STREAM_OPERATION_ATTRIBUTE; case 'ai.generateObject.doGenerate': - return GEN_AI_GENERATE_OBJECT_DO_GENERATE_OPERATION_ATTRIBUTE; case 'ai.streamObject.doStream': - return GEN_AI_STREAM_OBJECT_DO_STREAM_OPERATION_ATTRIBUTE; + return 'gen_ai.generate_content'; case 'ai.embed.doEmbed': return GEN_AI_EMBED_DO_EMBED_OPERATION_ATTRIBUTE; case 'ai.embedMany.doEmbed': From 60fe9e06f0f0f323d7738e93f2fafcd7a17f1c65 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 1 Apr 2026 15:22:25 +0200 Subject: [PATCH 2/3] lint --- packages/core/src/tracing/ai/gen-ai-attributes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/tracing/ai/gen-ai-attributes.ts b/packages/core/src/tracing/ai/gen-ai-attributes.ts index 9c92f2716d32..aa12142abc40 100644 --- a/packages/core/src/tracing/ai/gen-ai-attributes.ts +++ b/packages/core/src/tracing/ai/gen-ai-attributes.ts @@ -206,7 +206,6 @@ export const GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = 'gen_ai.usage.input_to */ export const GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE = 'gen_ai.invoke_agent'; - /** * The embeddings input * Only recorded when recordInputs is enabled From c60e746effb9b6f755c4743243e88d345c6b009a Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Thu, 2 Apr 2026 10:08:37 +0200 Subject: [PATCH 3/3] lfg --- CHANGELOG.md | 4 ++++ packages/core/src/tracing/ai/gen-ai-attributes.ts | 5 +++++ packages/core/src/tracing/vercel-ai/utils.ts | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a3430dd4db2..123cf20f5074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +- **ref(core): Unify .do\* span ops to `gen_ai.generate_content` ([#20074](https://github.com/getsentry/sentry-javascript/pull/20074))** + + All Vercel AI `do*` spans (`ai.generateText.doGenerate`, `ai.streamText.doStream`, `ai.generateObject.doGenerate`, `ai.streamObject.doStream`) now use a single unified span op `gen_ai.generate_content` instead of separate ops like `gen_ai.generate_text`, `gen_ai.stream_text`, `gen_ai.generate_object`, and `gen_ai.stream_object`. + - **ref(core): Remove provider-specific AI span attributes in favor of `gen_ai` attributes in sentry conventions ([#20011](https://github.com/getsentry/sentry-javascript/pull/20011))** The following provider-specific span attributes have been removed from the OpenAI and Anthropic AI integrations. Use the standardized `gen_ai.*` equivalents instead: diff --git a/packages/core/src/tracing/ai/gen-ai-attributes.ts b/packages/core/src/tracing/ai/gen-ai-attributes.ts index aa12142abc40..ff7a6512b962 100644 --- a/packages/core/src/tracing/ai/gen-ai-attributes.ts +++ b/packages/core/src/tracing/ai/gen-ai-attributes.ts @@ -206,6 +206,11 @@ export const GEN_AI_USAGE_INPUT_TOKENS_CACHED_ATTRIBUTE = 'gen_ai.usage.input_to */ export const GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE = 'gen_ai.invoke_agent'; +/** + * The span operation name for generating content + */ +export const GEN_AI_GENERATE_CONTENT_OPERATION_ATTRIBUTE = 'gen_ai.generate_content'; + /** * The embeddings input * Only recorded when recordInputs is enabled diff --git a/packages/core/src/tracing/vercel-ai/utils.ts b/packages/core/src/tracing/vercel-ai/utils.ts index 927a3072a25f..2a715deab764 100644 --- a/packages/core/src/tracing/vercel-ai/utils.ts +++ b/packages/core/src/tracing/vercel-ai/utils.ts @@ -4,6 +4,7 @@ import { GEN_AI_EMBED_DO_EMBED_OPERATION_ATTRIBUTE, GEN_AI_EMBED_MANY_DO_EMBED_OPERATION_ATTRIBUTE, GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE, + GEN_AI_GENERATE_CONTENT_OPERATION_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, @@ -294,7 +295,7 @@ export function getSpanOpFromName(name: string): string | undefined { case 'ai.streamText.doStream': case 'ai.generateObject.doGenerate': case 'ai.streamObject.doStream': - return 'gen_ai.generate_content'; + return GEN_AI_GENERATE_CONTENT_OPERATION_ATTRIBUTE; case 'ai.embed.doEmbed': return GEN_AI_EMBED_DO_EMBED_OPERATION_ATTRIBUTE; case 'ai.embedMany.doEmbed':