diff --git a/MIGRATION.md b/MIGRATION.md index fd633ac0d9ea..d37a78304379 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -393,6 +393,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 5546aa8abd66..43dd96dfce5c 100644 --- a/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/anthropic/test.ts @@ -1,7 +1,6 @@ import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, @@ -634,7 +633,6 @@ describe('Anthropic integration', () => { expect(truncatedSpan!.attributes['sentry.origin'].value).toBe('auto.ai.anthropic'); expect(truncatedSpan!.attributes[GEN_AI_SYSTEM_ATTRIBUTE].value).toBe('anthropic'); expect(truncatedSpan!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE].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_ATTRIBUTE]?.value === smallMsgValue, @@ -649,7 +647,6 @@ describe('Anthropic integration', () => { expect(smallMessageSpan!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE].value).toBe( 'claude-3-haiku-20240307', ); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() @@ -700,7 +697,6 @@ describe('Anthropic integration', () => { expect(firstSpan!.attributes['sentry.origin'].value).toBe('auto.ai.anthropic'); expect(firstSpan!.attributes[GEN_AI_SYSTEM_ATTRIBUTE].value).toBe('anthropic'); expect(firstSpan!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE].value).toBe('claude-3-haiku-20240307'); - expect(firstSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(2); }, }) .start() @@ -767,13 +763,11 @@ describe('Anthropic integration', () => { span => span.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.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_ATTRIBUTE]?.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 3332ff1d862c..81b983ea4231 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 @@ -3,7 +3,6 @@ import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE, @@ -368,7 +367,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_ATTRIBUTE].value).toBe('generate_content'); - expect(truncatedSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); const smallMessageSpan = container.items.find( span => @@ -384,7 +382,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_ATTRIBUTE].value).toBe('generate_content'); - expect(smallMessageSpan!.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE].value).toBe(3); }, }) .start() @@ -532,7 +529,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 ed342ce9d1a2..d2b94f200c62 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts @@ -3,7 +3,6 @@ import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, @@ -210,20 +209,25 @@ 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_ATTRIBUTE] === undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value)?.match( + truncatedContent, + ), ); expect(stringInputSpan).toBeDefined(); expect(stringInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE].value).toMatch( - /^\[\{"role":"user","content":"C+"\}\]$/, - ); + expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE].value).toMatch(truncatedContent); const arrayInputSpan = container.items.find( span => - span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 2 && + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] !== undefined && getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value)?.match( - /^\[\{"role":"user","content":"C+"\}\]$/, + truncatedContent, ), ); expect(arrayInputSpan).toBeDefined(); @@ -237,7 +241,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_ATTRIBUTE]).toBeDefined(); }, }) @@ -476,7 +479,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 b555e48229e4..9d5c5e7ba1a3 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 @@ -1,7 +1,6 @@ import { afterAll, expect } from 'vitest'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE, @@ -226,20 +225,25 @@ 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_ATTRIBUTE] === undefined && + getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value)?.match( + truncatedContent, + ), ); expect(stringInputSpan).toBeDefined(); expect(stringInputSpan!.name).toBe('chat claude-3-5-sonnet-20241022'); - expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE].value).toMatch( - /^\[\{"role":"user","content":"C+"\}\]$/, - ); + expect(stringInputSpan!.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE].value).toMatch(truncatedContent); const arrayInputSpan = container.items.find( span => - span.attributes[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]?.value === 2 && + span.attributes[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE] !== undefined && getStringAttributeValue(span.attributes[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]?.value)?.match( - /^\[\{"role":"user","content":"C+"\}\]$/, + truncatedContent, ), ); expect(arrayInputSpan).toBeDefined(); @@ -255,7 +259,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_ATTRIBUTE].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 f293ba29218e..ed104fa52933 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langgraph/test.ts @@ -4,7 +4,6 @@ import { GEN_AI_AGENT_NAME_ATTRIBUTE, GEN_AI_CONVERSATION_ID_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_PIPELINE_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, @@ -305,7 +304,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 0895e6dffd19..7caf0d745237 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 @@ -2,7 +2,6 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from ' import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE, @@ -355,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -430,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -502,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -573,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_ATTRIBUTE]).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 3f102d360e40..bbb93952136a 100644 --- a/dev-packages/node-integration-tests/suites/tracing/openai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/openai/test.ts @@ -4,7 +4,6 @@ import { GEN_AI_CONVERSATION_ID_ATTRIBUTE, GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, @@ -368,10 +367,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the capital of France?"}]', @@ -432,10 +427,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_ATTRIBUTE]).toEqual({ type: 'string', value: 'Translate this to French: Hello', @@ -497,10 +488,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -540,10 +527,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"Tell me about streaming"}]', @@ -615,10 +598,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_ATTRIBUTE]).toEqual({ type: 'string', value: 'Test streaming responses API', @@ -675,10 +654,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -781,10 +756,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_ATTRIBUTE]?.value === 'resp_mock456', @@ -798,10 +769,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() @@ -1220,10 +1187,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_ATTRIBUTE].value).toMatch( /^\[\{"role":"user","content":"C+"\}\]$/, ); @@ -1265,10 +1228,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_ATTRIBUTE].value).toMatch( /^\[\{"type":"text","content":"A+"\}\]$/, ); @@ -1315,10 +1274,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_ATTRIBUTE].value).toMatch(/^A+$/); }, }) @@ -1627,10 +1582,6 @@ describe('OpenAI integration', () => { expect(span!.status).toBe('ok'); expect(span!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ type: 'string', value: 'chat' }); expect(span!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE]).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_ATTRIBUTE].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 0530d1575845..0c44b5b02be7 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 @@ -3,7 +3,6 @@ import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, @@ -381,10 +380,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"What is the capital of France?"}]', @@ -445,10 +440,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_ATTRIBUTE]).toEqual({ type: 'string', value: 'Translate this to French: Hello', @@ -510,10 +501,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -553,10 +540,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"Tell me about streaming"}]', @@ -628,10 +611,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_ATTRIBUTE]).toEqual({ type: 'string', value: 'Test streaming responses API', @@ -688,10 +667,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_ATTRIBUTE]).toEqual({ type: 'string', value: '[{"role":"user","content":"This will fail"}]', @@ -738,10 +713,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_ATTRIBUTE]).toMatchObject({ type: 'string', value: expect.any(String), @@ -763,12 +734,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_ATTRIBUTE]).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 f28559c4b9e9..f522f7766822 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 @@ -2,7 +2,6 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from ' import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, @@ -141,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_ATTRIBUTE]: attr('[{"role":"user","content":"Where is the first span?"}]'), [GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE]: 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 2e8ccc0c1602..68e6660524e4 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 @@ -2,7 +2,6 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from ' import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, @@ -135,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_ATTRIBUTE]: attr('[{"role":"user","content":"Where is the first span?"}]'), [GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE]: 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 b759495545cc..1c79760227c9 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -3,7 +3,6 @@ import { afterAll, describe, expect } from 'vitest'; import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, @@ -501,9 +500,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_ATTRIBUTE].value).toMatch( /^\[.*"(?:text|content)":"C+".*\]$/, ); @@ -518,9 +514,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_ATTRIBUTE].value).toContain( 'This is a small message that fits within the limit', ); @@ -655,7 +648,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 32b54720a83e..8288320bbed9 100644 --- a/packages/core/src/server-exports.ts +++ b/packages/core/src/server-exports.ts @@ -58,11 +58,7 @@ 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, - GEN_AI_REQUEST_MODEL_ATTRIBUTE, - GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, -} from './tracing/ai/gen-ai-attributes'; +export { GEN_AI_REQUEST_MODEL_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_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 16cdfa17b4b3..526715ac9c2f 100644 --- a/packages/core/src/tracing/ai/gen-ai-attributes.ts +++ b/packages/core/src/tracing/ai/gen-ai-attributes.ts @@ -115,11 +115,6 @@ export const GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE = 'gen_ai.usage.total_tokens'; */ export const GEN_AI_OPERATION_NAME_ATTRIBUTE = 'gen_ai.operation.name'; -/** - * 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 prompt messages * Only recorded when recordInputs is enabled diff --git a/packages/core/src/tracing/anthropic-ai/utils.ts b/packages/core/src/tracing/anthropic-ai/utils.ts index 5fbde951343f..5989247c111c 100644 --- a/packages/core/src/tracing/anthropic-ai/utils.ts +++ b/packages/core/src/tracing/anthropic-ai/utils.ts @@ -2,18 +2,13 @@ import { captureException } from '../../exports'; import { SPAN_STATUS_ERROR } from '../../tracing'; import type { Span } from '../../types/span'; import type { SpanStatusType } from '../../types/spanStatus'; -import { - GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, - GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, -} from '../ai/gen-ai-attributes'; +import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_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) { @@ -28,12 +23,10 @@ export function setMessagesAttribute(span: Span, messages: unknown, enableTrunca }); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 1; span.setAttributes({ [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: 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 68e4d414586a..1909a0903764 100644 --- a/packages/core/src/tracing/google-genai/index.ts +++ b/packages/core/src/tracing/google-genai/index.ts @@ -8,7 +8,6 @@ import { handleCallbackErrors } from '../../utils/handleCallbackErrors'; import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE, @@ -192,9 +191,7 @@ export function addPrivateRequestAttributes( span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions); } - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; span.setAttributes({ - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: enableTruncation ? getTruncatedJsonString(filteredMessages) : stringify(filteredMessages), diff --git a/packages/core/src/tracing/langchain/utils.ts b/packages/core/src/tracing/langchain/utils.ts index 0f95464788da..db5fffa0e000 100644 --- a/packages/core/src/tracing/langchain/utils.ts +++ b/packages/core/src/tracing/langchain/utils.ts @@ -4,7 +4,6 @@ import { stringify } from '../../utils/string'; import { GEN_AI_AGENT_NAME_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_FREQUENCY_PENALTY_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, @@ -288,7 +287,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, @@ -331,9 +329,6 @@ export function extractChatModelRequestAttributes( setIfDefined(attrs, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, 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_ATTRIBUTE, diff --git a/packages/core/src/tracing/langgraph/index.ts b/packages/core/src/tracing/langgraph/index.ts index bcbd120b38e1..ea6653e28bd1 100644 --- a/packages/core/src/tracing/langgraph/index.ts +++ b/packages/core/src/tracing/langgraph/index.ts @@ -5,7 +5,6 @@ import { GEN_AI_AGENT_NAME_ATTRIBUTE, GEN_AI_CONVERSATION_ID_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_PIPELINE_NAME_ATTRIBUTE, @@ -224,12 +223,10 @@ export function instrumentCompiledGraphInvoke( } const enableTruncation = shouldEnableTruncation(options.enableTruncation); - const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0; span.setAttributes({ [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: 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 821e9c68e0ff..c15b10856f8e 100644 --- a/packages/core/src/tracing/openai/index.ts +++ b/packages/core/src/tracing/openai/index.ts @@ -8,7 +8,6 @@ import { debug } from '../../utils/debug-logger'; import { GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_REQUEST_MODEL_ATTRIBUTE, @@ -130,12 +129,6 @@ export function addRequestAttributes( GEN_AI_INPUT_MESSAGES_ATTRIBUTE, 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 b57a43666202..d5c01f6302a8 100644 --- a/packages/core/src/tracing/vercel-ai/utils.ts +++ b/packages/core/src/tracing/vercel-ai/utils.ts @@ -2,7 +2,6 @@ import type { TraceContext } from '../../types/context'; import type { Span, SpanAttributes, SpanJSON } from '../../types/span'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE, @@ -241,13 +240,11 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, 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_ATTRIBUTE]: messagesJson, - [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength, }); } } else if (typeof attributes[AI_PROMPT_MESSAGES_ATTRIBUTE] === 'string') { @@ -263,8 +260,6 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, 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 @@ -279,7 +274,6 @@ export function requestMessagesFromPrompt(span: Span, attributes: SpanAttributes span.setAttributes({ [AI_PROMPT_MESSAGES_ATTRIBUTE]: messagesJson, [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: 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 23eac0eaa6fc..42ad16328982 100644 --- a/packages/core/src/tracing/workers-ai/utils.ts +++ b/packages/core/src/tracing/workers-ai/utils.ts @@ -15,7 +15,6 @@ import { import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; import type { Span, SpanAttributeValue } from '../../types/span'; import { - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_OUTPUT_MESSAGES_ATTRIBUTE, GEN_AI_REQUEST_STREAM_ATTRIBUTE, GEN_AI_RESPONSE_TEXT_ATTRIBUTE, @@ -129,11 +128,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 b2230c917344..25e9ed53f1eb 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 @@ -3,7 +3,6 @@ import { getTruncatedJsonString } from '../../../src/tracing/ai/utils'; import { stringify } from '../../../src/utils/string'; import { GEN_AI_INPUT_MESSAGES_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, } from '../../../src/tracing/ai/gen-ai-attributes'; import { requestMessagesFromPrompt } from '../../../src/tracing/vercel-ai/utils'; @@ -40,7 +39,6 @@ describe('requestMessagesFromPrompt (ai.prompt.messages string branch)', () => { expect(recorded[AI_PROMPT_MESSAGES_ATTRIBUTE]).toBe(original); expect(recorded[GEN_AI_INPUT_MESSAGES_ATTRIBUTE]).toBe(original); - expect(recorded[GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]).toBe(1); expect(recorded[GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE]).toBeUndefined(); }); @@ -59,7 +57,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', () => { @@ -79,7 +76,6 @@ describe('requestMessagesFromPrompt (ai.prompt.messages string 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 0b9e7f39e101..bafc3b51bbd9 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 @@ -30,7 +30,6 @@ import type { Span, SpanAttributes } from '@sentry/core'; import { captureException, GEN_AI_CONVERSATION_ID_ATTRIBUTE, - GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE, GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, getClient, getProviderMetadataAttributes, @@ -740,8 +739,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;