diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 4d1df2d9fec9..31b91ed4811f 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -11,7 +11,7 @@ import { } from '@sentry/node'; import { extractTraceparentData } from '@sentry/tracing'; import { Integration } from '@sentry/types'; -import { isString, logger } from '@sentry/utils'; +import { isString, logger, SentryError } from '@sentry/utils'; // 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 // eslint-disable-next-line import/no-unresolved import { Context, Handler } from 'aws-lambda'; @@ -53,6 +53,7 @@ export interface WrapperOptions { * @default false */ captureAllSettledReasons: boolean; + ignoreSentryErrors: boolean; } export const defaultIntegrations: Integration[] = [...Sentry.defaultIntegrations, new AWSServices({ optional: true })]; @@ -224,6 +225,7 @@ export function wrapHandler( captureTimeoutWarning: true, timeoutWarningLimit: 500, captureAllSettledReasons: false, + ignoreSentryErrors: false, ...wrapOptions, }; let timeoutWarningTimer: NodeJS.Timeout; @@ -314,7 +316,13 @@ export function wrapHandler( clearTimeout(timeoutWarningTimer); transaction.finish(); hub.popScope(); - await flush(options.flushTimeout); + await flush(options.flushTimeout).catch(e => { + if (options.ignoreSentryErrors && e instanceof SentryError) { + logger.error(e); + return; + } + throw e; + }); } return rv; }; diff --git a/packages/serverless/test/awslambda.test.ts b/packages/serverless/test/awslambda.test.ts index a44f3281ba66..ab0c38d2f08a 100644 --- a/packages/serverless/test/awslambda.test.ts +++ b/packages/serverless/test/awslambda.test.ts @@ -1,3 +1,4 @@ +import { SentryError } from '@sentry/utils'; // 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 // eslint-disable-next-line import/no-unresolved import { Callback, Handler } from 'aws-lambda'; @@ -177,6 +178,44 @@ describe('AWSLambda', () => { expect(Sentry.captureException).toHaveBeenNthCalledWith(2, error2); expect(Sentry.captureException).toBeCalledTimes(2); }); + + test('ignoreSentryErrors - with successful handler', async () => { + const sentryError = new SentryError('HTTP Error (429)'); + jest.spyOn(Sentry, 'flush').mockRejectedValueOnce(sentryError); + + const handledError = new Error('handled error, and we want to monitor it'); + const expectedSuccessStatus = { status: 'success', reason: 'we handled error, so success' }; + const handler = () => { + Sentry.captureException(handledError); + return Promise.resolve(expectedSuccessStatus); + }; + const wrappedHandlerWithoutIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: false }); + const wrappedHandlerWithIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: true }); + + await expect(wrappedHandlerWithoutIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow( + sentryError, + ); + await expect(wrappedHandlerWithIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).resolves.toBe( + expectedSuccessStatus, + ); + }); + + test('ignoreSentryErrors - with failed handler', async () => { + const sentryError = new SentryError('HTTP Error (429)'); + jest.spyOn(Sentry, 'flush').mockRejectedValueOnce(sentryError); + + const criticalUnhandledError = new Error('critical unhandled error '); + const handler = () => Promise.reject(criticalUnhandledError); + const wrappedHandlerWithoutIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: false }); + const wrappedHandlerWithIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: true }); + + await expect(wrappedHandlerWithoutIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow( + sentryError, + ); + await expect(wrappedHandlerWithIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow( + criticalUnhandledError, + ); + }); }); describe('wrapHandler() on sync handler', () => {