Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 =>
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();
Expand All @@ -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();
},
})
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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();
Expand All @@ -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+"\}\]$/,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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?"}]',
Expand Down Expand Up @@ -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?"}]',
Expand Down Expand Up @@ -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?"}]',
Expand Down Expand Up @@ -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?"}]',
Expand Down
Loading
Loading