Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c0f0375

Browse files
authored
fix(node): Fix this context for vercel AI instrumentation (#17681)
Noticed while working on #17679, we incorrectly changed the `this` context here (which is also why TS complained). I rewrote this to a proxy which should keep the context properly.
1 parent 4756112 commit c0f0375

File tree

3 files changed

+60
-59
lines changed

3 files changed

+60
-59
lines changed

‎packages/node/src/integrations/tracing/anthropic-ai/instrumentation.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
InstrumentationNodeModuleDefinition,
66
} from '@opentelemetry/instrumentation';
77
import type { AnthropicAiClient, AnthropicAiOptions, Integration } from '@sentry/core';
8-
import { ANTHROPIC_AI_INTEGRATION_NAME, getCurrentScope, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core';
8+
import { ANTHROPIC_AI_INTEGRATION_NAME, getClient, instrumentAnthropicAiClient, SDK_VERSION } from '@sentry/core';
99

1010
const supportedVersions = ['>=0.19.2 <1.0.0'];
1111

@@ -61,10 +61,10 @@ export class SentryAnthropicAiInstrumentation extends InstrumentationBase<Instru
6161

6262
const WrappedAnthropic = function (this: unknown, ...args: unknown[]) {
6363
const instance = Reflect.construct(Original, args);
64-
const scopeClient = getCurrentScope().getClient();
65-
const integration = scopeClient?.getIntegrationByName<AnthropicAiIntegration>(ANTHROPIC_AI_INTEGRATION_NAME);
64+
const client = getClient();
65+
const integration = client?.getIntegrationByName<AnthropicAiIntegration>(ANTHROPIC_AI_INTEGRATION_NAME);
6666
const integrationOpts = integration?.options;
67-
const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);
67+
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
6868

6969
const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
7070

‎packages/node/src/integrations/tracing/openai/instrumentation.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
InstrumentationNodeModuleDefinition,
66
} from '@opentelemetry/instrumentation';
77
import type { Integration, OpenAiClient, OpenAiOptions } from '@sentry/core';
8-
import { getCurrentScope, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';
8+
import { getClient, instrumentOpenAiClient, OPENAI_INTEGRATION_NAME, SDK_VERSION } from '@sentry/core';
99

1010
const supportedVersions = ['>=4.0.0 <6'];
1111

@@ -57,10 +57,10 @@ export class SentryOpenAiInstrumentation extends InstrumentationBase<Instrumenta
5757

5858
const WrappedOpenAI = function (this: unknown, ...args: unknown[]) {
5959
const instance = Reflect.construct(Original, args);
60-
const scopeClient = getCurrentScope().getClient();
61-
const integration = scopeClient?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);
60+
const client = getClient();
61+
const integration = client?.getIntegrationByName<OpenAiIntegration>(OPENAI_INTEGRATION_NAME);
6262
const integrationOpts = integration?.options;
63-
const defaultPii = Boolean(scopeClient?.getOptions().sendDefaultPii);
63+
const defaultPii = Boolean(client?.getOptions().sendDefaultPii);
6464

6565
const { recordInputs, recordOutputs } = determineRecordingSettings(integrationOpts, defaultPii);
6666

‎packages/node/src/integrations/tracing/vercelai/instrumentation.ts‎

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
addNonEnumerableProperty,
88
captureException,
99
getActiveSpan,
10-
getCurrentScope,
10+
getClient,
1111
handleCallbackErrors,
1212
isThenable,
1313
SDK_VERSION,
@@ -212,57 +212,58 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase {
212212
this._callbacks.forEach(callback => callback());
213213
this._callbacks = [];
214214

215-
function generatePatch(originalMethod: (...args: MethodArgs) => unknown) {
216-
return (...args: MethodArgs) => {
217-
const existingExperimentalTelemetry = args[0].experimental_telemetry || {};
218-
const isEnabled = existingExperimentalTelemetry.isEnabled;
219-
220-
const client = getCurrentScope().getClient();
221-
const integration = client?.getIntegrationByName<VercelAiIntegration>(INTEGRATION_NAME);
222-
const integrationOptions = integration?.options;
223-
const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false;
224-
225-
const { recordInputs, recordOutputs } = determineRecordingSettings(
226-
integrationOptions,
227-
existingExperimentalTelemetry,
228-
isEnabled,
229-
shouldRecordInputsAndOutputs,
230-
);
231-
232-
args[0].experimental_telemetry = {
233-
...existingExperimentalTelemetry,
234-
isEnabled: isEnabled !== undefined ? isEnabled : true,
235-
recordInputs,
236-
recordOutputs,
237-
};
238-
239-
return handleCallbackErrors(
240-
() => {
241-
// @ts-expect-error we know that the method exists
242-
const result = originalMethod.apply(this, args);
243-
244-
if (isThenable(result)) {
245-
// check for tool errors when the promise resolves, keep the original promise identity
246-
result.then(checkResultForToolErrors, () => {});
215+
const generatePatch = <T extends (...args: MethodArgs) => unknown>(originalMethod: T): T => {
216+
return new Proxy(originalMethod, {
217+
apply: (target, thisArg, args: MethodArgs) => {
218+
const existingExperimentalTelemetry = args[0].experimental_telemetry || {};
219+
const isEnabled = existingExperimentalTelemetry.isEnabled;
220+
221+
const client = getClient();
222+
const integration = client?.getIntegrationByName<VercelAiIntegration>(INTEGRATION_NAME);
223+
const integrationOptions = integration?.options;
224+
const shouldRecordInputsAndOutputs = integration ? Boolean(client?.getOptions().sendDefaultPii) : false;
225+
226+
const { recordInputs, recordOutputs } = determineRecordingSettings(
227+
integrationOptions,
228+
existingExperimentalTelemetry,
229+
isEnabled,
230+
shouldRecordInputsAndOutputs,
231+
);
232+
233+
args[0].experimental_telemetry = {
234+
...existingExperimentalTelemetry,
235+
isEnabled: isEnabled !== undefined ? isEnabled : true,
236+
recordInputs,
237+
recordOutputs,
238+
};
239+
240+
return handleCallbackErrors(
241+
() => {
242+
const result = Reflect.apply(target, thisArg, args);
243+
244+
if (isThenable(result)) {
245+
// check for tool errors when the promise resolves, keep the original promise identity
246+
result.then(checkResultForToolErrors, () => {});
247+
return result;
248+
}
249+
250+
// check for tool errors when the result is synchronous
251+
checkResultForToolErrors(result);
247252
return result;
248-
}
249-
250-
// check for tool errors when the result is synchronous
251-
checkResultForToolErrors(result);
252-
return result;
253-
},
254-
error => {
255-
// This error bubbles up to unhandledrejection handler (if not handled before),
256-
// where we do not know the active span anymore
257-
// So to circumvent this, we set the active span on the error object
258-
// which is picked up by the unhandledrejection handler
259-
if (error && typeof error === 'object') {
260-
addNonEnumerableProperty(error, '_sentry_active_span', getActiveSpan());
261-
}
262-
},
263-
);
264-
};
265-
}
253+
},
254+
error => {
255+
// This error bubbles up to unhandledrejection handler (if not handled before),
256+
// where we do not know the active span anymore
257+
// So to circumvent this, we set the active span on the error object
258+
// which is picked up by the unhandledrejection handler
259+
if (error && typeof error === 'object') {
260+
addNonEnumerableProperty(error, '_sentry_active_span', getActiveSpan());
261+
}
262+
},
263+
);
264+
},
265+
});
266+
};
266267

267268
// Is this an ESM module?
268269
// https://tc39.es/ecma262/#sec-module-namespace-objects

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /