Skip to content

Commit c6e1884

Browse files
authored
Merge branch 'develop' into timfish/test/cloudflare-integration-tests
2 parents f763100 + 7bc6bd0 commit c6e1884

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

packages/cloudflare/src/request.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ interface RequestHandlerWrapperOptions {
1818
options: CloudflareOptions;
1919
request: Request<unknown, IncomingRequestCfProperties<unknown>>;
2020
context: ExecutionContext;
21+
/**
22+
* If true, errors will be captured, rethrown and sent to Sentry.
23+
* Otherwise, errors are rethrown but not captured.
24+
*
25+
* You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.
26+
* This is primarily meant as an escape hatch for higher-level SDKs relying on additional error
27+
* capturing mechanisms where this wrapper captures errors too early or too generally.
28+
*
29+
* @default true
30+
*/
31+
captureErrors?: boolean;
2132
}
2233

2334
/**
@@ -28,7 +39,7 @@ export function wrapRequestHandler(
2839
handler: (...args: unknown[]) => Response | Promise<Response>,
2940
): Promise<Response> {
3041
return withIsolationScope(async isolationScope => {
31-
const { options, request } = wrapperOptions;
42+
const { options, request, captureErrors = true } = wrapperOptions;
3243

3344
// In certain situations, the passed context can become undefined.
3445
// For example, for Astro while prerendering pages at build time.
@@ -67,7 +78,9 @@ export function wrapRequestHandler(
6778
try {
6879
return await handler();
6980
} catch (e) {
70-
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
81+
if (captureErrors) {
82+
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
83+
}
7184
throw e;
7285
} finally {
7386
waitUntil?.(flush(2000));
@@ -91,7 +104,9 @@ export function wrapRequestHandler(
91104
setHttpStatus(span, res.status);
92105
return res;
93106
} catch (e) {
94-
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
107+
if (captureErrors) {
108+
captureException(e, { mechanism: { handled: false, type: 'cloudflare' } });
109+
}
95110
throw e;
96111
} finally {
97112
waitUntil?.(flush(2000));

packages/cloudflare/test/request.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,33 @@ describe('withSentry', () => {
212212

213213
expect(thrownError).toBe(error);
214214
});
215+
216+
test("doesn't capture errors if `captureErrors` is false", async () => {
217+
const captureExceptionSpy = vi.spyOn(SentryCore, 'captureException');
218+
const error = new Error('test');
219+
220+
expect(captureExceptionSpy).not.toHaveBeenCalled();
221+
let thrownError: Error | undefined;
222+
223+
try {
224+
await wrapRequestHandler(
225+
{
226+
options: MOCK_OPTIONS,
227+
request: new Request('https://example.com'),
228+
context: createMockExecutionContext(),
229+
captureErrors: false,
230+
},
231+
() => {
232+
throw error;
233+
},
234+
);
235+
} catch (e: any) {
236+
thrownError = e;
237+
}
238+
239+
expect(captureExceptionSpy).not.toHaveBeenCalled();
240+
expect(thrownError).toBe(error);
241+
});
215242
});
216243

217244
describe('tracing instrumentation', () => {

packages/react-router/README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44
</a>
55
</p>
66

7-
# Official Sentry SDK for React Router Framework (EXPERIMENTAL)
7+
# Official Sentry SDK for React Router Framework (BETA)
88

99
[![npm version](https://img.shields.io/npm/v/@sentry/react-router.svg)](https://www.npmjs.com/package/@sentry/react-router)
1010
[![npm dm](https://img.shields.io/npm/dm/@sentry/react-router.svg)](https://www.npmjs.com/package/@sentry/react-router)
1111
[![npm dt](https://img.shields.io/npm/dt/@sentry/react-router.svg)](https://www.npmjs.com/package/@sentry/react-router)
1212

13-
> [!WARNING]
14-
> This SDK is considered ⚠️ **experimental and in an alpha state**. It may experience breaking changes. Please reach out
15-
> on [GitHub](https://github.com/getsentry/sentry-javascript/issues/) if you have any feedback or concerns. This
16-
> SDK is for [React Router (framework)](https://reactrouter.com/start/framework/installation). If you're using [React Router (library)](https://reactrouter.com/start/library/installation) see our
13+
> This SDK is currently in beta. Beta features are still in progress and may have bugs. Please reach out on [GitHub](https://github.com/getsentry/sentry-javascript/issues/) if you have any feedback or concerns.
14+
> This SDK is for [React Router (framework)](https://reactrouter.com/start/framework/installation). If you're using [React Router (library)](https://reactrouter.com/start/library/installation) see our
1715
> [React SDK here](https://docs.sentry.io/platforms/javascript/guides/react/features/react-router/v7/).
1816
1917
## Links

packages/sveltekit/src/worker/cloudflare.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
3737
request: event.request as Request<unknown, IncomingRequestCfProperties<unknown>>,
3838
// @ts-expect-error This will exist in Cloudflare
3939
context: event.platform.context,
40+
// We don't want to capture errors here, as we want to capture them in the `sentryHandle` handler
41+
// where we can distinguish between redirects and actual errors.
42+
captureErrors: false,
4043
},
4144
() => resolve(event),
4245
);

packages/sveltekit/test/worker/cloudflare.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('initCloudflareSentryHandle', () => {
4545

4646
expect(SentryCloudflare.wrapRequestHandler).toHaveBeenCalledTimes(1);
4747
expect(SentryCloudflare.wrapRequestHandler).toHaveBeenCalledWith(
48-
{ options: expect.objectContaining({ dsn: options.dsn }), request, context },
48+
{ options: expect.objectContaining({ dsn: options.dsn }), request, context, captureErrors: false },
4949
expect.any(Function),
5050
);
5151

0 commit comments

Comments
 (0)