import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import type { Observable } from 'rxjs'; import { finalize } from 'rxjs/operators'; import { MetricsService } from './metrics.service'; type RequestLike = { method?: string; baseUrl?: string; route?: { path?: string } }; type ResponseLike = { statusCode?: number }; @Injectable() export class MetricsInterceptor implements NestInterceptor { constructor(private readonly metrics: MetricsService) {} intercept(context: ExecutionContext, next: CallHandler): Observable { if (context.getType() !== 'http') return next.handle(); const http = context.switchToHttp(); const request = http.getRequest(); const response = http.getResponse(); const startedAt = this.metrics.beginRequest(); return next.handle().pipe(finalize(() => { const route = `${request.baseUrl ?? ''}${request.route?.path ?? '/unmatched'}`; this.metrics.finishRequest(startedAt, request.method ?? 'UNKNOWN', route, response.statusCode ?? 500); })); } }