All files / src/platform/gateway/interceptors api-metrics.interceptor.ts

0% Statements 0/18
0% Branches 0/2
0% Functions 0/4
0% Lines 0/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57                                                                                                                 
import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
 
// Threshold in milliseconds above which a request is flagged as slow
const SLOW_REQUEST_THRESHOLD_MS = 2000;
 
@Injectable()
export class ApiMetricsInterceptor implements NestInterceptor {
  private readonly logger = new Logger('API_METRICS');
  private readonly metrics = {
    totalRequests: 0,
    totalErrors: 0,
    slowRequests: 0,
  };
 
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const startTime = Date.now();
    this.metrics.totalRequests++;
 
    return next.handle().pipe(
      tap({
        next: () => {
          const duration = Date.now() - startTime;
          if (duration > SLOW_REQUEST_THRESHOLD_MS) {
            this.metrics.slowRequests++;
            const req = context.switchToHttp().getRequest();
            this.logger.warn(
              JSON.stringify({
                type: 'slow_request',
                method: req.method,
                url: req.url,
                durationMs: duration,
                tenantId: req.user?.tenantId,
                timestamp: new Date().toISOString(),
              }),
            );
          }
        },
        error: () => {
          this.metrics.totalErrors++;
        },
      }),
    );
  }
 
  getMetrics() {
    return { ...this.metrics };
  }
}