diff --git a/packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts b/packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts index 99fd2c546dd2..a10a01b3debf 100644 --- a/packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts @@ -5,7 +5,7 @@ import { InstrumentationNodeModuleDefinition, } from '@opentelemetry/instrumentation'; import type { AnthropicAiClient, AnthropicAiOptions, Integration } from '@sentry/core'; -import { ANTHROPIC_AI_INTEGRATION_NAME, getCurrentScope, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core'; +import { ANTHROPIC_AI_INTEGRATION_NAME, getClient, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core'; const supportedVersions = ['>=0.19.2 <1.0.0']; @@ -61,10 +61,10 @@ export class SentryAnthropicAiInstrumentation extends InstrumentationBase(ANTHROPIC_AI_INTEGRATION_NAME); + const client = getClient(); + const integration = client?.getIntegrationByName(ANTHROPIC_AI_INTEGRATION_NAME); const integrationOpts = integration?.options; - const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii); + const defaultPii = Boolean(client?.getOptions().sendDefaultPii); const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii); diff --git a/packages/node/src/integrations/tracing/openai/instrumentation.ts b/packages/node/src/integrations/tracing/openai/instrumentation.ts index 76385009f5ba..23df5bb66c35 100644 --- a/packages/node/src/integrations/tracing/openai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/openai/instrumentation.ts @@ -5,7 +5,7 @@ import { InstrumentationNodeModuleDefinition, } from '@opentelemetry/instrumentation'; import type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core'; -import { getCurrentScope, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core'; +import { getClient, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core'; const supportedVersions = ['>=4.0.0 <6']; @@ -57,10 +57,10 @@ export class SentryOpenAiInstrumentation extends InstrumentationBase(OPENAI_INTEGRATION_NAME); + const client = getClient(); + const integration = client?.getIntegrationByName(OPENAI_INTEGRATION_NAME); const integrationOpts = integration?.options; - const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii); + const defaultPii = Boolean(client?.getOptions().sendDefaultPii); const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii); diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index bf32d417c42e..cf2b0d7eeadc 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -7,7 +7,7 @@ import { addNonEnumerableProperty, captureException, getActiveSpan, - getCurrentScope, + getClient, handleCallbackErrors, isThenable, SDK_VERSION, @@ -212,57 +212,58 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { this._callbacks.forEach(callback => callback()); this._callbacks = []; - function generatePatch(originalMethod: (...args: MethodArgs) => unknown) { - return (...args: MethodArgs) => { - const existingExperimentalTelemetry = args[0].experimental_telemetry || {}; - const isEnabled = existingExperimentalTelemetry.isEnabled; - - const client = getCurrentScope().getClient(); - const integration = client?.getIntegrationByName(INTEGRATION_NAME); - const integrationOptions = integration?.options; - const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false; - - const { recordInputs, recordOutputs } = determineRecordingSettings( - integrationOptions, - existingExperimentalTelemetry, - isEnabled, - shouldRecordInputsAndOutputs, - ); - - args[0].experimental_telemetry = { - ...existingExperimentalTelemetry, - isEnabled: isEnabled !== undefined ? isEnabled : true, - recordInputs, - recordOutputs, - }; - - return handleCallbackErrors( - () => { - // @ts-expect-error we know that the method exists - const result = originalMethod.apply(this, args); - - if (isThenable(result)) { - // check for tool errors when the promise resolves, keep the original promise identity - result.then(checkResultForToolErrors, () => {}); + const generatePatch = unknown>(originalMethod: T): T => { + return new Proxy(originalMethod, { + apply: (target, thisArg, args: MethodArgs) => { + const existingExperimentalTelemetry = args[0].experimental_telemetry || {}; + const isEnabled = existingExperimentalTelemetry.isEnabled; + + const client = getClient(); + const integration = client?.getIntegrationByName(INTEGRATION_NAME); + const integrationOptions = integration?.options; + const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false; + + const { recordInputs, recordOutputs } = determineRecordingSettings( + integrationOptions, + existingExperimentalTelemetry, + isEnabled, + shouldRecordInputsAndOutputs, + ); + + args[0].experimental_telemetry = { + ...existingExperimentalTelemetry, + isEnabled: isEnabled !== undefined ? isEnabled : true, + recordInputs, + recordOutputs, + }; + + return handleCallbackErrors( + () => { + const result = Reflect.apply(target, thisArg, args); + + if (isThenable(result)) { + // check for tool errors when the promise resolves, keep the original promise identity + result.then(checkResultForToolErrors, () => {}); + return result; + } + + // check for tool errors when the result is synchronous + checkResultForToolErrors(result); return result; - } - - // check for tool errors when the result is synchronous - checkResultForToolErrors(result); - return result; - }, - error => { - // This error bubbles up to unhandledrejection handler (if not handled before), - // where we do not know the active span anymore - // So to circumvent this, we set the active span on the error object - // which is picked up by the unhandledrejection handler - if (error && typeof error === 'object') { - addNonEnumerableProperty(error, '_sentry_active_span', getActiveSpan()); - } - }, - ); - }; - } + }, + error => { + // This error bubbles up to unhandledrejection handler (if not handled before), + // where we do not know the active span anymore + // So to circumvent this, we set the active span on the error object + // which is picked up by the unhandledrejection handler + if (error && typeof error === 'object') { + addNonEnumerableProperty(error, '_sentry_active_span', getActiveSpan()); + } + }, + ); + }, + }); + }; // Is this an ESM module? // https://tc39.es/ecma262/#sec-module-namespace-objects