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 | 13x 13x 13x 13x 13x 13x 298x 298x 298x 298x 298x 298x 298x 241x 241x 241x 241x | import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Histogram, Counter, register } from 'prom-client';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
/**
* Collects basic HTTP metrics for Prometheus because numbers are sexy 🍆📈
*/
@Injectable()
export class MetricsInterceptor implements NestInterceptor {
private readonly requestCounter: Counter<string>;
private readonly durationHistogram: Histogram<string>;
constructor() {
this.requestCounter = (register.getSingleMetric("http_requests_total") as Counter<string>) ?? new Counter({
name: "http_requests_total",
help: "Total number of HTTP requests",
labelNames: ["method", "route", "status"] as const,
registers: [register],
});
this.durationHistogram = (register.getSingleMetric("http_request_duration_seconds") as Histogram<string>) ?? new Histogram({
name: "http_request_duration_seconds",
help: "Request duration in seconds",
buckets: [0.05, 0.1, 0.2, 0.5, 1, 3, 5, 10],
labelNames: ["method", "route", "status"] as const,
registers: [register],
});
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
Iif (context.getType() !== 'http') {
// Skip non-HTTP (e.g., GraphQL resolver). Feel free to extend later.
return next.handle();
}
const httpCtx = context.switchToHttp();
const request = httpCtx.getRequest();
const method = request.method;
const route = request.route?.path || request.url; // crude but works
const start = Date.now();
return next.handle().pipe(
tap(() => {
const status = httpCtx.getResponse().statusCode;
const labels = { method, route, status: String(status) } as const;
this.requestCounter.inc(labels);
this.durationHistogram.observe(labels, (Date.now() - start) / 1000);
}),
);
}
} |