diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/openai/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/openai/test.ts index 1dc4ca077665..c1aee24136a4 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/openai/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/openai/test.ts @@ -19,6 +19,7 @@ it('traces a basic chat completion request', async () => { data: expect.objectContaining({ 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-3.5-turbo', 'gen_ai.request.temperature': 0.7, @@ -31,7 +32,7 @@ it('traces a basic chat completion request', async () => { }), description: 'chat gpt-3.5-turbo', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', }), ]), ); 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 c5fd4fc97a72..98dab6e77b86 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 @@ -65,7 +65,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.available_tools': WEATHER_TOOL_DEFINITION, @@ -83,7 +83,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'chat gpt-4', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Second span - chat completion with tools and streaming @@ -91,7 +91,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -111,7 +111,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'chat gpt-4 stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Third span - responses API with tools (non-streaming) @@ -119,7 +119,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.available_tools': WEATHER_TOOL_DEFINITION, @@ -137,7 +137,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'responses gpt-4', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Fourth span - responses API with tools and streaming @@ -145,7 +145,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -165,7 +165,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'responses gpt-4 stream-response', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), ]), @@ -179,7 +179,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.messages': '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -200,7 +200,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'chat gpt-4', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Second span - chat completion with tools and streaming with PII @@ -208,7 +208,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -230,7 +230,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'chat gpt-4 stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Third span - responses API with tools (non-streaming) with PII @@ -238,7 +238,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.messages': '[{"role":"user","content":"What is the weather like in Paris today?"}]', @@ -258,7 +258,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'responses gpt-4', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Fourth span - responses API with tools and streaming with PII @@ -266,7 +266,7 @@ describe('OpenAI Tool Calls integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -288,7 +288,7 @@ describe('OpenAI Tool Calls integration', () => { }, description: 'responses gpt-4 stream-response', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), ]), 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 e72d0144d36c..52327887e041 100644 --- a/dev-packages/node-integration-tests/suites/tracing/openai/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/openai/test.ts @@ -14,7 +14,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-3.5-turbo', 'gen_ai.request.temperature': 0.7, @@ -32,7 +32,7 @@ describe('OpenAI integration', () => { }, description: 'chat gpt-3.5-turbo', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Second span - responses API @@ -40,7 +40,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-3.5-turbo', 'gen_ai.response.model': 'gpt-3.5-turbo', @@ -57,7 +57,7 @@ describe('OpenAI integration', () => { }, description: 'responses gpt-3.5-turbo', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Third span - error handling @@ -65,13 +65,13 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'error-model', }, description: 'chat error-model', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'unknown_error', }), // Fourth span - chat completions streaming @@ -79,7 +79,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.temperature': 0.8, @@ -99,7 +99,7 @@ describe('OpenAI integration', () => { }, description: 'chat gpt-4 stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Fifth span - responses API streaming @@ -107,7 +107,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -126,7 +126,7 @@ describe('OpenAI integration', () => { }, description: 'responses gpt-4 stream-response', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Sixth span - error handling in streaming context @@ -137,11 +137,11 @@ describe('OpenAI integration', () => { 'gen_ai.request.stream': true, 'gen_ai.system': 'openai', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', }, description: 'chat error-model stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'internal_error', }), ]), @@ -155,7 +155,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-3.5-turbo', 'gen_ai.request.temperature': 0.7, @@ -176,7 +176,7 @@ describe('OpenAI integration', () => { }, description: 'chat gpt-3.5-turbo', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Second span - responses API with PII @@ -184,7 +184,7 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-3.5-turbo', 'gen_ai.request.messages': '"Translate this to French: Hello"', @@ -203,7 +203,7 @@ describe('OpenAI integration', () => { }, description: 'responses gpt-3.5-turbo', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Third span - error handling with PII @@ -211,14 +211,14 @@ describe('OpenAI integration', () => { data: { 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'error-model', 'gen_ai.request.messages': '[{"role":"user","content":"This will fail"}]', }, description: 'chat error-model', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'unknown_error', }), // Fourth span - chat completions streaming with PII @@ -226,7 +226,7 @@ describe('OpenAI integration', () => { data: expect.objectContaining({ 'gen_ai.operation.name': 'chat', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.temperature': 0.8, @@ -249,7 +249,7 @@ describe('OpenAI integration', () => { }), description: 'chat gpt-4 stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Fifth span - responses API streaming with PII @@ -257,7 +257,7 @@ describe('OpenAI integration', () => { data: expect.objectContaining({ 'gen_ai.operation.name': 'responses', 'sentry.op': 'gen_ai.responses', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', 'gen_ai.system': 'openai', 'gen_ai.request.model': 'gpt-4', 'gen_ai.request.stream': true, @@ -278,7 +278,7 @@ describe('OpenAI integration', () => { }), description: 'responses gpt-4 stream-response', op: 'gen_ai.responses', - origin: 'manual', + origin: 'auto.ai.openai', status: 'ok', }), // Sixth span - error handling in streaming context with PII @@ -290,11 +290,11 @@ describe('OpenAI integration', () => { 'gen_ai.request.messages': '[{"role":"user","content":"This will fail"}]', 'gen_ai.system': 'openai', 'sentry.op': 'gen_ai.chat', - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.ai.openai', }, description: 'chat error-model stream-response', op: 'gen_ai.chat', - origin: 'manual', + origin: 'auto.ai.openai', status: 'internal_error', }), ]), diff --git a/packages/core/src/utils/openai/index.ts b/packages/core/src/utils/openai/index.ts index 3fb4f0d16fce..261e0296e479 100644 --- a/packages/core/src/utils/openai/index.ts +++ b/packages/core/src/utils/openai/index.ts @@ -1,5 +1,6 @@ import { getCurrentScope } from '../../currentScopes'; import { captureException } from '../../exports'; +import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; import { SPAN_STATUS_ERROR } from '../../tracing'; import { startSpan, startSpanManual } from '../../tracing/trace'; import type { Span, SpanAttributeValue } from '../../types-hoist/span'; @@ -49,6 +50,7 @@ function extractRequestAttributes(args: unknown[], methodPath: string): Record = { [GEN_AI_SYSTEM_ATTRIBUTE]: 'openai', [GEN_AI_OPERATION_NAME_ATTRIBUTE]: getOperationName(methodPath), + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.openai', }; // Chat completion API accepts web_search_options and tools as parameters @@ -256,6 +258,10 @@ function instrumentMethod( captureException(error, { mechanism: { handled: false, + type: 'auto.ai.openai.stream', + data: { + function: methodPath, + }, }, }); span.end(); @@ -281,7 +287,15 @@ function instrumentMethod( addResponseAttributes(span, result, finalOptions.recordOutputs); return result; } catch (error) { - captureException(error); + captureException(error, { + mechanism: { + handled: false, + type: 'auto.ai.openai', + data: { + function: methodPath, + }, + }, + }); throw error; } }, diff --git a/packages/core/src/utils/openai/streaming.ts b/packages/core/src/utils/openai/streaming.ts index 2791e715920e..e17c5a2054e0 100644 --- a/packages/core/src/utils/openai/streaming.ts +++ b/packages/core/src/utils/openai/streaming.ts @@ -152,6 +152,7 @@ function processResponsesApiEvent( captureException(streamEvent, { mechanism: { handled: false, + type: 'auto.ai.openai.stream-response', }, }); return;