diff --git a/packages/cloudflare/src/index.ts b/packages/cloudflare/src/index.ts index 72cb9ff94c02..568e39debcb1 100644 --- a/packages/cloudflare/src/index.ts +++ b/packages/cloudflare/src/index.ts @@ -76,7 +76,6 @@ export { functionToStringIntegration, // eslint-disable-next-line typescript/no-deprecated inboundFiltersIntegration, - instrumentGoogleGenAIClient, eventFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, @@ -126,7 +125,12 @@ export { httpServerIntegration } from './integrations/httpServer'; export { fetchIntegration } from './integrations/fetch'; export { spotlightIntegration } from './integrations/spotlight'; export { vercelAIIntegration } from './integrations/tracing/vercelai'; -export { prismaIntegration, instrumentOpenAiClient, instrumentAnthropicAiClient } from '@sentry/server-utils'; +export { + prismaIntegration, + instrumentOpenAiClient, + instrumentAnthropicAiClient, + instrumentGoogleGenAIClient, +} from '@sentry/server-utils'; // eslint-disable-next-line typescript/no-deprecated export { instrumentD1WithSentry } from './instrumentations/worker/instrumentD1'; diff --git a/packages/core/src/server-exports.ts b/packages/core/src/server-exports.ts index 67a3c9f2fc9b..195cb9777669 100644 --- a/packages/core/src/server-exports.ts +++ b/packages/core/src/server-exports.ts @@ -60,15 +60,6 @@ export { addVercelAiProcessors, getProviderMetadataAttributes } from './tracing/ export { getTruncatedJsonString, shouldEnableTruncation, resolveAIRecordingOptions } from './tracing/ai/utils'; export { _INTERNAL_getSpanContextForToolCallId, _INTERNAL_cleanupToolCallSpanContext } from './tracing/vercel-ai/utils'; export { toolCallSpanContextMap as _INTERNAL_toolCallSpanContextMap } from './tracing/vercel-ai/constants'; -export { - instrumentGoogleGenAIClient, - extractRequestAttributes as extractGoogleGenAIRequestAttributes, - addPrivateRequestAttributes as addGoogleGenAIRequestAttributes, - addResponseAttributes as addGoogleGenAIResponseAttributes, -} from './tracing/google-genai'; -export { instrumentStream as instrumentGoogleGenAIStream } from './tracing/google-genai/streaming'; -export { GOOGLE_GENAI_INTEGRATION_NAME } from './tracing/google-genai/constants'; -export type { GoogleGenAIResponse } from './tracing/google-genai/types'; export { createLangChainCallbackHandler, instrumentLangChainEmbeddings } from './tracing/langchain'; export { _INTERNAL_getLangChainEmbeddingsSpanOptions } from './tracing/langchain/embeddings'; export { _INTERNAL_mergeLangChainCallbackHandler } from './tracing/langchain/utils'; @@ -85,11 +76,3 @@ export { LANGGRAPH_INTEGRATION_NAME } from './tracing/langgraph/constants'; export type { LangGraphOptions, LangGraphIntegration, CompiledGraph } from './tracing/langgraph/types'; export { instrumentWorkersAiClient } from './tracing/workers-ai'; export type { WorkersAiClient, WorkersAiOptions } from './tracing/workers-ai/types'; -export type { - GoogleGenAIClient, - GoogleGenAIChat, - GoogleGenAIOptions, - GoogleGenAIInstrumentedMethod, -} from './tracing/google-genai/types'; -// eslint-disable-next-line typescript/no-deprecated -export type { GoogleGenAIIstrumentedMethod } from './tracing/google-genai/types'; diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index a1bdec11735c..21b5de7685cd 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -30,7 +30,12 @@ export { vercelAiIntegration as vercelAIIntegration, } from '@sentry/server-utils/orchestrion'; export { redisIntegration } from './integrations/tracing/redis'; -export { prismaIntegration, instrumentOpenAiClient, instrumentAnthropicAiClient } from '@sentry/server-utils'; +export { + prismaIntegration, + instrumentOpenAiClient, + instrumentAnthropicAiClient, + instrumentGoogleGenAIClient, +} from '@sentry/server-utils'; export { setupHapiErrorHandler } from './integrations/tracing/hapi'; export { setupKoaErrorHandler } from './integrations/tracing/koa'; export { @@ -133,7 +138,6 @@ export { updateSpanName, supabaseIntegration, instrumentSupabaseClient, - instrumentGoogleGenAIClient, zodErrorsIntegration, profiler, consoleLoggingIntegration, diff --git a/packages/core/src/tracing/google-genai/constants.ts b/packages/server-utils/src/ai/google-genai/constants.ts similarity index 93% rename from packages/core/src/tracing/google-genai/constants.ts rename to packages/server-utils/src/ai/google-genai/constants.ts index f23467e2cb62..12fec18a7ba4 100644 --- a/packages/core/src/tracing/google-genai/constants.ts +++ b/packages/server-utils/src/ai/google-genai/constants.ts @@ -1,4 +1,4 @@ -import type { InstrumentedMethodRegistry } from '../ai/utils'; +import type { InstrumentedMethodRegistry } from '../core/utils'; export const GOOGLE_GENAI_INTEGRATION_NAME = 'Google_GenAI' as const; diff --git a/packages/core/src/tracing/google-genai/index.ts b/packages/server-utils/src/ai/google-genai/index.ts similarity index 96% rename from packages/core/src/tracing/google-genai/index.ts rename to packages/server-utils/src/ai/google-genai/index.ts index 384c42477dca..307bb25b708f 100644 --- a/packages/core/src/tracing/google-genai/index.ts +++ b/packages/server-utils/src/ai/google-genai/index.ts @@ -1,11 +1,15 @@ /* eslint-disable typescript-eslint/no-deprecated */ /* eslint-disable max-lines */ -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/span'; -import { handleCallbackErrors } from '../../utils/handleCallbackErrors'; +import { + captureException, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SPAN_STATUS_ERROR, + startSpan, + startSpanManual, + handleCallbackErrors, + stringify, +} from '@sentry/core'; +import type { Span, SpanAttributeValue } from '@sentry/core'; import { GEN_AI_EMBEDDINGS_INPUT, GEN_AI_INPUT_MESSAGES, @@ -27,15 +31,14 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import type { InstrumentedMethodEntry } from '../ai/utils'; -import { stringify } from '../../utils/string'; +import type { InstrumentedMethodEntry } from '../core/utils'; import { buildMethodPath, extractSystemInstructions, getTruncatedJsonString, resolveAIRecordingOptions, shouldEnableTruncation, -} from '../ai/utils'; +} from '../core/utils'; import { GOOGLE_GENAI_METHOD_REGISTRY, GOOGLE_GENAI_SYSTEM_NAME } from './constants'; import { instrumentStream } from './streaming'; import type { Candidate, ContentPart, GoogleGenAIOptions, GoogleGenAIResponse } from './types'; @@ -411,7 +414,7 @@ function createDeepProxy(target: T, currentPath = '', options: * @example * ```typescript * import { GoogleGenAI } from '@google/genai'; - * import { instrumentGoogleGenAIClient } from '@sentry/core'; + * import { instrumentGoogleGenAIClient } from '@sentry/node'; * * const genAI = new GoogleGenAI({ apiKey: process.env.GOOGLE_GENAI_API_KEY }); * const instrumentedClient = instrumentGoogleGenAIClient(genAI); diff --git a/packages/core/src/tracing/google-genai/streaming.ts b/packages/server-utils/src/ai/google-genai/streaming.ts similarity index 95% rename from packages/core/src/tracing/google-genai/streaming.ts rename to packages/server-utils/src/ai/google-genai/streaming.ts index d44d678753be..646884b62e4b 100644 --- a/packages/core/src/tracing/google-genai/streaming.ts +++ b/packages/server-utils/src/ai/google-genai/streaming.ts @@ -1,7 +1,6 @@ -import { captureException } from '../../exports'; -import { SPAN_STATUS_ERROR } from '../../tracing'; -import type { Span } from '../../types/span'; -import { endStreamSpan } from '../ai/utils'; +import { captureException, SPAN_STATUS_ERROR } from '@sentry/core'; +import type { Span } from '@sentry/core'; +import { endStreamSpan } from '../core/utils'; import type { GoogleGenAIResponse } from './types'; /** diff --git a/packages/core/src/tracing/google-genai/types.ts b/packages/server-utils/src/ai/google-genai/types.ts similarity index 100% rename from packages/core/src/tracing/google-genai/types.ts rename to packages/server-utils/src/ai/google-genai/types.ts diff --git a/packages/core/src/tracing/google-genai/utils.ts b/packages/server-utils/src/ai/google-genai/utils.ts similarity index 100% rename from packages/core/src/tracing/google-genai/utils.ts rename to packages/server-utils/src/ai/google-genai/utils.ts diff --git a/packages/server-utils/src/ai/index.ts b/packages/server-utils/src/ai/index.ts index 3931cb532c6e..15618cf73702 100644 --- a/packages/server-utils/src/ai/index.ts +++ b/packages/server-utils/src/ai/index.ts @@ -6,3 +6,4 @@ export { instrumentOpenAiClient } from './openai'; export { instrumentAnthropicAiClient } from './anthropic-ai'; +export { instrumentGoogleGenAIClient } from './google-genai'; diff --git a/packages/server-utils/src/integrations/tracing-channel/google-genai.ts b/packages/server-utils/src/integrations/tracing-channel/google-genai.ts index ec253f78f394..74ffcfea0ba5 100644 --- a/packages/server-utils/src/integrations/tracing-channel/google-genai.ts +++ b/packages/server-utils/src/integrations/tracing-channel/google-genai.ts @@ -1,20 +1,18 @@ import { GEN_AI_REQUEST_MODEL } from '@sentry/conventions/attributes'; import * as diagnosticsChannel from 'node:diagnostics_channel'; -import type { GoogleGenAIOptions, GoogleGenAIResponse, IntegrationFn, Span } from '@sentry/core'; +import type { IntegrationFn, Span } from '@sentry/core'; import { _INTERNAL_shouldSkipAiProviderWrapping, - addGoogleGenAIRequestAttributes, - addGoogleGenAIResponseAttributes, defineIntegration, - extractGoogleGenAIRequestAttributes, getActiveSpan, - instrumentGoogleGenAIStream, - resolveAIRecordingOptions, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, - shouldEnableTruncation, spanToJSON, startInactiveSpan, } from '@sentry/core'; +import { resolveAIRecordingOptions, shouldEnableTruncation } from '../../ai/core/utils'; +import { addPrivateRequestAttributes, addResponseAttributes, extractRequestAttributes } from '../../ai/google-genai'; +import { instrumentStream } from '../../ai/google-genai/streaming'; +import type { GoogleGenAIOptions, GoogleGenAIResponse } from '../../ai/google-genai/types'; import { CHANNELS } from '../../orchestrion/channels'; import { bindTracingChannelToSpan } from '../../tracing-channel'; import { googleGenAiModuleNames } from '../../orchestrion/config/google-genai'; @@ -59,7 +57,7 @@ function instrumentGoogleGenai(options: GoogleGenAIOptions): void { beforeSpanEnd: (span, data) => { // Embeddings responses carry no content attributes. if (operation !== 'embeddings') { - addGoogleGenAIResponseAttributes( + addResponseAttributes( span, data.result as GoogleGenAIResponse, resolveAIRecordingOptions(options).recordOutputs, @@ -106,7 +104,7 @@ function createGenAiSpan( const { recordInputs } = resolveAIRecordingOptions(options); const enableTruncation = shouldEnableTruncation(options.enableTruncation); - const attributes = extractGoogleGenAIRequestAttributes(operation, params, data.self); + const attributes = extractRequestAttributes(operation, params, data.self); const model = (attributes[GEN_AI_REQUEST_MODEL] as string) || 'unknown'; attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = ORIGIN; @@ -117,7 +115,7 @@ function createGenAiSpan( }); if (recordInputs && params) { - addGoogleGenAIRequestAttributes(span, params, operation, enableTruncation); + addPrivateRequestAttributes(span, params, operation, enableTruncation); } return span; @@ -131,7 +129,7 @@ function isAsyncIterable(value: unknown): value is AsyncIterableStream { /** * Only the streaming methods (`generateContentStream`/`sendMessageStream`) resolve to an async iterable. - * For a stream we patch `result[Symbol.asyncIterator]` in place so `instrumentGoogleGenAIStream` ends the + * For a stream we patch `result[Symbol.asyncIterator]` in place so `instrumentStream` ends the * span when iteration finishes. */ function wrapStreamResult(span: Span, data: GoogleGenAIChannelContext, options: GoogleGenAIOptions): boolean { @@ -142,7 +140,7 @@ function wrapStreamResult(span: Span, data: GoogleGenAIChannelContext, options: const { recordOutputs } = resolveAIRecordingOptions(options); const iterate = result[Symbol.asyncIterator].bind(result); - const instrumented = instrumentGoogleGenAIStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false); + const instrumented = instrumentStream({ [Symbol.asyncIterator]: iterate }, span, recordOutputs ?? false); result[Symbol.asyncIterator] = () => instrumented; return true; diff --git a/packages/server-utils/src/integrations/tracing-channel/langchain.ts b/packages/server-utils/src/integrations/tracing-channel/langchain.ts index 3a0b05321299..e00a2977ed59 100644 --- a/packages/server-utils/src/integrations/tracing-channel/langchain.ts +++ b/packages/server-utils/src/integrations/tracing-channel/langchain.ts @@ -6,11 +6,11 @@ import { _INTERNAL_skipAiProviderWrapping, createLangChainCallbackHandler, defineIntegration, - GOOGLE_GENAI_INTEGRATION_NAME, LANGCHAIN_INTEGRATION_NAME, startInactiveSpan, } from '@sentry/core'; import { ANTHROPIC_AI_INTEGRATION_NAME } from '../../ai/anthropic-ai/constants'; +import { GOOGLE_GENAI_INTEGRATION_NAME } from '../../ai/google-genai/constants'; import { OPENAI_INTEGRATION_NAME } from '../../ai/openai/constants'; import { CHANNELS } from '../../orchestrion/channels'; import { langchainEmbeddingsChannels } from '../../orchestrion/config/langchain'; diff --git a/packages/core/test/lib/utils/google-genai-utils.test.ts b/packages/server-utils/test/ai/lib/utils/google-genai-utils.test.ts similarity index 92% rename from packages/core/test/lib/utils/google-genai-utils.test.ts rename to packages/server-utils/test/ai/lib/utils/google-genai-utils.test.ts index 93d7750994f1..15a63c86df68 100644 --- a/packages/core/test/lib/utils/google-genai-utils.test.ts +++ b/packages/server-utils/test/ai/lib/utils/google-genai-utils.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import type { ContentListUnion } from '../../../src/tracing/google-genai/utils'; -import { contentUnionToMessages } from '../../../src/tracing/google-genai/utils'; +import type { ContentListUnion } from '../../../../src/ai/google-genai/utils'; +import { contentUnionToMessages } from '../../../../src/ai/google-genai/utils'; describe('convert google-genai messages to consistent message', () => { it('converts strings to messages', () => { diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index 880df4543286..f92158288162 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -74,7 +74,6 @@ export { // eslint-disable-next-line typescript/no-deprecated inboundFiltersIntegration, instrumentStateGraph, - instrumentGoogleGenAIClient, eventFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, @@ -106,7 +105,11 @@ export { withStreamedSpan, spanStreamingIntegration, } from '@sentry/core'; -export { instrumentOpenAiClient, instrumentAnthropicAiClient } from '@sentry/server-utils/no-diagnostic-channels'; +export { + instrumentOpenAiClient, + instrumentAnthropicAiClient, + instrumentGoogleGenAIClient, +} from '@sentry/server-utils/no-diagnostic-channels'; export { VercelEdgeClient } from './client'; export { getDefaultIntegrations, init } from './sdk';