|
7 | 7 | addNonEnumerableProperty,
|
8 | 8 | captureException,
|
9 | 9 | getActiveSpan,
|
10 |
| - getCurrentScope, |
| 10 | + getClient, |
11 | 11 | handleCallbackErrors,
|
12 | 12 | isThenable,
|
13 | 13 | SDK_VERSION,
|
@@ -212,57 +212,58 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase {
|
212 | 212 | this._callbacks.forEach(callback => callback());
|
213 | 213 | this._callbacks = [];
|
214 | 214 |
|
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); |
247 | 252 | 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 | + }; |
266 | 267 |
|
267 | 268 | // Is this an ESM module?
|
268 | 269 | // https://tc39.es/ecma262/#sec-module-namespace-objects
|
|
0 commit comments