Skip to content

Commit 84075b2

Browse files
lforstAbhiPrasad
authored andcommitted
ref(serverless): Do not throw on flush error (#5090)
1 parent 6069b15 commit 84075b2

File tree

7 files changed

+55
-56
lines changed

7 files changed

+55
-56
lines changed

MIGRATION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ For our efforts to reduce bundle size of the SDK we had to remove and refactor p
340340
- Remove `SDK_NAME` export from `@sentry/browser`, `@sentry/node`, `@sentry/tracing` and `@sentry/vue` packages.
341341
- Removed `eventStatusFromHttpCode` to save on bundle size.
342342
- Replace `BrowserTracing` `maxTransactionDuration` option with `finalTimeout` option
343+
- Removed `ignoreSentryErrors` option from AWS lambda SDK. Errors originating from the SDK will now *always* be caught internally.
343344

344345
## Sentry Angular SDK Changes
345346

packages/serverless/src/awslambda.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '@sentry/node';
1212
import { extractTraceparentData } from '@sentry/tracing';
1313
import { Integration } from '@sentry/types';
14-
import { isString, logger, SentryError } from '@sentry/utils';
14+
import { isString, logger } from '@sentry/utils';
1515
// 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
1616
// eslint-disable-next-line import/no-unresolved
1717
import { Context, Handler } from 'aws-lambda';
@@ -54,7 +54,6 @@ export interface WrapperOptions {
5454
* @default false
5555
*/
5656
captureAllSettledReasons: boolean;
57-
ignoreSentryErrors: boolean;
5857
}
5958

6059
export const defaultIntegrations: Integration[] = [...Sentry.defaultIntegrations, new AWSServices({ optional: true })];
@@ -226,7 +225,6 @@ export function wrapHandler<TEvent, TResult>(
226225
captureTimeoutWarning: true,
227226
timeoutWarningLimit: 500,
228227
captureAllSettledReasons: false,
229-
ignoreSentryErrors: true,
230228
...wrapOptions,
231229
};
232230
let timeoutWarningTimer: NodeJS.Timeout;
@@ -318,11 +316,7 @@ export function wrapHandler<TEvent, TResult>(
318316
transaction.finish();
319317
hub.popScope();
320318
await flush(options.flushTimeout).catch(e => {
321-
if (options.ignoreSentryErrors && e instanceof SentryError) {
322-
IS_DEBUG_BUILD && logger.error(e);
323-
return;
324-
}
325-
throw e;
319+
IS_DEBUG_BUILD && logger.error(e);
326320
});
327321
}
328322
return rv;

packages/serverless/src/gcpfunction/cloud_events.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ function _wrapCloudEventFunction(
6161
transaction.finish();
6262

6363
void flush(options.flushTimeout)
64-
.then(() => {
65-
callback(...args);
66-
})
6764
.then(null, e => {
6865
IS_DEBUG_BUILD && logger.error(e);
66+
})
67+
.then(() => {
68+
callback(...args);
6969
});
7070
});
7171

packages/serverless/src/gcpfunction/events.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ function _wrapEventFunction(
5656
transaction.finish();
5757

5858
void flush(options.flushTimeout)
59-
.then(() => {
60-
callback(...args);
61-
})
6259
.then(null, e => {
6360
IS_DEBUG_BUILD && logger.error(e);
61+
})
62+
.then(() => {
63+
callback(...args);
6464
});
6565
});
6666

packages/serverless/src/gcpfunction/http.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial<HttpFunctionWr
9191
transaction.finish();
9292

9393
void flush(options.flushTimeout)
94-
.then(() => {
95-
_end.call(this, chunk, encoding, cb);
96-
})
9794
.then(null, e => {
9895
IS_DEBUG_BUILD && logger.error(e);
96+
})
97+
.then(() => {
98+
_end.call(this, chunk, encoding, cb);
9999
});
100100
};
101101

