I want to integrate sentry with nest.js + express but I just found raven version but that is deprecated. I follow the sentry docs for integrate with express but dont know how to handle the 'All controllers should live here' part.
const express = require('express');
const app = express();
const Sentry = require('@sentry/node');
Sentry.init({ dsn: 'https://[email protected]/1768434' });
// The request handler must be the first middleware on the app
app.use(Sentry.Handlers.requestHandler());
**// All controllers should live here
app.get('/', function rootHandler(req, res) {
res.end('Hello world!');
});**
// The error handler must be before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler());
// Optional fallthrough error handler
app.use(function onError(err, req, res, next) {
// The error id is attached to `res.sentry` to be returned
// and optionally displayed to the user for support.
res.statusCode = 500;
res.end(res.sentry + "\n");
});
app.listen(3000);
I just created a Sample Project on Github to answer this question:
https://github.com/ericjeker/nestjs-sentry-example
Below is a partial copy of the README file. Let me know if you have any questions.
Create Sentry module, service, and interceptor
$ nest g module sentry
$ nest g service sentry
$ nest g interceptor sentry/sentry
Create the SentryModule.forRoot()
method and add the Sentry.init(options)
in it.
Call the SentryModule.forRoot({...})
in the AppModule
and integrate with your preferred configuration (I use ConfigModule
and a .env
file).
Add the call to the Express requestHandler middleware in the AppModule.configure()
.
configure(consumer: MiddlewareConsumer): void {
consumer.apply(Sentry.Handlers.requestHandler()).forRoutes({
path: '*',
method: RequestMethod.ALL,
});
}
It is important to use that middleware otherwise the current Hub will be global and you will run into conflicts as Sentry creates a Hub by thread and Node.js is not multi-threaded.
We want to initialize the transaction in the constructor of the service. You can customize your main transaction there.
Note that because I inject the Express request, the service must be request scoped. You can read more about that here.
@Injectable({ scope: Scope.REQUEST })
export class SentryService {
constructor(@Inject(REQUEST) private request: Request) {
// ... etc ...
}
}
The SentryInterceptor
will capture the exception and finish the transaction. Please also
note that it must be request scoped as we inject the SentryService
:
@Injectable({ scope: Scope.REQUEST })
export class SentryInterceptor implements NestInterceptor {
constructor(private sentryService: SentryService) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// ... etc ...
}
}
As an example, I added a span. This is not necessary, but it will just make the trace nicer in the performance viewer of Sentry.
You can add more spans anywhere in your application simply by injecting the SentryService
and calling startChild
or by simply calling the startChild
method of the current span.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With