Thank you for creating this.
I just wanted to warn that using this will cause pretty much all dependencies to be Request Scoped. I'd recommend not using this approach in production.
The Problem
By making the providers request-scoped, and injecting them to AppModule, API will instantiate new injection models for everything. This can slow down the API significantly.
Using request-scoped providers will have an impact on application performance. While Nest tries to cache as much metadata as possible, it will still have to create an instance of your class on each request. Hence, it will slow down your average response time and overall benchmarking result. Unless a provider must be request-scoped, it is strongly recommended that you use the default singleton scope.
The Solution
Use the context from the intercept
method of the Exception Filter to start the Sentry Transaction and set the span.
Extract the request from the SentryInterceptor
.
@Injectable()
export class SentryInterceptor implements NestInterceptor {
constructor(private sentryService: SentryService) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const span = this.sentryService.getRequestSpan(request, {
op: `Route Handler`,
});
return next.handle().pipe(
catchError((error) => {
// capture the error, you can filter out some errors here
Sentry.captureException(
error,
span.getTraceContext(),
);
// throw again the error
return throwError(() => error);
}),
finalize(() => {
span.finish();
}),
);
}
}
Modify the sentry.service
to accept the request as a parameter, and return the scope:
@Injectable()
export class SentryService {
public getRequestSpan(request: Request, spanContext: SpanContext) {
const { method, headers, url } = request;
const transaction = Sentry.startTransaction({
name: `Route: ${method} ${url}`,
op: 'transaction',
});
Sentry.getCurrentHub().configureScope((scope) => {
scope.setSpan(transaction);
scope.setContext('http', {
method,
url,
headers,
});
});
const span = Sentry.getCurrentHub().getScope().getSpan();
span.startChild(spanContext);
return span;
}
}