Good Code
The good version puts request timing in an interceptor that wraps the controller call. The controller can focus on returning reviews.
Lesson 06
Use interceptors for cross-cutting response mapping, timing, and logging around controller method execution.
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from "@nestjs/common";
import { tap } from "rxjs";
@Injectable()
export class RequestTimingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
const startedAt = Date.now();
// The interceptor measures every decorated route the same way.
return next.handle().pipe(
tap(() => {
const request = context.switchToHttp().getRequest();
logger.info({ path: request.url, durationMs: Date.now() - startedAt });
}),
);
}
}import { Controller, Get } from "@nestjs/common";
@Controller("reviews")
export class ReviewsController {
@Get()
async findAll() {
// Repeating timing code in each route invites drift.
const startedAt = Date.now();
const result = await this.reviews.findAll();
logger.info({ durationMs: Date.now() - startedAt });
return { data: result };
}
}The good version puts request timing in an interceptor that wraps the controller call. The controller can focus on returning reviews.
The bad version repeats timing and response wrapping inside a route. Other routes can drift in field names, timing behavior, or log context.