packages/serverless/test/awslambda.test.ts

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { SentryError } from '@sentry/utils';
21
// 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
32
// eslint-disable-next-line import/no-unresolved
43
import { Callback, Handler } from 'aws-lambda';
@@ -178,44 +177,6 @@ describe('AWSLambda', () => {
178177
expect(Sentry.captureException).toHaveBeenNthCalledWith(2, error2);
179178
expect(Sentry.captureException).toBeCalledTimes(2);
180179
});
181-
182-
test('ignoreSentryErrors - with successful handler', async () => {
183-
const sentryError = new SentryError('HTTP Error (429)');
184-
jest.spyOn(Sentry, 'flush').mockRejectedValueOnce(sentryError);
185-
186-
const handledError = new Error('handled error, and we want to monitor it');
187-
const expectedSuccessStatus = { status: 'success', reason: 'we handled error, so success' };
188-
const handler = () => {
189-
Sentry.captureException(handledError);
190-
return Promise.resolve(expectedSuccessStatus);
191-
};
192-
const wrappedHandlerWithoutIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: false });
193-
const wrappedHandlerWithIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: true });
194-
195-
await expect(wrappedHandlerWithoutIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow(
196-
sentryError,
197-
);
198-
await expect(wrappedHandlerWithIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).resolves.toBe(
199-
expectedSuccessStatus,
200-
);
201-
});
202-
203-
test('ignoreSentryErrors - with failed handler', async () => {
204-
const sentryError = new SentryError('HTTP Error (429)');
205-
jest.spyOn(Sentry, 'flush').mockRejectedValueOnce(sentryError);
206-
207-
const criticalUnhandledError = new Error('critical unhandled error ');
208-
const handler = () => Promise.reject(criticalUnhandledError);
209-
const wrappedHandlerWithoutIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: false });
210-
const wrappedHandlerWithIgnoringSentryErrors = wrapHandler(handler, { ignoreSentryErrors: true });
211-
212-
await expect(wrappedHandlerWithoutIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow(
213-
sentryError,
214-
);
215-
await expect(wrappedHandlerWithIgnoringSentryErrors(fakeEvent, fakeContext, fakeCallback)).rejects.toThrow(
216-
criticalUnhandledError,
217-
);
218-
});
219180
});
220181

221182
describe('wrapHandler() on sync handler', () => {
@@ -345,6 +306,21 @@ describe('AWSLambda', () => {
345306
expect(Sentry.flush).toBeCalled();
346307
}
347308
});
309+
310+
test('should not throw when flush rejects', async () => {
311+
const handler: Handler = async () => {
312+
// Friendly handler with no errors :)
313+
return 'some string';
314+
};
315+
316+
const wrappedHandler = wrapHandler(handler);
317+
318+
jest.spyOn(Sentry, 'flush').mockImplementationOnce(async () => {
319+
throw new Error();
320+
});
321+
322+
await expect(wrappedHandler(fakeEvent, fakeContext, fakeCallback)).resolves.toBe('some string');
323+
});
348324
});
349325

350326
describe('wrapHandler() on async handler with a callback method (aka incorrect usage)', () => {

packages/serverless/test/gcpfunction.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,34 @@ describe('GCPFunction', () => {
148148
expect(Sentry.fakeTransaction.finish).toBeCalled();
149149
expect(Sentry.flush).toBeCalled();
150150
});
151+
152+
test('should not throw when flush rejects', async () => {
153+
expect.assertions(2);
154+
155+
const handler: HttpFunction = async (_req, res) => {
156+
res.statusCode = 200;
157+
res.end();
158+
};
159+
160+
const wrappedHandler = wrapHttpFunction(handler);
161+
162+
const request = {
163+
method: 'POST',
164+
url: '/path?q=query',
165+
headers: { host: 'hostname', 'content-type': 'application/json' },
166+
body: { foo: 'bar' },
167+
} as Request;
168+
169+
const mockEnd = jest.fn();
170+
const response = { end: mockEnd } as unknown as Response;
171+
172+
jest.spyOn(Sentry, 'flush').mockImplementationOnce(async () => {
173+
throw new Error();
174+
});
175+
176+
await expect(wrappedHandler(request, response)).resolves.toBeUndefined();
177+
expect(mockEnd).toHaveBeenCalledTimes(1);
178+
});
151179
});
152180

153181
test('wrapHttpFunction request data', async () => {

0 commit comments

Comments
 (0)