Skip to content

Commit 15f8378

Browse files
committed
fix(node): Fix this context for vercel AI instrumentation
1 parent 6e8e561 commit 15f8378

File tree

1 file changed

+51
-50
lines changed

1 file changed

+51
-50
lines changed

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

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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 = getCurrentScope().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)