-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
docs(js): Review and update Nest.js Quick Start guide #13497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
5427ba1
90ab40a
bb448d1
352fc65
3c54163
bd7fea7
17472be
3995e01
d443895
59e2357
6e33498
8f78185
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -27,4 +27,118 @@ You need to create a file named `instrument.js` that imports and initializes Sen | |||||
|
||||||
You need to require or import the `instrument.js` file before requiring any other modules in your application. This is necessary to ensure that Sentry can automatically instrument all modules in your application: | ||||||
|
||||||
<PlatformContent includePath="getting-started-use" /> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. h: the platform content here is important because this page is shown in various guides/frameworks. Right now, we'd show NestJS specific code in e.g. Node or Hono guides. I think we can take two possibe routes:
|
||||||
```javascript {filename: main.ts} | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
// Import this first! | ||||||
import "./instrument"; | ||||||
|
||||||
// Now import other modules | ||||||
import { NestFactory } from "@nestjs/core"; | ||||||
import { AppModule } from "./app.module"; | ||||||
|
||||||
async function bootstrap() { | ||||||
const app = await NestFactory.create(AppModule); | ||||||
await app.listen(3000); | ||||||
} | ||||||
|
||||||
bootstrap(); | ||||||
``` | ||||||
|
||||||
Afterwards, add the `SentryModule` as a root module to your main module: | ||||||
|
||||||
```javascript {filename: app.module.ts} {2, 8} | ||||||
import { Module } from "@nestjs/common"; | ||||||
import { SentryModule } from "@sentry/nestjs/setup"; | ||||||
import { AppController } from "./app.controller"; | ||||||
import { AppService } from "./app.service"; | ||||||
|
||||||
@Module({ | ||||||
imports: [ | ||||||
SentryModule.forRoot(), | ||||||
// ...other modules | ||||||
], | ||||||
controllers: [AppController], | ||||||
providers: [AppService], | ||||||
}) | ||||||
export class AppModule {} | ||||||
``` | ||||||
|
||||||
If you're using a global catch-all exception filter (which is either a filter registered with `app.useGlobalFilters()` or a filter registered in your app module providers annotated with a `@Catch()` decorator without arguments), add a `@SentryExceptionCaptured()` decorator to the filter's `catch()` method. | ||||||
This decorator will report all unexpected errors that are received by your global error filter to Sentry: | ||||||
|
||||||
```javascript {2, 6} | ||||||
import { Catch, ExceptionFilter } from '@nestjs/common'; | ||||||
import { SentryExceptionCaptured } from '@sentry/nestjs'; | ||||||
|
||||||
@Catch() | ||||||
export class YourCatchAllExceptionFilter implements ExceptionFilter { | ||||||
@SentryExceptionCaptured() | ||||||
catch(exception, host): void { | ||||||
// your implementation here | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
By default, only unhandled exceptions that are not caught by an error filter are reported to Sentry. | ||||||
`HttpException`s (including [derivatives](https://docs.nestjs.com/exception-filters#built-in-http-exceptions)) are also not captured by default because they mostly act as control flow vehicles. | ||||||
|
||||||
If you don't have a global catch-all exception filter, add the `SentryGlobalFilter` to the providers of your main module. | ||||||
This filter will report any unhandled errors that aren't caught by other error filters to Sentry. | ||||||
**Important:** The `SentryGlobalFilter` needs to be registered before any other exception filters. | ||||||
|
||||||
```javascript {3, 9} | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
import { Module } from "@nestjs/common"; | ||||||
import { APP_FILTER } from "@nestjs/core"; | ||||||
import { SentryGlobalFilter } from "@sentry/nestjs/setup"; | ||||||
|
||||||
@Module({ | ||||||
providers: [ | ||||||
{ | ||||||
provide: APP_FILTER, | ||||||
useClass: SentryGlobalFilter, | ||||||
}, | ||||||
// ..other providers | ||||||
], | ||||||
}) | ||||||
export class AppModule {} | ||||||
``` | ||||||
|
||||||
<Expandable title="Using Microservices?"> | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
If you are using `@nestjs/microservices` make sure to handle errors in RPC contexts correctly by providing your own `RpcExceptionFilter` (see https://docs.nestjs.com/microservices/exception-filters). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC we generally prefer "you're" over "you are" (but again, feel free to disregard, no strong opinions)
Suggested change
|
||||||
`SentryGlobalFilter` in a [hybrid application](https://docs.nestjs.com/faq/hybrid-application) does not extend `BaseRpcExceptionFilter` since this depends on `@nestjs/microservices`. | ||||||
|
||||||
Use `Sentry.captureException(exception)` in your custom filter in case you want to send these errors to Sentry: | ||||||
|
||||||
```typescript | ||||||
import { Catch, RpcExceptionFilter, ArgumentsHost } from "@nestjs/common"; | ||||||
import { Observable, throwError } from "rxjs"; | ||||||
import { RpcException } from "@nestjs/microservices"; | ||||||
import * as Sentry from "@sentry/nestjs"; | ||||||
|
||||||
@Catch(RpcException) | ||||||
export class ExceptionFilter implements RpcExceptionFilter<RpcException> { | ||||||
catch(exception: RpcException, host: ArgumentsHost): Observable<any> { | ||||||
Sentry.captureException(exception); // optional | ||||||
return throwError(() => exception.getError()); | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
</Expandable> | ||||||
|
||||||
If you have error filters for specific types of exceptions (for example `@Catch(HttpException)`, or any other `@Catch(...)` with arguments) and you want to capture errors caught by these filters, capture the errors in the `catch()` handler with `Sentry.captureException()`: | ||||||
|
||||||
```javascript {9} | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
import { ArgumentsHost, BadRequestException, Catch } from '@nestjs/common'; | ||||||
import { BaseExceptionFilter } from '@nestjs/core'; | ||||||
import { ExampleException } from './example.exception'; | ||||||
import * as Sentry from '@sentry/nestjs'; | ||||||
|
||||||
@Catch(ExampleException) | ||||||
export class ExampleExceptionFilter extends BaseExceptionFilter { | ||||||
catch(exception: unknown, host: ArgumentsHost) { | ||||||
Sentry.captureException(exception); | ||||||
return super.catch(new BadRequestException(exception.message), host) | ||||||
} | ||||||
} | ||||||
``` |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -14,7 +14,7 @@ async function bootstrap() { | |||||
bootstrap(); | ||||||
``` | ||||||
|
||||||
Afterwards, add the `SentryModule` as a root module to your main module: | ||||||
Afterward, add the `SentryModule` as a root module to your main module: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think? 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both forms are correct, although the variant with “s” is used in British English and the one without in American English 👍 |
||||||
|
||||||
```javascript {filename: app.module.ts} {2, 8} | ||||||
import { Module } from "@nestjs/common"; | ||||||
|
@@ -33,28 +33,15 @@ import { AppService } from "./app.service"; | |||||
export class AppModule {} | ||||||
``` | ||||||
|
||||||
If you're using a global catch-all exception filter (which is either a filter registered with `app.useGlobalFilters()` or a filter registered in your app module providers annotated with a `@Catch()` decorator without arguments), add a `@SentryExceptionCaptured()` decorator to the filter's `catch()` method. | ||||||
This decorator will report all unexpected errors that are received by your global error filter to Sentry: | ||||||
By default, only unhandled exceptions that are not caught by an error filter are reported to Sentry. Additionally, `HttpException`s (including [derivatives](https://docs.nestjs.com/exception-filters#built-in-http-exceptions)) are not captured automatically as they mostly act as control flow vehicles. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we start with the Error Capturing topic. But then this only seems to be documented for CJS - I was wondering why we don't have this documented for ESM? Or is this not needed/possible? I don't see this as part of this PR -- we can address in a future issue/PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This sounds reasonable to me!
I think this should be the same for CJS and ESM. Or IOW, the filters require should be applied in the same way regardless of ESM/CJS
that also sounds reasonable :D |
||||||
|
||||||
```javascript {2, 6} | ||||||
import { Catch, ExceptionFilter } from '@nestjs/common'; | ||||||
import { SentryExceptionCaptured } from '@sentry/nestjs'; | ||||||
##### Basic Error Capture | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
@Catch() | ||||||
export class YourCatchAllExceptionFilter implements ExceptionFilter { | ||||||
@SentryExceptionCaptured() | ||||||
catch(exception, host): void { | ||||||
// your implementation here | ||||||
} | ||||||
} | ||||||
``` | ||||||
Add the `SentryGlobalFilter` to the providers of your main module. This filter will report any unhandled errors that aren't caught by other error filters to Sentry. | ||||||
|
||||||
By default, only unhandled exceptions that are not caught by an error filter are reported to Sentry. | ||||||
`HttpException`s (including [derivatives](https://docs.nestjs.com/exception-filters#built-in-http-exceptions)) are also not captured by default because they mostly act as control flow vehicles. | ||||||
|
||||||
If you don't have a global catch-all exception filter, add the `SentryGlobalFilter` to the providers of your main module. | ||||||
This filter will report any unhandled errors that aren't caught by other error filters to Sentry. | ||||||
**Important:** The `SentryGlobalFilter` needs to be registered before any other exception filters. | ||||||
<Alert level="warning" title="Important"> | ||||||
Make sure to register `SentryGlobalFilter` before any other exception filters. | ||||||
</Alert> | ||||||
|
||||||
```javascript {3, 9} | ||||||
import { Module } from "@nestjs/common"; | ||||||
|
@@ -73,45 +60,6 @@ import { SentryGlobalFilter } from "@sentry/nestjs/setup"; | |||||
export class AppModule {} | ||||||
``` | ||||||
|
||||||
<Expandable title="Using Microservices?"> | ||||||
|
||||||
If you are using `@nestjs/microservices` make sure to handle errors in RPC contexts correctly by providing your own `RpcExceptionFilter` (see https://docs.nestjs.com/microservices/exception-filters). | ||||||
`SentryGlobalFilter` in a [hybrid application](https://docs.nestjs.com/faq/hybrid-application) does not extend `BaseRpcExceptionFilter` since this depends on `@nestjs/microservices`. | ||||||
|
||||||
Use `Sentry.captureException(exception)` in your custom filter in case you want to send these errors to Sentry: | ||||||
|
||||||
```typescript | ||||||
import { Catch, RpcExceptionFilter, ArgumentsHost } from '@nestjs/common'; | ||||||
import { Observable, throwError } from 'rxjs'; | ||||||
import { RpcException } from '@nestjs/microservices'; | ||||||
import * as Sentry from '@sentry/nestjs'; | ||||||
|
||||||
@Catch(RpcException) | ||||||
export class ExceptionFilter implements RpcExceptionFilter<RpcException> { | ||||||
catch(exception: RpcException, host: ArgumentsHost): Observable<any> { | ||||||
Sentry.captureException(exception); // optional | ||||||
return throwError(() => exception.getError()); | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
|
||||||
</Expandable> | ||||||
|
||||||
##### Fine-Tuning Error Capture | ||||||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
If you have error filters for specific types of exceptions (for example `@Catch(HttpException)`, or any other `@Catch(...)` with arguments) and you want to capture errors caught by these filters, capture the errors in the `catch()` handler with `Sentry.captureException()`: | ||||||
|
||||||
```javascript {9} | ||||||
import { ArgumentsHost, BadRequestException, Catch } from '@nestjs/common'; | ||||||
import { BaseExceptionFilter } from '@nestjs/core'; | ||||||
import { ExampleException } from './example.exception'; | ||||||
import * as Sentry from '@sentry/nestjs'; | ||||||
|
||||||
@Catch(ExampleException) | ||||||
export class ExampleExceptionFilter extends BaseExceptionFilter { | ||||||
catch(exception: unknown, host: ArgumentsHost) { | ||||||
Sentry.captureException(exception); | ||||||
return super.catch(new BadRequestException(exception.message), host) | ||||||
} | ||||||
} | ||||||
``` | ||||||
For more precise control over error reporting in global catch-all exception filters, specific exception filters, or microservices, check out our [CommonJS installation documentation](/platforms/javascript/guides/nestjs/install/commonjs/). | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. m: I don't think we should link to the CJS guide for this. Either we find a place for it here, or we do something like we have in Angular or React where we explain the intricacies of the filters in a "NestJS Features -> Exception Filters" page. wdyt? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,44 @@ | ||
### Issues | ||
|
||
First, let's verify that Sentry captures errors and creates issues in your Sentry project. Add the following route to your application, which will call an undefined function, triggering an error that Sentry will capture: | ||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```javascript | ||
@Get("/debug-sentry") | ||
getError() { | ||
throw new Error("My first Sentry error!"); | ||
getError() { | ||
setTimeout(() => { | ||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try { | ||
foo(); | ||
} catch (e) { | ||
Sentry.captureException(e); | ||
} | ||
}, 99); | ||
} | ||
``` | ||
|
||
<OnboardingOption optionId="performance"> | ||
### Tracing | ||
|
||
To test your tracing configuration, update the previous code snippet by starting a performance trace to measure the time it takes for the execution of your code: | ||
|
||
```javascript | ||
@Get("/debug-sentry") | ||
getError() { | ||
Sentry.startSpan( | ||
{ | ||
op: "test", | ||
name: "My First Test Transaction", | ||
}, | ||
() => { | ||
setTimeout(() => { | ||
inventarSarah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try { | ||
foo(); | ||
} catch (e) { | ||
Sentry.captureException(e); | ||
} | ||
}, 99); | ||
}, | ||
); | ||
} | ||
``` | ||
|
||
</OnboardingOption> |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For NestJS-CommmonJS specifically, I don't think we should show ESM/CJS tabs here because later on we instruct users to
import "./instrument"
. Since Nest ships with TS, we can simply let users create aninstrument.ts
file. (cc @chargome - let me know if I'm missing something or this sounds unreasonable to you)I'm realizing that this is a common guide for various node platforms but it's quite confusing for NestJS I'd argue. So maybe it makes sense to create a Nest-specific version of it 🤔 In general, for the common guide, I don't think we should even show the ESM tab on the CommonJS installation page :)
also please see my other comment about nestjs-specific code in this page
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sounds reasonable to just use a ts file here 👍