Skip to content

Commit

Permalink
feat(nestjs): Automatic instrumentation of nestjs interceptors after …
Browse files Browse the repository at this point in the history
…route execution (#13264)

Adding a span 'Interceptor - After Span' to improve instrumentation for
operations happening after the route execution is done. Tracking what
happens in individual interceptors after the route is hard, so currently
we create one span to trace everything that happens after the route is
executed.
  • Loading branch information
nicohrubec authored Aug 28, 2024
1 parent b192678 commit 7e9a038
Show file tree
Hide file tree
Showing 14 changed files with 794 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Controller, Get, Param, ParseIntPipe, UseFilters, UseGuards, UseInterceptors } from '@nestjs/common';
import { flush } from '@sentry/nestjs';
import { AppService } from './app.service';
import { AsyncInterceptor } from './async-example.interceptor';
import { ExampleInterceptor1 } from './example-1.interceptor';
import { ExampleInterceptor2 } from './example-2.interceptor';
import { ExampleExceptionGlobalFilter } from './example-global-filter.exception';
import { ExampleExceptionLocalFilter } from './example-local-filter.exception';
import { ExampleLocalFilter } from './example-local.filter';
import { ExampleGuard } from './example.guard';
import { ExampleInterceptor } from './example.interceptor';

@Controller()
@UseFilters(ExampleLocalFilter)
Expand All @@ -29,11 +31,17 @@ export class AppController {
}

@Get('test-interceptor-instrumentation')
@UseInterceptors(ExampleInterceptor)
@UseInterceptors(ExampleInterceptor1, ExampleInterceptor2)
testInterceptorInstrumentation() {
return this.appService.testSpan();
}

@Get('test-async-interceptor-instrumentation')
@UseInterceptors(AsyncInterceptor)
testAsyncInterceptorInstrumentation() {
return this.appService.testSpan();
}

@Get('test-pipe-instrumentation/:id')
testPipeInstrumentation(@Param('id', ParseIntPipe) id: number) {
return { value: id };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import * as Sentry from '@sentry/nestjs';
import { tap } from 'rxjs';

@Injectable()
export class AsyncInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
Sentry.startSpan({ name: 'test-async-interceptor-span' }, () => {});
return Promise.resolve(
next.handle().pipe(
tap(() => {
Sentry.startSpan({ name: 'test-async-interceptor-span-after-route' }, () => {});
}),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import * as Sentry from '@sentry/nestjs';
import { tap } from 'rxjs';

@Injectable()
export class ExampleInterceptor1 implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
Sentry.startSpan({ name: 'test-interceptor-span-1' }, () => {});
return next.handle().pipe(
tap(() => {
Sentry.startSpan({ name: 'test-interceptor-span-after-route' }, () => {});
}),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nes
import * as Sentry from '@sentry/nestjs';

@Injectable()
export class ExampleInterceptor implements NestInterceptor {
export class ExampleInterceptor2 implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
Sentry.startSpan({ name: 'test-interceptor-span' }, () => {});
Sentry.startSpan({ name: 'test-interceptor-span-2' }, () => {});
return next.handle().pipe();
}
}
Loading

0 comments on commit 7e9a038

Please sign in to comment.