Skip to content

Commit 538702e

Browse files
authored
feat(nestjs): Add alias @SentryExceptionCaptured for @WithSentry (#14322)
1 parent 43c7079 commit 538702e

File tree

7 files changed

+98
-90
lines changed

7 files changed

+98
-90
lines changed

dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/src/example-global.filter.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { ArgumentsHost, BadRequestException, Catch, ExceptionFilter } from '@nestjs/common';
2-
import { WithSentry } from '@sentry/nestjs';
2+
import { SentryExceptionCaptured } from '@sentry/nestjs';
33
import { Request, Response } from 'express';
44

55
@Catch()
66
export class ExampleWrappedGlobalFilter implements ExceptionFilter {
7-
@WithSentry()
7+
@SentryExceptionCaptured()
88
catch(exception: BadRequestException, host: ArgumentsHost): void {
99
const ctx = host.switchToHttp();
1010
const response = ctx.getResponse<Response>();

packages/nestjs/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,16 @@ export class AppModule {}
6969

7070
In case you are using a global catch-all exception filter (which is either a filter registered with
7171
`app.useGlobalFilters()` or a filter registered in your app module providers annotated with an empty `@Catch()`
72-
decorator), add a `@WithSentry()` decorator to the `catch()` method of this global error filter. This decorator will
73-
report all unexpected errors that are received by your global error filter to Sentry:
72+
decorator), add a `@SentryExceptionCaptured()` decorator to the `catch()` method of this global error filter. This
73+
decorator will report all unexpected errors that are received by your global error filter to Sentry:
7474

7575
```typescript
7676
import { Catch, ExceptionFilter } from '@nestjs/common';
7777
import { WithSentry } from '@sentry/nestjs';
7878

7979
@Catch()
8080
export class YourCatchAllExceptionFilter implements ExceptionFilter {
81-
@WithSentry()
81+
@SentryExceptionCaptured()
8282
catch(exception, host): void {
8383
// your implementation here
8484
}

packages/nestjs/src/decorators.ts

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { captureException } from '@sentry/core';
2+
import * as Sentry from '@sentry/node';
3+
import { startSpan } from '@sentry/node';
4+
import type { MonitorConfig } from '@sentry/types';
5+
import { isExpectedError } from './helpers';
6+
7+
/**
8+
* A decorator wrapping the native nest Cron decorator, sending check-ins to Sentry.
9+
*/
10+
export const SentryCron = (monitorSlug: string, monitorConfig?: MonitorConfig): MethodDecorator => {
11+
return (target: unknown, propertyKey, descriptor: PropertyDescriptor) => {
12+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13+
const originalMethod = descriptor.value as (...args: any[]) => Promise<any>;
14+
15+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
16+
descriptor.value = function (...args: any[]) {
17+
return Sentry.withMonitor(
18+
monitorSlug,
19+
() => {
20+
return originalMethod.apply(this, args);
21+
},
22+
monitorConfig,
23+
);
24+
};
25+
return descriptor;
26+
};
27+
};
28+
29+
/**
30+
* A decorator usable to wrap arbitrary functions with spans.
31+
*/
32+
export function SentryTraced(op: string = 'function') {
33+
return function (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) {
34+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
35+
const originalMethod = descriptor.value as (...args: any[]) => Promise<any> | any; // function can be sync or async
36+
37+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
38+
descriptor.value = function (...args: any[]) {
39+
return startSpan(
40+
{
41+
op: op,
42+
name: propertyKey,
43+
},
44+
() => {
45+
return originalMethod.apply(this, args);
46+
},
47+
);
48+
};
49+
50+
// preserve the original name on the decorated function
51+
Object.defineProperty(descriptor.value, 'name', {
52+
value: originalMethod.name,
53+
configurable: true,
54+
enumerable: true,
55+
writable: true,
56+
});
57+
58+
return descriptor;
59+
};
60+
}
61+
62+
/**
63+
* A decorator to wrap user-defined exception filters and add Sentry error reporting.
64+
*/
65+
export function SentryExceptionCaptured() {
66+
return function (target: unknown, propertyKey: string, descriptor: PropertyDescriptor) {
67+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
68+
const originalCatch = descriptor.value as (exception: unknown, host: unknown, ...args: any[]) => void;
69+
70+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
71+
descriptor.value = function (exception: unknown, host: unknown, ...args: any[]) {
72+
if (isExpectedError(exception)) {
73+
return originalCatch.apply(this, [exception, host, ...args]);
74+
}
75+
76+
captureException(exception);
77+
return originalCatch.apply(this, [exception, host, ...args]);
78+
};
79+
80+
return descriptor;
81+
};
82+
}
83+
84+
/**
85+
* A decorator to wrap user-defined exception filters and add Sentry error reporting.
86+
*/
87+
export const WithSentry = SentryExceptionCaptured;

packages/nestjs/src/decorators/sentry-cron.ts

-24
This file was deleted.

packages/nestjs/src/decorators/sentry-traced.ts

-34
This file was deleted.

packages/nestjs/src/decorators/with-sentry.ts

-24
This file was deleted.

packages/nestjs/src/index.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ export * from '@sentry/node';
22

33
export { init } from './sdk';
44

5-
export { SentryTraced } from './decorators/sentry-traced';
6-
export { SentryCron } from './decorators/sentry-cron';
7-
export { WithSentry } from './decorators/with-sentry';
5+
export {
6+
SentryTraced,
7+
SentryCron,
8+
WithSentry,
9+
SentryExceptionCaptured,
10+
} from './decorators';

0 commit comments

Comments
 (0)