|
2 | 2 | import * as Sentry from '@sentry/node'; |
3 | 3 | import { captureException, captureMessage, flush, getCurrentHub, Scope, withScope } from '@sentry/node'; |
4 | 4 | import { extractTraceparentData } from '@sentry/tracing'; |
5 | | -import { Integration } from '@sentry/types'; |
| 5 | +import { CaptureContext,Integration } from '@sentry/types'; |
6 | 6 | import { baggageHeaderToDynamicSamplingContext, dsnFromString, dsnToString, isString, logger } from '@sentry/utils'; |
7 | 7 | // NOTE: I have no idea how to fix this right now, and don't want to waste more time, as it builds just fine — Kamil |
8 | 8 | // eslint-disable-next-line import/no-unresolved |
@@ -44,7 +44,15 @@ export interface WrapperOptions { |
44 | 44 | * The {@link wrapHandler} will not fail the lambda even if there are errors |
45 | 45 | * @default false |
46 | 46 | */ |
47 | | - captureAllSettledReasons: boolean; |
| 47 | + captureAllSettledReasons: boolean | { |
| 48 | + /** |
| 49 | + * Build {CaptureContext} according to the error reported. |
| 50 | + * @param event The original event. |
| 51 | + * @param reason The `reason` property of the promise rejection |
| 52 | + * @param allSettledResultIndex The {PromiseSettledResult} `index` |
| 53 | + */ |
| 54 | + buildContext?: (event: Parameters<Handler>[0], reason: PromiseSettledResult<unknown>['reason'], allSettledResultIndex: number) => CaptureContext; |
| 55 | + }; |
48 | 56 | } |
49 | 57 |
|
50 | 58 | export const defaultIntegrations: Integration[] = [...Sentry.defaultIntegrations, new AWSServices({ optional: true })]; |
@@ -119,24 +127,18 @@ function tryRequire<T>(taskRoot: string, subdir: string, mod: string): T { |
119 | 127 | // Node-style path |
120 | 128 | return require(require.resolve(mod, { paths: [taskRoot, subdir] })); |
121 | 129 | } |
| 130 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 131 | +type PromiseSettledResult<T, S extends 'rejected' | 'fulfilled' = 'rejected' | 'fulfilled'> = { status: S; reason?: any, value: T }; |
122 | 132 |
|
123 | 133 | /** */ |
124 | | -function isPromiseAllSettledResult<T>(result: T[]): boolean { |
125 | | - return result.every( |
126 | | - v => |
127 | | - Object.prototype.hasOwnProperty.call(v, 'status') && |
128 | | - (Object.prototype.hasOwnProperty.call(v, 'value') || Object.prototype.hasOwnProperty.call(v, 'reason')), |
129 | | - ); |
| 134 | +function isPromiseAllSettledResult<T>(result: unknown): result is PromiseSettledResult<T>[] { |
| 135 | + return Array.isArray(result) && result.every(v => isPromiseSettledResult(v)); |
130 | 136 | } |
131 | 137 |
|
132 | | -type PromiseSettledResult<T> = { status: 'rejected' | 'fulfilled'; reason?: T }; |
133 | | - |
134 | 138 | /** */ |
135 | | -function getRejectedReasons<T>(results: PromiseSettledResult<T>[]): T[] { |
136 | | - return results.reduce((rejected: T[], result) => { |
137 | | - if (result.status === 'rejected' && result.reason) rejected.push(result.reason); |
138 | | - return rejected; |
139 | | - }, []); |
| 139 | +function isPromiseSettledResult<T>(result: unknown): result is PromiseSettledResult<T> { |
| 140 | + return Object.prototype.hasOwnProperty.call(result, 'status') && |
| 141 | + (Object.prototype.hasOwnProperty.call(result, 'value') || Object.prototype.hasOwnProperty.call(result, 'reason')); |
140 | 142 | } |
141 | 143 |
|
142 | 144 | /** */ |
@@ -332,10 +334,14 @@ export function wrapHandler<TEvent, TResult>( |
332 | 334 | rv = await asyncHandler(event, context); |
333 | 335 |
|
334 | 336 | // We manage lambdas that use Promise.allSettled by capturing the errors of failed promises |
335 | | - if (options.captureAllSettledReasons && Array.isArray(rv) && isPromiseAllSettledResult(rv)) { |
336 | | - const reasons = getRejectedReasons(rv); |
337 | | - reasons.forEach(exception => { |
338 | | - captureException(exception); |
| 337 | + if (options.captureAllSettledReasons && isPromiseAllSettledResult(rv)) { |
| 338 | + rv.forEach((result, allSettledIndex) => { |
| 339 | + if(result.status === 'rejected') { |
| 340 | + const context = typeof options.captureAllSettledReasons !== 'boolean' |
| 341 | + ? options.captureAllSettledReasons.buildContext?.(event, result.reason, allSettledIndex) |
| 342 | + : undefined; |
| 343 | + captureException(result.reason, context); |
| 344 | + } |
339 | 345 | }); |
340 | 346 | } |
341 | 347 | } catch (e) { |
|
0 commit comments