|
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