From e518d64c604e0aa2a1f90105b3f3f4815233bb1f Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Thu, 23 Jul 2026 12:06:32 +0200 Subject: [PATCH] feat(core)!: Remove `sentry.sdk_meta.gen_ai.input.messages.original_length` attribute This internal SDK-meta span attribute only ever signaled how many gen_ai input messages existed before truncation dropped some. It carries no meaning for consumers on its own and is being removed ahead of the truncation removal. Text truncation itself is unchanged by this commit. Co-Authored-By: Claude Opus 4.8 (1M context) --- MIGRATION.md | 1 + .../suites/tracing/anthropic/test.ts | 10 +--- .../suites/tracing/google-genai/test.ts | 4 -- .../suites/tracing/langchain/test.ts | 20 ++++---- .../suites/tracing/langchain/v1/test.ts | 23 ++++----- .../suites/tracing/langgraph/test.ts | 2 - .../tracing/openai/openai-tool-calls/test.ts | 21 +------- .../suites/tracing/openai/test.ts | 49 ------------------- .../suites/tracing/openai/v6/test.ts | 35 ------------- .../vercelai/span-streaming-v4/test.ts | 6 +-- .../vercelai/span-streaming-v6/test.ts | 6 +-- .../suites/tracing/vercelai/test.ts | 12 +---- packages/core/src/server-exports.ts | 1 - .../core/src/tracing/ai/gen-ai-attributes.ts | 5 -- .../core/src/tracing/anthropic-ai/utils.ts | 6 +-- .../core/src/tracing/google-genai/index.ts | 3 -- packages/core/src/tracing/langchain/utils.ts | 5 -- packages/core/src/tracing/langgraph/index.ts | 7 +-- packages/core/src/tracing/openai/index.ts | 7 --- packages/core/src/tracing/vercel-ai/utils.ts | 6 --- packages/core/src/tracing/workers-ai/utils.ts | 10 +--- .../vercel-ai-request-messages.test.ts | 5 -- .../test/lib/utils/anthropic-utils.test.ts | 3 -- .../src/vercel-ai/vercel-ai-dc-subscriber.ts | 3 -- 24 files changed, 28 insertions(+), 222 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 3ee29f749e7a..129377ba8587 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -447,6 +447,7 @@ Sentry.init({ ### AI integrations - The `enableTruncation` and `streamGenAiSpans` flags were removed. The new default is no truncation and to always stream gen AI spans. +- 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. diff --git a/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts b/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts index c960ac10d8bd..29518d2f3d0c 100644 --- a/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts @@ -18,10 +18,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_REQUEST_STREAM_ATTRIBUTE, -} from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_REQUEST_STREAM_ATTRIBUTE } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { getStringAttributeValue, isOrchestrionEnabled } from '../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; @@ -629,7 +626,6 @@ describe('Anthropic integration', () => { expect(truncatedSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic'); expect(truncatedSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic'); expect(truncatedSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307'); - expect(truncatedSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); const smallMessageSpan = container.items.find( span => span.attributes[GEN_AI_INPUT_MESSAGES]?.value === smallMsgValue, @@ -642,7 +638,6 @@ describe('Anthropic integration', () => { expect(smallMessageSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic'); expect(smallMessageSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic'); expect(smallMessageSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307'); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() @@ -693,7 +688,6 @@ describe('Anthropic integration', () => { expect(firstSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic'); expect(firstSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic'); expect(firstSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307'); - expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(2); }, }) .start() @@ -760,13 +754,11 @@ describe('Anthropic integration', () => { span => span.attributes[GEN_AI_INPUT_MESSAGES]?.value === expectedAllMessages, ); expect(conversationSpan).toBeDefined(); - expect(conversationSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); const longStringSpan = container.items.find( span => span.attributes[GEN_AI_INPUT_MESSAGES]?.value === expectedLongString, ); expect(longStringSpan).toBeDefined(); - expect(longStringSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(1); }, }) .start() diff --git a/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts b/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts index 8097aac2b839..554ee394ef8d 100644 --- a/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts @@ -20,7 +20,6 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; import { getStringAttributeValue, isOrchestrionEnabled } from '../../../utils'; @@ -366,7 +365,6 @@ describe('Google GenAI integration', () => { expect(truncatedSpan!.name).toBe('generate_content gemini-1.5-flash'); expect(truncatedSpan!.status).toBe('ok'); expect(truncatedSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('generate_content'); - expect(truncatedSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); const smallMessageSpan = container.items.find( span => @@ -382,7 +380,6 @@ describe('Google GenAI integration', () => { expect(smallMessageSpan!.name).toBe('generate_content gemini-1.5-flash'); expect(smallMessageSpan!.status).toBe('ok'); expect(smallMessageSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('generate_content'); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() @@ -530,7 +527,6 @@ describe('Google GenAI integration', () => { { role: 'user', parts: [{ text: 'Follow-up question' }] }, ]), ); - expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() diff --git a/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts b/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts index cbbbe95ae7d3..2111bc89cb9d 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts @@ -19,7 +19,6 @@ import { } from '@sentry/conventions/attributes'; import { GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; @@ -212,21 +211,22 @@ describe('LangChain integration', () => { .expect({ span: container => { expect(container.items).toHaveLength(3); + // The string-input span has no system message (and therefore no system instructions), + // while the array-input span does — use that to distinguish the two truncated spans. + const truncatedContent = /^\[\{"role":"user","content":"C+"\}\]$/; const stringInputSpan = container.items.find( - span => span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 1, + span => + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS] === undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match(truncatedContent), ); expect(stringInputSpan).toBeDefined(); expect(stringInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch( - /^\[\{"role":"user","content":"C+"\}\]$/, - ); + expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch(truncatedContent); const arrayInputSpan = container.items.find( span => - span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 2 && - getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match( - /^\[\{"role":"user","content":"C+"\}\]$/, - ), + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS] !== undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match(truncatedContent), ); expect(arrayInputSpan).toBeDefined(); expect(arrayInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); @@ -239,7 +239,6 @@ describe('LangChain integration', () => { ); expect(smallMessageSpan).toBeDefined(); expect(smallMessageSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(2); expect(smallMessageSpan!.attributes[GEN_AI_SYSTEM_INSTRUCTIONS]).toBeDefined(); }, }) @@ -478,7 +477,6 @@ describe('LangChain integration', () => { { role: 'user', content: 'Follow-up question' }, ]), ); - expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() diff --git a/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts b/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts index 579ef83bcbc3..088f8918fa88 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts @@ -16,10 +16,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, -} from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { conditionalTest, getStringAttributeValue, isOrchestrionEnabled } from '../../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../../utils/runner'; import { createEsmTests } from '../../../../utils/runner/createEsmAndCjsTests'; @@ -228,21 +225,22 @@ conditionalTest({ min: 20 })('LangChain integration (v1)', () => { .expect({ span: container => { expect(container.items).toHaveLength(3); + // The string-input span has no system message (and therefore no system instructions), + // while the array-input span does — use that to distinguish the two truncated spans. + const truncatedContent = /^\[\{"role":"user","content":"C+"\}\]$/; const stringInputSpan = container.items.find( - span => span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 1, + span => + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS] === undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match(truncatedContent), ); expect(stringInputSpan).toBeDefined(); expect(stringInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch( - /^\[\{"role":"user","content":"C+"\}\]$/, - ); + expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch(truncatedContent); const arrayInputSpan = container.items.find( span => - span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 2 && - getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match( - /^\[\{"role":"user","content":"C+"\}\]$/, - ), + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS] !== undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES]?.value)?.match(truncatedContent), ); expect(arrayInputSpan).toBeDefined(); expect(arrayInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); @@ -257,7 +255,6 @@ conditionalTest({ min: 20 })('LangChain integration (v1)', () => { ); expect(smallMessageSpan).toBeDefined(); expect(smallMessageSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(2); expect(smallMessageSpan!.attributes[GEN_AI_SYSTEM_INSTRUCTIONS].value).toMatch( /^\[\{"type":"text","content":"A+"\}\]$/, ); diff --git a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts index de47990be403..16d51d5f1962 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts @@ -16,7 +16,6 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { getStringAttributeValue } from '../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; @@ -298,7 +297,6 @@ describe('LangGraph integration', () => { expect(invokeAgentSpan).toBeDefined(); expect(invokeAgentSpan!.name).toBe('invoke_agent weather_assistant'); - expect(invokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() diff --git a/dev-packages/node-integration-tests/suites/tracing/openai/openai-tool-calls/test.ts b/dev-packages/node-integration-tests/suites/tracing/openai/openai-tool-calls/test.ts index f2c2c94aca92..c7c3e5614166 100644 --- a/dev-packages/node-integration-tests/suites/tracing/openai/openai-tool-calls/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/openai/openai-tool-calls/test.ts @@ -16,10 +16,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_REQUEST_STREAM_ATTRIBUTE, -} from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_REQUEST_STREAM_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../../utils/runner'; describe('OpenAI Tool Calls integration', () => { @@ -357,10 +354,6 @@ describe('OpenAI Tool Calls integration', () => { type: 'string', value: 'gpt-4', }); - expect(chatToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(chatToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -432,10 +425,6 @@ describe('OpenAI Tool Calls integration', () => { type: 'boolean', value: true, }); - expect(streamingChatToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingChatToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -504,10 +493,6 @@ describe('OpenAI Tool Calls integration', () => { value: 'gpt-4', }); expect(responsesToolsSpan!.attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE]).toBeUndefined(); - expect(responsesToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(responsesToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -575,10 +560,6 @@ describe('OpenAI Tool Calls integration', () => { type: 'boolean', value: true, }); - expect(streamingResponsesToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingResponsesToolsSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', diff --git a/dev-packages/node-integration-tests/suites/tracing/openai/test.ts b/dev-packages/node-integration-tests/suites/tracing/openai/test.ts index 8f4c8c631bf1..a81723effa40 100644 --- a/dev-packages/node-integration-tests/suites/tracing/openai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/openai/test.ts @@ -19,7 +19,6 @@ import { GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, GEN_AI_REQUEST_STREAM_ATTRIBUTE, @@ -370,10 +369,6 @@ describe('OpenAI integration', () => { type: 'double', value: 0.7, }); - expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the capital of France?"}]', @@ -434,10 +429,6 @@ describe('OpenAI integration', () => { type: 'string', value: 'gpt-3.5-turbo', }); - expect(responsesSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(responsesSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: 'Translate this to French: Hello', @@ -499,10 +490,6 @@ describe('OpenAI integration', () => { type: 'string', value: 'error-model', }); - expect(nonStreamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(nonStreamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -542,10 +529,6 @@ describe('OpenAI integration', () => { type: 'boolean', value: true, }); - expect(streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"Tell me about streaming"}]', @@ -617,10 +600,6 @@ describe('OpenAI integration', () => { type: 'boolean', value: true, }); - expect(streamingResponsesSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingResponsesSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: 'Test streaming responses API', @@ -677,10 +656,6 @@ describe('OpenAI integration', () => { type: 'boolean', value: true, }); - expect(streamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -783,10 +758,6 @@ describe('OpenAI integration', () => { { role: 'user', content: 'Follow-up question' }, ]), }); - expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toMatchObject({ - type: 'integer', - value: 3, - }); const responsesSpan = container.items.find( span => span.attributes[GEN_AI_RESPONSE_ID]?.value === 'resp_mock456', @@ -800,10 +771,6 @@ describe('OpenAI integration', () => { type: 'string', value: 'B'.repeat(50_000), }); - expect(responsesSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toMatchObject({ - type: 'integer', - value: 1, - }); }, }) .start() @@ -1222,10 +1189,6 @@ describe('OpenAI integration', () => { type: 'string', value: 'gpt-3.5-turbo', }); - expect(truncatedMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 2, - }); expect(truncatedMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch( /^\[\{"role":"user","content":"C+"\}\]$/, ); @@ -1267,10 +1230,6 @@ describe('OpenAI integration', () => { { role: 'user', content: 'This is a small message that fits within the limit' }, ]), }); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 2, - }); expect(smallMessageSpan!.attributes[GEN_AI_SYSTEM_INSTRUCTIONS].value).toMatch( /^\[\{"type":"text","content":"A+"\}\]$/, ); @@ -1317,10 +1276,6 @@ describe('OpenAI integration', () => { type: 'string', value: 'gpt-3.5-turbo', }); - expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch(/^A+$/); }, }) @@ -1629,10 +1584,6 @@ describe('OpenAI integration', () => { expect(span!.status).toBe('ok'); expect(span!.attributes[GEN_AI_OPERATION_NAME]).toEqual({ type: 'string', value: 'chat' }); expect(span!.attributes[GEN_AI_REQUEST_MODEL]).toEqual({ type: 'string', value: 'gpt-4o' }); - expect(span!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(span!.attributes[GEN_AI_INPUT_MESSAGES].value).toContain('[Blob substitute]'); } }, diff --git a/dev-packages/node-integration-tests/suites/tracing/openai/v6/test.ts b/dev-packages/node-integration-tests/suites/tracing/openai/v6/test.ts index 855b614108eb..2759b975851e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/openai/v6/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/openai/v6/test.ts @@ -18,7 +18,6 @@ import { GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, GEN_AI_REQUEST_STREAM_ATTRIBUTE, @@ -383,10 +382,6 @@ describe('OpenAI integration (V6)', () => { type: 'double', value: 0.7, }); - expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the capital of France?"}]', @@ -447,10 +442,6 @@ describe('OpenAI integration (V6)', () => { type: 'string', value: 'gpt-3.5-turbo', }); - expect(responsesSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(responsesSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: 'Translate this to French: Hello', @@ -512,10 +503,6 @@ describe('OpenAI integration (V6)', () => { type: 'string', value: 'error-model', }); - expect(nonStreamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(nonStreamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -555,10 +542,6 @@ describe('OpenAI integration (V6)', () => { type: 'boolean', value: true, }); - expect(streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"Tell me about streaming"}]', @@ -630,10 +613,6 @@ describe('OpenAI integration (V6)', () => { type: 'boolean', value: true, }); - expect(streamingResponsesSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingResponsesSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: 'Test streaming responses API', @@ -690,10 +669,6 @@ describe('OpenAI integration (V6)', () => { type: 'boolean', value: true, }); - expect(streamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toEqual({ - type: 'integer', - value: 1, - }); expect(streamingErrorSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -740,10 +715,6 @@ describe('OpenAI integration (V6)', () => { ); expect(chatCompletionSpan).toBeDefined(); expect(chatCompletionSpan!.attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE]).toBeUndefined(); - expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toMatchObject({ - type: 'integer', - value: 1, - }); expect(chatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toMatchObject({ type: 'string', value: expect.any(String), @@ -765,12 +736,6 @@ describe('OpenAI integration (V6)', () => { type: 'boolean', value: true, }); - expect( - streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE], - ).toMatchObject({ - type: 'integer', - value: 1, - }); expect(streamingChatCompletionSpan!.attributes[GEN_AI_INPUT_MESSAGES]).toMatchObject({ type: 'string', value: expect.any(String), diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v4/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v4/test.ts index faebe38f1d30..e28aa7ddbe41 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v4/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v4/test.ts @@ -16,10 +16,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_TOOL_CALL_ID_ATTRIBUTE, -} from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../../utils/runner'; import { getStringAttributeValue, isOrchestrionEnabled } from '../../../../utils'; @@ -143,7 +140,6 @@ describe('Vercel AI integration (streaming v4)', () => { name: 'invoke_agent', status: 'ok', attributes: expect.objectContaining({ - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: attr(1), [GEN_AI_INPUT_MESSAGES]: attr('[{"role":"user","content":"Where is the first span?"}]'), [GEN_AI_OUTPUT_MESSAGES]: attr( '[{"role":"assistant","parts":[{"type":"text","content":"First span here!"}],"finish_reason":"stop"}]', diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v6/test.ts b/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v6/test.ts index 38d4b0873d59..220a0314a77b 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v6/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/span-streaming-v6/test.ts @@ -16,10 +16,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_TOOL_CALL_ID_ATTRIBUTE, -} from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../../utils/runner'; import { isOrchestrionEnabled } from '../../../../utils'; @@ -137,7 +134,6 @@ describe('Vercel AI integration (streaming, v6)', () => { name: 'invoke_agent', status: 'ok', attributes: expect.objectContaining({ - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: attr(1), [GEN_AI_INPUT_MESSAGES]: attr('[{"role":"user","content":"Where is the first span?"}]'), [GEN_AI_OUTPUT_MESSAGES]: attr( '[{"role":"assistant","parts":[{"type":"text","content":"First span here!"}],"finish_reason":"stop"}]', 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 e948e2706ec5..ca28f11c3305 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -19,10 +19,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_TOOL_CALL_ID_ATTRIBUTE, -} from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; import { getStringAttributeValue, isOrchestrionEnabled } from '../../../utils'; @@ -488,9 +485,6 @@ describe('Vercel AI integration (v4)', () => { expect(truncatedInvokeAgentSpan).toBeDefined(); expect(truncatedInvokeAgentSpan!.name).toBe('invoke_agent'); expect(truncatedInvokeAgentSpan!.attributes['sentry.op'].value).toBe('gen_ai.invoke_agent'); - expect(truncatedInvokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe( - 3, - ); expect(truncatedInvokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toMatch( /^\[.*"(?:text|content)":"C+".*\]$/, ); @@ -505,9 +499,6 @@ describe('Vercel AI integration (v4)', () => { expect(smallMessageInvokeAgentSpan).toBeDefined(); expect(smallMessageInvokeAgentSpan!.name).toBe('invoke_agent'); expect(smallMessageInvokeAgentSpan!.attributes['sentry.op'].value).toBe('gen_ai.invoke_agent'); - expect( - smallMessageInvokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value, - ).toBe(3); expect(smallMessageInvokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toContain( 'This is a small message that fits within the limit', ); @@ -638,7 +629,6 @@ describe('Vercel AI integration (v4)', () => { { role: 'user', content: 'Follow-up question' }, ]), ); - expect(invokeAgentSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); const generateContentSpan = container.items.find(span => span.name === 'generate_content mock-model-id'); expect(generateContentSpan).toBeDefined(); diff --git a/packages/core/src/server-exports.ts b/packages/core/src/server-exports.ts index a0fcef8f44ed..14486692830e 100644 --- a/packages/core/src/server-exports.ts +++ b/packages/core/src/server-exports.ts @@ -58,7 +58,6 @@ export type { // avoid shipping the AI tracing code in browser bundles. export { addVercelAiProcessors, getProviderMetadataAttributes } from './tracing/vercel-ai'; export { getTruncatedJsonString, shouldEnableTruncation, resolveAIRecordingOptions } from './tracing/ai/utils'; -export { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from './tracing/ai/gen-ai-attributes'; export { _INTERNAL_getSpanContextForToolCallId, _INTERNAL_cleanupToolCallSpanContext } from './tracing/vercel-ai/utils'; export { toolCallSpanContextMap as _INTERNAL_toolCallSpanContextMap } from './tracing/vercel-ai/constants'; export { diff --git a/packages/core/src/tracing/ai/gen-ai-attributes.ts b/packages/core/src/tracing/ai/gen-ai-attributes.ts index 35050f19a8f4..7f88b2a621ef 100644 --- a/packages/core/src/tracing/ai/gen-ai-attributes.ts +++ b/packages/core/src/tracing/ai/gen-ai-attributes.ts @@ -30,11 +30,6 @@ export const GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE = 'gen_ai.request.dimensions'; */ export const GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE = 'gen_ai.response.stop_reason'; -/** - * Original length of messages array, used to indicate truncations had occured - */ -export const GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE = 'sentry.sdk_meta.gen_ai.input.messages.original_length'; - /** * The number of cache creation input tokens used * diff --git a/packages/core/src/tracing/anthropic-ai/utils.ts b/packages/core/src/tracing/anthropic-ai/utils.ts index c41656c8cf76..98a1a7f9033f 100644 --- a/packages/core/src/tracing/anthropic-ai/utils.ts +++ b/packages/core/src/tracing/anthropic-ai/utils.ts @@ -3,14 +3,12 @@ import { SPAN_STATUS_ERROR } from '../../tracing'; import type { Span } from '../../types/span'; import type { SpanStatusType } from '../../types/spanStatus'; import { GEN_AI_INPUT_MESSAGES, GEN_AI_SYSTEM_INSTRUCTIONS } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../ai/gen-ai-attributes'; import { extractSystemInstructions, getTruncatedJsonString } from '../ai/utils'; import { stringify } from '../../utils/string'; import type { AnthropicAiResponse } from './types'; /** - * Set the messages and messages original length attributes. - * Extracts system instructions before truncation. + * Set the input messages attribute, extracting system instructions before truncation. */ export function setMessagesAttribute(span: Span, messages: unknown, enableTruncation: boolean): void { if (Array.isArray(messages) && messages.length === 0) { @@ -25,10 +23,8 @@ export function setMessagesAttribute(span: Span, messages: unknown, enableTrunca }); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 1; span.setAttributes({ [GEN_AI_INPUT_MESSAGES]: enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } diff --git a/packages/core/src/tracing/google-genai/index.ts b/packages/core/src/tracing/google-genai/index.ts index 0b6c96d0ac81..384c42477dca 100644 --- a/packages/core/src/tracing/google-genai/index.ts +++ b/packages/core/src/tracing/google-genai/index.ts @@ -27,7 +27,6 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../ai/gen-ai-attributes'; import type { InstrumentedMethodEntry } from '../ai/utils'; import { stringify } from '../../utils/string'; import { @@ -190,9 +189,7 @@ export function addPrivateRequestAttributes( span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS, systemInstructions); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; span.setAttributes({ - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, [GEN_AI_INPUT_MESSAGES]: enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), diff --git a/packages/core/src/tracing/langchain/utils.ts b/packages/core/src/tracing/langchain/utils.ts index 7d5b86369df4..4683c02e7cf4 100644 --- a/packages/core/src/tracing/langchain/utils.ts +++ b/packages/core/src/tracing/langchain/utils.ts @@ -24,7 +24,6 @@ import { GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_STREAM_ATTRIBUTE, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS_ATTRIBUTE, @@ -291,7 +290,6 @@ export function extractLLMRequestAttributes( const attrs = baseRequestAttributes(system, modelName, llm, invocationParams, langSmithMetadata); if (recordInputs && Array.isArray(prompts) && prompts.length > 0) { - setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, prompts.length); const messages = prompts.map(p => ({ role: 'user', content: p })); setIfDefined( attrs, @@ -334,9 +332,6 @@ export function extractChatModelRequestAttributes( setIfDefined(attrs, GEN_AI_SYSTEM_INSTRUCTIONS, systemInstructions); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; - setIfDefined(attrs, GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredLength); - setIfDefined( attrs, GEN_AI_INPUT_MESSAGES, diff --git a/packages/core/src/tracing/langgraph/index.ts b/packages/core/src/tracing/langgraph/index.ts index f708e4c40f70..c5cdd753f79c 100644 --- a/packages/core/src/tracing/langgraph/index.ts +++ b/packages/core/src/tracing/langgraph/index.ts @@ -12,10 +12,7 @@ import { GEN_AI_REQUEST_MODEL, GEN_AI_SYSTEM_INSTRUCTIONS, } from '@sentry/conventions/attributes'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, -} from '../ai/gen-ai-attributes'; +import { GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE } from '../ai/gen-ai-attributes'; import { extractSystemInstructions, getTruncatedJsonString, @@ -227,12 +224,10 @@ export function instrumentCompiledGraphInvoke( } const enableTruncation = shouldEnableTruncation(options.enableTruncation); - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; span.setAttributes({ [GEN_AI_INPUT_MESSAGES]: enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } diff --git a/packages/core/src/tracing/openai/index.ts b/packages/core/src/tracing/openai/index.ts index 52d2df8eeafd..f4c9122aa024 100644 --- a/packages/core/src/tracing/openai/index.ts +++ b/packages/core/src/tracing/openai/index.ts @@ -15,7 +15,6 @@ import { GEN_AI_SYSTEM, GEN_AI_SYSTEM_INSTRUCTIONS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../ai/gen-ai-attributes'; import type { InstrumentedMethodEntry } from '../ai/utils'; import { stringify } from '../../utils/string'; import { @@ -131,12 +130,6 @@ export function addRequestAttributes( GEN_AI_INPUT_MESSAGES, enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), ); - - if (Array.isArray(filteredMessages)) { - span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, filteredMessages.length); - } else { - span.setAttribute(GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, 1); - } } /** diff --git a/packages/core/src/tracing/vercel-ai/utils.ts b/packages/core/src/tracing/vercel-ai/utils.ts index d5b59808c722..19f593808e64 100644 --- a/packages/core/src/tracing/vercel-ai/utils.ts +++ b/packages/core/src/tracing/vercel-ai/utils.ts @@ -10,7 +10,6 @@ import { GEN_AI_USAGE_INPUT_TOKENS, GEN_AI_USAGE_OUTPUT_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../ai/gen-ai-attributes'; import { extractSystemInstructions, getTruncatedJsonString } from '../ai/utils'; import { stringify } from '../../utils/string'; import { toolCallSpanContextMap } from './constants'; @@ -242,13 +241,11 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS, systemInstructions); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; const messagesJson = enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages); span.setAttributes({ [AI_PROMPT_ATTRIBUTE]: messagesJson, [GEN_AI_INPUT_MESSAGES]: messagesJson, - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } } else if (typeof attributes[AI_PROMPT_MESSAGES_ATTRIBUTE] === 'string') { @@ -264,8 +261,6 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS, systemInstructions); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; - // `extractSystemInstructions` returns the original array reference unchanged when no // system message is extracted. When truncation is also disabled, re-serializing would // reproduce the SDK's own input string, so we reuse it instead of allocating a second @@ -280,7 +275,6 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttributes({ [AI_PROMPT_MESSAGES_ATTRIBUTE]: messagesJson, [GEN_AI_INPUT_MESSAGES]: messagesJson, - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } // eslint-disable-next-line no-empty diff --git a/packages/core/src/tracing/workers-ai/utils.ts b/packages/core/src/tracing/workers-ai/utils.ts index 2e258b9c122b..8caea5e6c0bc 100644 --- a/packages/core/src/tracing/workers-ai/utils.ts +++ b/packages/core/src/tracing/workers-ai/utils.ts @@ -18,10 +18,7 @@ import { } from '@sentry/conventions/attributes'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; import type { Span, SpanAttributeValue } from '../../types/span'; -import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_REQUEST_STREAM_ATTRIBUTE, -} from '../ai/gen-ai-attributes'; +import { GEN_AI_REQUEST_STREAM_ATTRIBUTE } from '../ai/gen-ai-attributes'; import { extractSystemInstructions, getTruncatedJsonString, setTokenUsageAttributes } from '../ai/utils'; import { stringify } from '../../utils/string'; import { WORKERS_AI_ORIGIN, WORKERS_AI_PROVIDER_NAME } from './constants'; @@ -130,11 +127,6 @@ export function addRequestAttributes( GEN_AI_INPUT_MESSAGES, enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), ); - - span.setAttribute( - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - Array.isArray(filteredMessages) ? filteredMessages.length : 1, - ); } /** diff --git a/packages/core/test/lib/tracing/vercel-ai-request-messages.test.ts b/packages/core/test/lib/tracing/vercel-ai-request-messages.test.ts index a0af09a7d0f9..be9f4e9f8dff 100644 --- a/packages/core/test/lib/tracing/vercel-ai-request-messages.test.ts +++ b/packages/core/test/lib/tracing/vercel-ai-request-messages.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest'; import { getTruncatedJsonString } from '../../../src/tracing/ai/utils'; import { stringify } from '../../../src/utils/string'; import { GEN_AI_INPUT_MESSAGES, GEN_AI_SYSTEM_INSTRUCTIONS } from '@sentry/conventions/attributes'; -import { GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE } from '../../../src/tracing/ai/gen-ai-attributes'; import { requestMessagesFromPrompt } from '../../../src/tracing/vercel-ai/utils'; import { AI_PROMPT_MESSAGES_ATTRIBUTE } from '../../../src/tracing/vercel-ai/vercel-ai-attributes'; import type { Span, SpanAttributes } from '../../../src/types/span'; @@ -37,7 +36,6 @@ describe('requestMessagesFromPrompt (ai.prompt.messages string branch)', () => { expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).toBe(original); expect(recorded[GEN_AI_INPUT_MESSAGES]).toBe(original); - expect(recorded[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toBe(1); expect(recorded[GEN_AI_SYSTEM_INSTRUCTIONS]).toBeUndefined(); }); @@ -56,7 +54,6 @@ describe('requestMessagesFromPrompt (ai.prompt.messages string branch)', () => { // System message removed; output is the SDK's own serialization of just the remainder. expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).toBe(stringify([{ role: 'user', content: 'hello' }])); expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).not.toBe(original); - expect(recorded[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toBe(1); }); it('keeps the truncation path untouched when truncation is on', () => { @@ -75,8 +72,6 @@ describe('requestMessagesFromPrompt (ai.prompt.messages string branch)', () => { // input), proving the fast-path reuse did NOT short-circuit the truncation branch. expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).toBe(getTruncatedJsonString(messages)); expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).not.toBe(original); - // Original (pre-truncation) message count is still reported. - expect(recorded[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toBe(2); }); it('does not throw and sets no attributes for malformed JSON', () => { diff --git a/packages/core/test/lib/utils/anthropic-utils.test.ts b/packages/core/test/lib/utils/anthropic-utils.test.ts index 6880310c2064..59b6dd63fad2 100644 --- a/packages/core/test/lib/utils/anthropic-utils.test.ts +++ b/packages/core/test/lib/utils/anthropic-utils.test.ts @@ -101,7 +101,6 @@ describe('anthropic-ai-utils', () => { setMessagesAttribute(span, [{ role: 'user', content }], true); const result = [{ role: 'user', content: 'A'.repeat(19970) }]; expect(mock.attributes).toStrictEqual({ - 'sentry.sdk_meta.gen_ai.input.messages.original_length': 1, 'gen_ai.input.messages': JSON.stringify(result), }); }); @@ -109,7 +108,6 @@ describe('anthropic-ai-utils', () => { it('sets length to 1 for non-array input', () => { setMessagesAttribute(span, { content: 'hello, world' }, true); expect(mock.attributes).toStrictEqual({ - 'sentry.sdk_meta.gen_ai.input.messages.original_length': 1, 'gen_ai.input.messages': '{"content":"hello, world"}', }); }); @@ -117,7 +115,6 @@ describe('anthropic-ai-utils', () => { it('ignores empty array', () => { setMessagesAttribute(span, [], true); expect(mock.attributes).toStrictEqual({ - 'sentry.sdk_meta.gen_ai.input.messages.original_length': 1, 'gen_ai.input.messages': '{"content":"hello, world"}', }); }); diff --git a/packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts b/packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts index 27f286a2e202..79ded795c817 100644 --- a/packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts +++ b/packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts @@ -32,7 +32,6 @@ import { _INTERNAL_skipAiProviderWrapping, captureException, GEN_AI_CONVERSATION_ID_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, getClient, getProviderMetadataAttributes, getTruncatedJsonString, @@ -745,8 +744,6 @@ function buildInputMessageAttributes( const messages = event.messages ?? event.prompt; if (messages !== undefined) { attributes[GEN_AI_INPUT_MESSAGES] = enableTruncation ? getTruncatedJsonString(messages) : stringify(messages); - // The original (pre-truncation) message count, so the product can show how many were dropped. - attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE] = Array.isArray(messages) ? messages.length : 1; } return attributes;