diff --git a/dev-packages/node-integration-tests/suites/tracing/vercelai/scenario-conversation-id.mjs b/dev-packages/node-integration-tests/suites/tracing/vercelai/scenario-conversation-id.mjs new file mode 100644 index 000000000000..4933d3bfb9c2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/scenario-conversation-id.mjs @@ -0,0 +1,27 @@ +import * as Sentry from '@sentry/node'; +import { generateText } from 'ai'; +import { MockLanguageModelV1 } from 'ai/test'; + +Sentry.setConversationId('conv-a'); + +async function run() { + await Sentry.startSpan({ op: 'function', name: 'main' }, async () => { + await generateText({ + experimental_telemetry: { isEnabled: true }, + model: new MockLanguageModelV1({ + doGenerate: async () => ({ + rawCall: { rawPrompt: null, rawSettings: {} }, + finishReason: 'stop', + usage: { promptTokens: 10, completionTokens: 20 }, + text: 'Hello!', + providerMetadata: { + openai: { responseId: 'resp_should_not_overwrite' }, + }, + }), + }), + prompt: 'Say hello', + }); + }); +} + +run(); 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 7907544a6d11..6b0b0a45fcf8 100644 --- a/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/vercelai/test.ts @@ -923,4 +923,31 @@ describe('Vercel AI integration', () => { await createRunner().expect({ transaction: expectedTransaction }).start().completed(); }); }); + + createEsmAndCjsTests(__dirname, 'scenario-conversation-id.mjs', 'instrument.mjs', (createRunner, test) => { + test('does not overwrite conversation id set via Sentry.setConversationId with responseId from provider metadata', async () => { + await createRunner() + .expect({ + transaction: { + transaction: 'main', + spans: expect.arrayContaining([ + expect.objectContaining({ + op: 'gen_ai.invoke_agent', + data: expect.objectContaining({ + 'gen_ai.conversation.id': 'conv-a', + }), + }), + expect.objectContaining({ + op: 'gen_ai.generate_text', + data: expect.objectContaining({ + 'gen_ai.conversation.id': 'conv-a', + }), + }), + ]), + }, + }) + .start() + .completed(); + }); + }); }); diff --git a/packages/core/src/tracing/vercel-ai/index.ts b/packages/core/src/tracing/vercel-ai/index.ts index 17e26b7b6bac..1d8a27e8e3aa 100644 --- a/packages/core/src/tracing/vercel-ai/index.ts +++ b/packages/core/src/tracing/vercel-ai/index.ts @@ -470,7 +470,9 @@ function addProviderMetadataToAttributes(attributes: SpanAttributes): void { 'gen_ai.usage.output_tokens.prediction_rejected', openaiMetadata.rejectedPredictionTokens, ); - setAttributeIfDefined(attributes, 'gen_ai.conversation.id', openaiMetadata.responseId); + if (!attributes['gen_ai.conversation.id']) { + setAttributeIfDefined(attributes, 'gen_ai.conversation.id', openaiMetadata.responseId); + } } if (providerMetadataObject.anthropic) {