So far Sentry doesn’t have integration directly with NestJS, so let’s see how to make the integration with NestJS Exception Filters. Worth mentioning that we will use some specific configurations for Express, the default HTTP server Nest.js uses under the hood. If you use Fastify you will need some tweaks in the configuration.
Select Node.js and complete the form. If they ask if you use a framework on the project creation skip it.
After creating the project, Sentry will show you the configuration details for your project.
For the minimum basic configuration, we don’t need Performance Monitoring or Profiling, so let’s install only @sentry/node
npm install @sentry/node
Now let’s create the src/sentry.filter.ts
. We are generating a generic ExceptionFilter that captures any type of Exception because the @Catch()
decorator is empty. Also, we are extending it from BaseExceptionFilter
, which is Nest's default class for handling exceptions. Therefore, we will not change the original behavior when an exception is thrown because the method of the parent class that handles exceptions is called at the end of the code: super.handleUnknownError(exception, host);
. Also notice we are implementing only the handleUnknownError
method, this way we won’t pass to Sentry exceptions that are handled correctly in our system (BadRequest
, NotAuthorized
, etc.).
import { Catch, ArgumentsHost, HttpServer } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
import * as Sentry from '@sentry/node';
@Catch()
export class SentryFilter extends BaseExceptionFilter {
handleUnknownError(exception: unknown, host: ArgumentsHost, applicationRef: HttpServer): void {
// If you want to avoid sending errors when running in local environment
// you can wrap the captureException in
// if (host.switchToHttp().getRequest().hostname !== 'localhost')
Sentry.captureException(exception);
super.handleUnknownError(exception, host, applicationRef);
}
}
Finally, let’s include in your app boostrap()
(normally is in src/main.ts
) the Sentry initialization, and an extra configuration to add the request object in the captured exception as is mentioned in the Sentry Express guide
import { NestFactory, HttpAdapterHost } from '@nestjs/core';
import * as Sentry from '@sentry/node';
import { SentryFilter } from './sentry.filter';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Sentry initialization
Sentry.init({
environment: process.env.ENVIRONMENT, // Capture your environment
dsn: '<https://[email protected]/xxx>' // Put your DSN link
});
// The request handler must be the first middleware on the app
app.use(Sentry.Handlers.requestHandler());
// ... your other middlewares
// Import the filter globally, capturing all exceptions on all routes
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new SentryFilter(httpAdapter));
// The error handler must be before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler());
await app.listen(process.env.PORT || 8080);
}
Configuration completed 🎉🎉.
Now you just need to generate an exception in any part of your application and take a look in Sentry issues page. Your issue should look similar to this
Notice that Sentry is capturing correctly all the information from the request object (user email, user ID, url, etc.).