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;