From db55a48fc7ee52dc111f4f794926994faf97a2aa Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 2 Oct 2025 13:19:08 +0300 Subject: [PATCH 1/8] feat(browser): Expose AI instrumentation methods --- .../tracing/ai-providers/anthropic/mocks.js | 55 ++++++++ .../tracing/ai-providers/anthropic/subject.js | 25 ++++ .../tracing/ai-providers/anthropic/test.ts | 39 ++++++ .../ai-providers/google-genai/mocks.js | 118 ++++++++++++++++++ .../ai-providers/google-genai/subject.js | 38 ++++++ .../tracing/ai-providers/google-genai/test.ts | 34 +++++ .../tracing/ai-providers/openai/mocks.js | 47 +++++++ .../tracing/ai-providers/openai/subject.js | 28 +++++ .../tracing/ai-providers/openai/test.ts | 40 ++++++ packages/browser/src/index.ts | 3 + 10 files changed, 427 insertions(+) create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js new file mode 100644 index 000000000000..ba2a01c8ed40 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js @@ -0,0 +1,55 @@ +// Mock Anthropic client for browser testing +export class MockAnthropic { + constructor(config) { + this.apiKey = config.apiKey; + + // Main focus: messages.create functionality + this.messages = { + create: async (...args) => { + const params = args[0]; + // Simulate processing time + await new Promise(resolve => setTimeout(resolve, 10)); + + if (params.model === 'error-model') { + const error = new Error('Model not found'); + error.status = 404; + error.headers = { 'x-request-id': 'mock-request-123' }; + throw error; + } + + return { + id: 'msg_mock123', + type: 'message', + role: 'assistant', + model: params.model, + content: [ + { + type: 'text', + text: 'Hello from Anthropic mock!', + }, + ], + stop_reason: 'end_turn', + stop_sequence: null, + usage: { + input_tokens: 10, + output_tokens: 15, + cache_creation_input_tokens: 0, + cache_read_input_tokens: 0, + }, + }; + }, + countTokens: async (..._args) => ({ id: 'mock', type: 'model', model: 'mock', input_tokens: 0 }), + }; + + // Minimal implementations for required interface compliance + this.models = { + list: async (..._args) => ({ id: 'mock', type: 'model', model: 'mock' }), + get: async (..._args) => ({ id: 'mock', type: 'model', model: 'mock' }), + }; + + this.completions = { + create: async (..._args) => ({ id: 'mock', type: 'completion', model: 'mock' }), + }; + } +} + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js new file mode 100644 index 000000000000..7e38cfb749db --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -0,0 +1,25 @@ +import * as Sentry from '@sentry/browser'; +import { MockAnthropic } from './mocks.js'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); + +const mockClient = new MockAnthropic({ + apiKey: 'mock-api-key', +}); + +const client = Sentry.instrumentAnthropicAiClient(mockClient); + +// Test that manual instrumentation doesn't crash the browser +// The instrumentation automatically creates spans +client.messages.create({ + model: 'claude-3-haiku-20240307', + messages: [{ role: 'user', content: 'What is the capital of France?' }], + temperature: 0.7, + max_tokens: 100, +}); + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts new file mode 100644 index 000000000000..ec13310f792f --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts @@ -0,0 +1,39 @@ +import { expect } from '@playwright/test'; +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; + +// These tests are not exhaustive because the instrumentation is +// already tested in the node integration tests and we merely +// want to test that the instrumentation does not crash in the browser +// and that gen_ai transactions are sent. + +sentryTest('manual Anthropic instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const transactionPromise = waitForTransactionRequest(page, event => { + return !!event.transaction?.includes('claude-3-haiku-20240307'); + }); + + const url = await getLocalTestUrl({ testDir: __dirname }); + await page.goto(url); + + const req = await transactionPromise; + const eventData = envelopeRequestParser(req); + + // Verify it's a gen_ai transaction + expect(eventData.transaction).toBe('messages claude-3-haiku-20240307'); + expect(eventData.contexts?.trace?.op).toBe('gen_ai.messages'); + expect(eventData.contexts?.trace?.origin).toBe('auto.ai.anthropic'); + expect(eventData.contexts?.trace?.data).toMatchObject({ + 'gen_ai.operation.name': 'messages', + 'gen_ai.system': 'anthropic', + 'gen_ai.request.model': 'claude-3-haiku-20240307', + 'gen_ai.request.temperature': 0.7, + 'gen_ai.response.model': 'claude-3-haiku-20240307', + 'gen_ai.response.id': 'msg_mock123', + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 15, + }); +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js new file mode 100644 index 000000000000..f125fa9f16c0 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js @@ -0,0 +1,118 @@ +// Mock Google GenAI client for browser testing +export class MockGoogleGenAI { + constructor(config) { + this.apiKey = config.apiKey; + + // models.generateContent functionality + this.models = { + generateContent: async (...args) => { + const params = args[0]; + // Simulate processing time + await new Promise(resolve => setTimeout(resolve, 10)); + + if (params.model === 'error-model') { + const error = new Error('Model not found'); + error.status = 404; + error.headers = { 'x-request-id': 'mock-request-123' }; + throw error; + } + + return { + candidates: [ + { + content: { + parts: [ + { + text: 'Hello from Google GenAI mock!', + }, + ], + role: 'model', + }, + finishReason: 'stop', + index: 0, + }, + ], + usageMetadata: { + promptTokenCount: 8, + candidatesTokenCount: 12, + totalTokenCount: 20, + }, + }; + }, + generateContentStream: async () => { + // Return a promise that resolves to an async generator + return (async function* () { + yield { + candidates: [ + { + content: { + parts: [{ text: 'Streaming response' }], + role: 'model', + }, + finishReason: 'stop', + index: 0, + }, + ], + }; + })(); + }, + }; + + // chats.create implementation + this.chats = { + create: (...args) => { + const params = args[0]; + const model = params.model; + + return { + modelVersion: model, + sendMessage: async (..._messageArgs) => { + // Simulate processing time + await new Promise(resolve => setTimeout(resolve, 10)); + + return { + candidates: [ + { + content: { + parts: [ + { + text: 'This is a joke from the chat!', + }, + ], + role: 'model', + }, + finishReason: 'stop', + index: 0, + }, + ], + usageMetadata: { + promptTokenCount: 8, + candidatesTokenCount: 12, + totalTokenCount: 20, + }, + modelVersion: model, // Include model version in response + }; + }, + sendMessageStream: async () => { + // Return a promise that resolves to an async generator + return (async function* () { + yield { + candidates: [ + { + content: { + parts: [{ text: 'Streaming chat response' }], + role: 'model', + }, + finishReason: 'stop', + index: 0, + }, + ], + }; + })(); + }, + }; + }, + }; + } +} + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js new file mode 100644 index 000000000000..f6f4f7fbe701 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -0,0 +1,38 @@ +import * as Sentry from '@sentry/browser'; +import { MockGoogleGenAI } from './mocks.js'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); + +const mockClient = new MockGoogleGenAI({ + apiKey: 'mock-api-key', +}); + +const client = Sentry.instrumentGoogleGenAIClient(mockClient); + +// Test that manual instrumentation doesn't crash the browser +// The instrumentation automatically creates spans +// Test both chats and models APIs +const chat = client.chats.create({ + model: 'gemini-1.5-pro', + config: { + temperature: 0.8, + topP: 0.9, + maxOutputTokens: 150, + }, + history: [ + { + role: 'user', + parts: [{ text: 'Hello, how are you?' }], + }, + ], +}); + +chat.sendMessage({ + message: 'Tell me a joke', +}) + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts new file mode 100644 index 000000000000..d943746339fa --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts @@ -0,0 +1,34 @@ +import { expect } from '@playwright/test'; +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; + +// These tests are not exhaustive because the instrumentation is +// already tested in the node integration tests and we merely +// want to test that the instrumentation does not crash in the browser +// and that gen_ai transactions are sent. + +sentryTest('manual Google GenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const transactionPromise = waitForTransactionRequest(page, event => { + return !!event.transaction?.includes('gemini-1.5-pro'); + }); + + const url = await getLocalTestUrl({ testDir: __dirname }); + await page.goto(url); + + const req = await transactionPromise; + const eventData = envelopeRequestParser(req); + + // Verify it's a gen_ai transaction + expect(eventData.transaction).toBe('chat gemini-1.5-pro create'); + expect(eventData.contexts?.trace?.op).toBe('gen_ai.chat'); + expect(eventData.contexts?.trace?.origin).toBe('auto.ai.google_genai'); + expect(eventData.contexts?.trace?.data).toMatchObject({ + 'gen_ai.operation.name': 'chat', + 'gen_ai.system': 'google_genai', + 'gen_ai.request.model': 'gemini-1.5-pro', + }); +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js new file mode 100644 index 000000000000..df2d6064a6f2 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js @@ -0,0 +1,47 @@ +// Mock OpenAI client for browser testing +export class MockOpenAi { + constructor(config) { + this.apiKey = config.apiKey; + + this.chat = { + completions: { + create: async (...args) => { + const params = args[0]; + // Simulate processing time + await new Promise(resolve => setTimeout(resolve, 10)); + + if (params.model === 'error-model') { + const error = new Error('Model not found'); + error.status = 404; + error.headers = { 'x-request-id': 'mock-request-123' }; + throw error; + } + + return { + id: 'chatcmpl-mock123', + object: 'chat.completion', + created: 1677652288, + model: params.model, + system_fingerprint: 'fp_44709d6fcb', + choices: [ + { + index: 0, + message: { + role: 'assistant', + content: 'Hello from OpenAI mock!', + }, + finish_reason: 'stop', + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 15, + total_tokens: 25, + }, + }; + }, + }, + }; + } +} + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js new file mode 100644 index 000000000000..e926f899cce8 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -0,0 +1,28 @@ +import * as Sentry from '@sentry/browser'; +import { MockOpenAi } from './mocks.js'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); + +const mockClient = new MockOpenAi({ + apiKey: 'mock-api-key', +}); + +const client = Sentry.instrumentOpenAiClient(mockClient); + +// Test that manual instrumentation doesn't crash the browser +// The instrumentation automatically creates spans +client.chat.completions.create({ + model: 'gpt-3.5-turbo', + messages: [ + { role: 'system', content: 'You are a helpful assistant.' }, + { role: 'user', content: 'What is the capital of France?' }, + ], + temperature: 0.7, + max_tokens: 100, +}); + diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts new file mode 100644 index 000000000000..4ab4d768dffd --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts @@ -0,0 +1,40 @@ +import { expect } from '@playwright/test'; +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; + +// These tests are not exhaustive because the instrumentation is +// already tested in the node integration tests and we merely +// want to test that the instrumentation does not crash in the browser +// and that gen_ai transactions are sent. + +sentryTest('manual OpenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + if (shouldSkipTracingTest()) { + sentryTest.skip(); + } + + const transactionPromise = waitForTransactionRequest(page, event => { + return !!event.transaction?.includes('gpt-3.5-turbo'); + }); + + const url = await getLocalTestUrl({ testDir: __dirname }); + await page.goto(url); + + const req = await transactionPromise; + const eventData = envelopeRequestParser(req); + + // Verify it's a gen_ai transaction + expect(eventData.transaction).toBe('chat gpt-3.5-turbo'); + expect(eventData.contexts?.trace?.op).toBe('gen_ai.chat'); + expect(eventData.contexts?.trace?.origin).toBe('auto.ai.openai'); + expect(eventData.contexts?.trace?.data).toMatchObject({ + 'gen_ai.operation.name': 'chat', + 'gen_ai.system': 'openai', + 'gen_ai.request.model': 'gpt-3.5-turbo', + 'gen_ai.request.temperature': 0.7, + 'gen_ai.response.model': 'gpt-3.5-turbo', + 'gen_ai.response.id': 'chatcmpl-mock123', + 'gen_ai.usage.input_tokens': 10, + 'gen_ai.usage.output_tokens': 15, + 'gen_ai.usage.total_tokens': 25, + }); +}); diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 5e9924fe6da5..ae13e984c85f 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -63,6 +63,9 @@ export { zodErrorsIntegration, thirdPartyErrorFilterIntegration, featureFlagsIntegration, + instrumentAnthropicAiClient, + instrumentOpenAiClient, + instrumentGoogleGenAIClient, logger, } from '@sentry/core'; export type { Span, FeatureFlagsIntegration } from '@sentry/core'; From a8e10f4815e0559817cdff93dcddd0869155b915 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 2 Oct 2025 13:30:27 +0300 Subject: [PATCH 2/8] Fix linter --- .../suites/tracing/ai-providers/anthropic/mocks.js | 1 - .../suites/tracing/ai-providers/anthropic/subject.js | 3 --- .../suites/tracing/ai-providers/anthropic/test.ts | 6 +----- .../suites/tracing/ai-providers/google-genai/mocks.js | 1 - .../suites/tracing/ai-providers/google-genai/subject.js | 5 +---- .../suites/tracing/ai-providers/google-genai/test.ts | 6 +----- .../suites/tracing/ai-providers/openai/mocks.js | 1 - .../suites/tracing/ai-providers/openai/subject.js | 3 --- .../suites/tracing/ai-providers/openai/test.ts | 6 +----- 9 files changed, 4 insertions(+), 28 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js index ba2a01c8ed40..aab76b2b4fcc 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js @@ -52,4 +52,3 @@ export class MockAnthropic { }; } } - diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index 7e38cfb749db..ce9668b88372 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -1,8 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockAnthropic } from './mocks.js'; -window.Sentry = Sentry; - Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, @@ -22,4 +20,3 @@ client.messages.create({ temperature: 0.7, max_tokens: 100, }); - diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts index ec13310f792f..cc0ab62d22c9 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../utils/fixtures'; -import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; +import { envelopeRequestParser, waitForTransactionRequest } from '../../../../utils/helpers'; // These tests are not exhaustive because the instrumentation is // already tested in the node integration tests and we merely @@ -8,10 +8,6 @@ import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest // and that gen_ai transactions are sent. sentryTest('manual Anthropic instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } - const transactionPromise = waitForTransactionRequest(page, event => { return !!event.transaction?.includes('claude-3-haiku-20240307'); }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js index f125fa9f16c0..0870487d5c91 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js @@ -115,4 +115,3 @@ export class MockGoogleGenAI { }; } } - diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js index f6f4f7fbe701..303636f88242 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -1,8 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockGoogleGenAI } from './mocks.js'; -window.Sentry = Sentry; - Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, @@ -34,5 +32,4 @@ const chat = client.chats.create({ chat.sendMessage({ message: 'Tell me a joke', -}) - +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts index d943746339fa..8e4c90ff5ec3 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../utils/fixtures'; -import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; +import { envelopeRequestParser, waitForTransactionRequest } from '../../../../utils/helpers'; // These tests are not exhaustive because the instrumentation is // already tested in the node integration tests and we merely @@ -8,10 +8,6 @@ import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest // and that gen_ai transactions are sent. sentryTest('manual Google GenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } - const transactionPromise = waitForTransactionRequest(page, event => { return !!event.transaction?.includes('gemini-1.5-pro'); }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js index df2d6064a6f2..fa8011fbd372 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js @@ -44,4 +44,3 @@ export class MockOpenAi { }; } } - diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index e926f899cce8..58e04c46ca09 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -1,8 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockOpenAi } from './mocks.js'; -window.Sentry = Sentry; - Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, @@ -25,4 +23,3 @@ client.chat.completions.create({ temperature: 0.7, max_tokens: 100, }); - diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts index 4ab4d768dffd..8f59a21deaef 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../utils/fixtures'; -import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; +import { envelopeRequestParser, waitForTransactionRequest } from '../../../../utils/helpers'; // These tests are not exhaustive because the instrumentation is // already tested in the node integration tests and we merely @@ -8,10 +8,6 @@ import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest // and that gen_ai transactions are sent. sentryTest('manual OpenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { - if (shouldSkipTracingTest()) { - sentryTest.skip(); - } - const transactionPromise = waitForTransactionRequest(page, event => { return !!event.transaction?.includes('gpt-3.5-turbo'); }); From d611a75e7c9426ba9e8f248e3a93e80191a017f9 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 2 Oct 2025 14:20:53 +0300 Subject: [PATCH 3/8] update with init --- .../suites/tracing/ai-providers/anthropic/init.js | 8 ++++++++ .../suites/tracing/ai-providers/anthropic/subject.js | 5 ----- .../suites/tracing/ai-providers/google-genai/init.js | 8 ++++++++ .../suites/tracing/ai-providers/google-genai/subject.js | 5 ----- .../suites/tracing/ai-providers/openai/init.js | 8 ++++++++ .../suites/tracing/ai-providers/openai/subject.js | 5 ----- 6 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js create mode 100644 dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js new file mode 100644 index 000000000000..7c200c542c56 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js @@ -0,0 +1,8 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index ce9668b88372..455ca65c55a0 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -1,11 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockAnthropic } from './mocks.js'; -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - tracesSampleRate: 1, -}); - const mockClient = new MockAnthropic({ apiKey: 'mock-api-key', }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js new file mode 100644 index 000000000000..7c200c542c56 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js @@ -0,0 +1,8 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js index 303636f88242..47671ff00cde 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -1,11 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockGoogleGenAI } from './mocks.js'; -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - tracesSampleRate: 1, -}); - const mockClient = new MockGoogleGenAI({ apiKey: 'mock-api-key', }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js new file mode 100644 index 000000000000..7c200c542c56 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js @@ -0,0 +1,8 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index 58e04c46ca09..7f32e596d08c 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -1,11 +1,6 @@ import * as Sentry from '@sentry/browser'; import { MockOpenAi } from './mocks.js'; -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - tracesSampleRate: 1, -}); - const mockClient = new MockOpenAi({ apiKey: 'mock-api-key', }); From f2d429cfdb813bbfb24c54b5c94bc0598a1d89bc Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Thu, 2 Oct 2025 14:38:09 +0300 Subject: [PATCH 4/8] await the call --- .../suites/tracing/ai-providers/anthropic/subject.js | 2 +- .../suites/tracing/ai-providers/google-genai/subject.js | 2 +- .../suites/tracing/ai-providers/openai/subject.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index 455ca65c55a0..0ba78dc301a7 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -9,7 +9,7 @@ const client = Sentry.instrumentAnthropicAiClient(mockClient); // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans -client.messages.create({ +await client.messages.create({ model: 'claude-3-haiku-20240307', messages: [{ role: 'user', content: 'What is the capital of France?' }], temperature: 0.7, diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js index 47671ff00cde..1ab47e665347 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -25,6 +25,6 @@ const chat = client.chats.create({ ], }); -chat.sendMessage({ +await chat.sendMessage({ message: 'Tell me a joke', }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index 7f32e596d08c..7dbde4b4985b 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -9,7 +9,7 @@ const client = Sentry.instrumentOpenAiClient(mockClient); // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans -client.chat.completions.create({ +await client.chat.completions.create({ model: 'gpt-3.5-turbo', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, From affb6f92b011db3b11b9d069eb23adf95290b6a0 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 6 Oct 2025 11:55:58 +0200 Subject: [PATCH 5/8] try to fix timeout issue --- .../suites/tracing/ai-providers/anthropic/subject.js | 5 ++++- .../suites/tracing/ai-providers/openai/subject.js | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index 0ba78dc301a7..fca4b5d75fa4 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -9,9 +9,12 @@ const client = Sentry.instrumentAnthropicAiClient(mockClient); // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans -await client.messages.create({ +const response = await client.messages.create({ model: 'claude-3-haiku-20240307', messages: [{ role: 'user', content: 'What is the capital of France?' }], temperature: 0.7, max_tokens: 100, }); + +// eslint-disable-next-line no-console +console.log(JSON.stringify(response)); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index 7dbde4b4985b..2e01d9b1e2c7 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -9,7 +9,7 @@ const client = Sentry.instrumentOpenAiClient(mockClient); // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans -await client.chat.completions.create({ +const response = await client.chat.completions.create({ model: 'gpt-3.5-turbo', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, @@ -18,3 +18,9 @@ await client.chat.completions.create({ temperature: 0.7, max_tokens: 100, }); + +// eslint-disable-next-line no-console +console.log(JSON.stringify(response)); + + + From 62397c5f374ce5df342d28556b17f5570992759f Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Mon, 6 Oct 2025 14:02:25 +0200 Subject: [PATCH 6/8] one more try --- .../suites/tracing/ai-providers/anthropic/subject.js | 3 +++ .../suites/tracing/ai-providers/google-genai/subject.js | 8 +++++++- .../suites/tracing/ai-providers/openai/subject.js | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index fca4b5d75fa4..04ae4fb9bdc6 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -18,3 +18,6 @@ const response = await client.messages.create({ // eslint-disable-next-line no-console console.log(JSON.stringify(response)); + +// Ensure transaction is flushed in CI +await Sentry.flush(2000); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js index 1ab47e665347..6d193b3a98c4 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -25,6 +25,12 @@ const chat = client.chats.create({ ], }); -await chat.sendMessage({ +const response = await chat.sendMessage({ message: 'Tell me a joke', }); + +// eslint-disable-next-line no-console +console.log(JSON.stringify(response)); + +// Ensure transaction is flushed in CI +await Sentry.flush(2000); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index 2e01d9b1e2c7..417340584108 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -22,5 +22,5 @@ const response = await client.chat.completions.create({ // eslint-disable-next-line no-console console.log(JSON.stringify(response)); - - +// Ensure transaction is flushed in CI +await Sentry.flush(2000); From 535e8dc4aac686ea1b9cdef64646879e6e7062d5 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Tue, 7 Oct 2025 11:31:59 +0200 Subject: [PATCH 7/8] debug --- .../tracing/ai-providers/anthropic/init.js | 1 + .../tracing/ai-providers/anthropic/mocks.js | 9 ++++++- .../tracing/ai-providers/anthropic/subject.js | 22 ++++++++++++++++- .../tracing/ai-providers/anthropic/test.ts | 23 ++++++++++++++++++ .../tracing/ai-providers/google-genai/init.js | 1 + .../ai-providers/google-genai/mocks.js | 13 +++++++++- .../ai-providers/google-genai/subject.js | 24 ++++++++++++++++++- .../tracing/ai-providers/google-genai/test.ts | 23 ++++++++++++++++++ .../tracing/ai-providers/openai/init.js | 1 + .../tracing/ai-providers/openai/mocks.js | 9 ++++++- .../tracing/ai-providers/openai/subject.js | 22 ++++++++++++++++- .../tracing/ai-providers/openai/test.ts | 23 ++++++++++++++++++ 12 files changed, 165 insertions(+), 6 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js index 7c200c542c56..d90a3acf6157 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/init.js @@ -5,4 +5,5 @@ window.Sentry = Sentry; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, + debug: true, }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js index aab76b2b4fcc..1f56143e251f 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/mocks.js @@ -1,11 +1,15 @@ // Mock Anthropic client for browser testing export class MockAnthropic { constructor(config) { + // eslint-disable-next-line no-console + console.log('[Mock Anthropic] Constructor called with config:', config); this.apiKey = config.apiKey; // Main focus: messages.create functionality this.messages = { create: async (...args) => { + // eslint-disable-next-line no-console + console.log('[Mock Anthropic] messages.create called with args:', args); const params = args[0]; // Simulate processing time await new Promise(resolve => setTimeout(resolve, 10)); @@ -17,7 +21,7 @@ export class MockAnthropic { throw error; } - return { + const response = { id: 'msg_mock123', type: 'message', role: 'assistant', @@ -37,6 +41,9 @@ export class MockAnthropic { cache_read_input_tokens: 0, }, }; + // eslint-disable-next-line no-console + console.log('[Mock Anthropic] Returning response:', response); + return response; }, countTokens: async (..._args) => ({ id: 'mock', type: 'model', model: 'mock', input_tokens: 0 }), }; diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js index 04ae4fb9bdc6..ab0b8c2265b9 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/subject.js @@ -1,14 +1,29 @@ import * as Sentry from '@sentry/browser'; import { MockAnthropic } from './mocks.js'; +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Starting test...'); + +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Creating mock client...'); const mockClient = new MockAnthropic({ apiKey: 'mock-api-key', }); +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Mock client created:', mockClient); + +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Instrumenting client with Sentry...'); const client = Sentry.instrumentAnthropicAiClient(mockClient); +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Client instrumented:', client); + // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Calling messages.create...'); const response = await client.messages.create({ model: 'claude-3-haiku-20240307', messages: [{ role: 'user', content: 'What is the capital of France?' }], @@ -17,7 +32,12 @@ const response = await client.messages.create({ }); // eslint-disable-next-line no-console -console.log(JSON.stringify(response)); +console.log('[Anthropic Test] Response received:', JSON.stringify(response)); +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Flushing Sentry...'); // Ensure transaction is flushed in CI await Sentry.flush(2000); + +// eslint-disable-next-line no-console +console.log('[Anthropic Test] Test completed!'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts index cc0ab62d22c9..9ba7b847a663 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts @@ -8,15 +8,38 @@ import { envelopeRequestParser, waitForTransactionRequest } from '../../../../ut // and that gen_ai transactions are sent. sentryTest('manual Anthropic instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + // Listen for console logs + page.on('console', msg => { + // eslint-disable-next-line no-console + console.log(`[Browser Console ${msg.type()}]`, msg.text()); + }); + + // Listen for page errors + page.on('pageerror', error => { + // eslint-disable-next-line no-console + console.error('[Browser Error]', error); + }); + const transactionPromise = waitForTransactionRequest(page, event => { + // eslint-disable-next-line no-console + console.log('[Test] Received transaction event:', JSON.stringify(event, null, 2)); return !!event.transaction?.includes('claude-3-haiku-20240307'); }); const url = await getLocalTestUrl({ testDir: __dirname }); + // eslint-disable-next-line no-console + console.log('[Test] Navigating to URL:', url); await page.goto(url); + // eslint-disable-next-line no-console + console.log('[Test] Waiting for transaction...'); const req = await transactionPromise; + // eslint-disable-next-line no-console + console.log('[Test] Transaction received!'); + const eventData = envelopeRequestParser(req); + // eslint-disable-next-line no-console + console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2)); // Verify it's a gen_ai transaction expect(eventData.transaction).toBe('messages claude-3-haiku-20240307'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js index 7c200c542c56..d90a3acf6157 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/init.js @@ -5,4 +5,5 @@ window.Sentry = Sentry; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, + debug: true, }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js index 0870487d5c91..d9374b64c990 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/mocks.js @@ -1,11 +1,15 @@ // Mock Google GenAI client for browser testing export class MockGoogleGenAI { constructor(config) { + // eslint-disable-next-line no-console + console.log('[Mock Google GenAI] Constructor called with config:', config); this.apiKey = config.apiKey; // models.generateContent functionality this.models = { generateContent: async (...args) => { + // eslint-disable-next-line no-console + console.log('[Mock Google GenAI] models.generateContent called with args:', args); const params = args[0]; // Simulate processing time await new Promise(resolve => setTimeout(resolve, 10)); @@ -61,16 +65,20 @@ export class MockGoogleGenAI { // chats.create implementation this.chats = { create: (...args) => { + // eslint-disable-next-line no-console + console.log('[Mock Google GenAI] chats.create called with args:', args); const params = args[0]; const model = params.model; return { modelVersion: model, sendMessage: async (..._messageArgs) => { + // eslint-disable-next-line no-console + console.log('[Mock Google GenAI] chat.sendMessage called with args:', _messageArgs); // Simulate processing time await new Promise(resolve => setTimeout(resolve, 10)); - return { + const response = { candidates: [ { content: { @@ -92,6 +100,9 @@ export class MockGoogleGenAI { }, modelVersion: model, // Include model version in response }; + // eslint-disable-next-line no-console + console.log('[Mock Google GenAI] Returning response:', response); + return response; }, sendMessageStream: async () => { // Return a promise that resolves to an async generator diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js index 6d193b3a98c4..65123b1eb18d 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/subject.js @@ -1,15 +1,30 @@ import * as Sentry from '@sentry/browser'; import { MockGoogleGenAI } from './mocks.js'; +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Starting test...'); + +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Creating mock client...'); const mockClient = new MockGoogleGenAI({ apiKey: 'mock-api-key', }); +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Mock client created:', mockClient); + +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Instrumenting client with Sentry...'); const client = Sentry.instrumentGoogleGenAIClient(mockClient); +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Client instrumented:', client); + // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans // Test both chats and models APIs +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Creating chat...'); const chat = client.chats.create({ model: 'gemini-1.5-pro', config: { @@ -25,12 +40,19 @@ const chat = client.chats.create({ ], }); +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Sending message...'); const response = await chat.sendMessage({ message: 'Tell me a joke', }); // eslint-disable-next-line no-console -console.log(JSON.stringify(response)); +console.log('[Google GenAI Test] Response received:', JSON.stringify(response)); +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Flushing Sentry...'); // Ensure transaction is flushed in CI await Sentry.flush(2000); + +// eslint-disable-next-line no-console +console.log('[Google GenAI Test] Test completed!'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts index 8e4c90ff5ec3..89180ed52cb8 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts @@ -8,15 +8,38 @@ import { envelopeRequestParser, waitForTransactionRequest } from '../../../../ut // and that gen_ai transactions are sent. sentryTest('manual Google GenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + // Listen for console logs + page.on('console', msg => { + // eslint-disable-next-line no-console + console.log(`[Browser Console ${msg.type()}]`, msg.text()); + }); + + // Listen for page errors + page.on('pageerror', error => { + // eslint-disable-next-line no-console + console.error('[Browser Error]', error); + }); + const transactionPromise = waitForTransactionRequest(page, event => { + // eslint-disable-next-line no-console + console.log('[Test] Received transaction event:', JSON.stringify(event, null, 2)); return !!event.transaction?.includes('gemini-1.5-pro'); }); const url = await getLocalTestUrl({ testDir: __dirname }); + // eslint-disable-next-line no-console + console.log('[Test] Navigating to URL:', url); await page.goto(url); + // eslint-disable-next-line no-console + console.log('[Test] Waiting for transaction...'); const req = await transactionPromise; + // eslint-disable-next-line no-console + console.log('[Test] Transaction received!'); + const eventData = envelopeRequestParser(req); + // eslint-disable-next-line no-console + console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2)); // Verify it's a gen_ai transaction expect(eventData.transaction).toBe('chat gemini-1.5-pro create'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js index 7c200c542c56..d90a3acf6157 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/init.js @@ -5,4 +5,5 @@ window.Sentry = Sentry; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, + debug: true, }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js index fa8011fbd372..fe7912a6ff72 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/mocks.js @@ -1,11 +1,15 @@ // Mock OpenAI client for browser testing export class MockOpenAi { constructor(config) { + // eslint-disable-next-line no-console + console.log('[Mock OpenAI] Constructor called with config:', config); this.apiKey = config.apiKey; this.chat = { completions: { create: async (...args) => { + // eslint-disable-next-line no-console + console.log('[Mock OpenAI] chat.completions.create called with args:', args); const params = args[0]; // Simulate processing time await new Promise(resolve => setTimeout(resolve, 10)); @@ -17,7 +21,7 @@ export class MockOpenAi { throw error; } - return { + const response = { id: 'chatcmpl-mock123', object: 'chat.completion', created: 1677652288, @@ -39,6 +43,9 @@ export class MockOpenAi { total_tokens: 25, }, }; + // eslint-disable-next-line no-console + console.log('[Mock OpenAI] Returning response:', response); + return response; }, }, }; diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js index 417340584108..ce4580a0d274 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/subject.js @@ -1,14 +1,29 @@ import * as Sentry from '@sentry/browser'; import { MockOpenAi } from './mocks.js'; +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Starting test...'); + +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Creating mock client...'); const mockClient = new MockOpenAi({ apiKey: 'mock-api-key', }); +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Mock client created:', mockClient); + +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Instrumenting client with Sentry...'); const client = Sentry.instrumentOpenAiClient(mockClient); +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Client instrumented:', client); + // Test that manual instrumentation doesn't crash the browser // The instrumentation automatically creates spans +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Calling chat.completions.create...'); const response = await client.chat.completions.create({ model: 'gpt-3.5-turbo', messages: [ @@ -20,7 +35,12 @@ const response = await client.chat.completions.create({ }); // eslint-disable-next-line no-console -console.log(JSON.stringify(response)); +console.log('[OpenAI Test] Response received:', JSON.stringify(response)); +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Flushing Sentry...'); // Ensure transaction is flushed in CI await Sentry.flush(2000); + +// eslint-disable-next-line no-console +console.log('[OpenAI Test] Test completed!'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts index 8f59a21deaef..752a930dd4eb 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts @@ -8,15 +8,38 @@ import { envelopeRequestParser, waitForTransactionRequest } from '../../../../ut // and that gen_ai transactions are sent. sentryTest('manual OpenAI instrumentation sends gen_ai transactions', async ({ getLocalTestUrl, page }) => { + // Listen for console logs + page.on('console', msg => { + // eslint-disable-next-line no-console + console.log(`[Browser Console ${msg.type()}]`, msg.text()); + }); + + // Listen for page errors + page.on('pageerror', error => { + // eslint-disable-next-line no-console + console.error('[Browser Error]', error); + }); + const transactionPromise = waitForTransactionRequest(page, event => { + // eslint-disable-next-line no-console + console.log('[Test] Received transaction event:', JSON.stringify(event, null, 2)); return !!event.transaction?.includes('gpt-3.5-turbo'); }); const url = await getLocalTestUrl({ testDir: __dirname }); + // eslint-disable-next-line no-console + console.log('[Test] Navigating to URL:', url); await page.goto(url); + // eslint-disable-next-line no-console + console.log('[Test] Waiting for transaction...'); const req = await transactionPromise; + // eslint-disable-next-line no-console + console.log('[Test] Transaction received!'); + const eventData = envelopeRequestParser(req); + // eslint-disable-next-line no-console + console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2)); // Verify it's a gen_ai transaction expect(eventData.transaction).toBe('chat gpt-3.5-turbo'); From d05004671eea57a7562441ed92a992fa219e8536 Mon Sep 17 00:00:00 2001 From: RulaKhaled Date: Tue, 7 Oct 2025 11:32:08 +0200 Subject: [PATCH 8/8] debug --- .../suites/tracing/ai-providers/anthropic/test.ts | 2 +- .../suites/tracing/ai-providers/google-genai/test.ts | 2 +- .../suites/tracing/ai-providers/openai/test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts index 9ba7b847a663..4705f435dfdd 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/anthropic/test.ts @@ -36,7 +36,7 @@ sentryTest('manual Anthropic instrumentation sends gen_ai transactions', async ( const req = await transactionPromise; // eslint-disable-next-line no-console console.log('[Test] Transaction received!'); - + const eventData = envelopeRequestParser(req); // eslint-disable-next-line no-console console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2)); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts index 89180ed52cb8..316b3fe509a0 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/google-genai/test.ts @@ -36,7 +36,7 @@ sentryTest('manual Google GenAI instrumentation sends gen_ai transactions', asyn const req = await transactionPromise; // eslint-disable-next-line no-console console.log('[Test] Transaction received!'); - + const eventData = envelopeRequestParser(req); // eslint-disable-next-line no-console console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2)); diff --git a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts index 752a930dd4eb..bd92baa661f3 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/ai-providers/openai/test.ts @@ -36,7 +36,7 @@ sentryTest('manual OpenAI instrumentation sends gen_ai transactions', async ({ g const req = await transactionPromise; // eslint-disable-next-line no-console console.log('[Test] Transaction received!'); - + const eventData = envelopeRequestParser(req); // eslint-disable-next-line no-console console.log('[Test] Parsed event data:', JSON.stringify(eventData, null, 2));