-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
183 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/config/metrics/interceptors/request.prom.interceptor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { CallHandler, ExecutionContext, Injectable, NestInterceptor, OnModuleInit } from "@nestjs/common"; | ||
import { Counter, Gauge, Histogram } from "prom-client"; | ||
import { Observable, tap } from "rxjs"; | ||
|
||
@Injectable() | ||
export class PrometheusInterceptor implements NestInterceptor, OnModuleInit { | ||
onModuleInit() { | ||
this.requestSuccessHistogram.reset(); | ||
this.requestFailHistogram.reset(); | ||
this.failureCounter.reset(); | ||
} | ||
// status code 2XX | ||
private readonly requestSuccessHistogram = new Histogram({ | ||
name: "nestjs_success_requests", | ||
help: "NestJs success requests - duration in seconds", | ||
labelNames: ["handler", "controller", "method"], | ||
buckets: [0.0001, 0.001, 0.005, 0.01, 0.025, 0.05, 0.075, 0.09, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], | ||
}); | ||
|
||
// status code != 2XX | ||
private readonly requestFailHistogram = new Histogram({ | ||
name: "nestjs_fail_requests", | ||
help: "NestJs fail requests - duration in seconds", | ||
labelNames: ["handler", "controller", "method"], | ||
buckets: [0.0001, 0.001, 0.005, 0.01, 0.025, 0.05, 0.075, 0.09, 0.1, 0.25, 0.5, 1, 2.5, 5, 10], | ||
}); | ||
|
||
private readonly failureCounter = new Counter({ | ||
name: "nestjs_requests_failed_count", | ||
help: "NestJs requests that failed", | ||
labelNames: ["handler", "controller", "error", "method"], | ||
}); | ||
|
||
static registerServiceInfo(serviceInfo: { domain: string; name: string; version: string }): PrometheusInterceptor { | ||
new Gauge({ | ||
name: "nestjs_info", | ||
help: "NestJs service version info", | ||
labelNames: ["domain", "name", "version"], | ||
}).set( | ||
{ | ||
domain: serviceInfo.domain, | ||
name: `${serviceInfo.domain}.${serviceInfo.name}`, | ||
version: serviceInfo.version, | ||
}, | ||
1 | ||
); | ||
|
||
return new PrometheusInterceptor(); | ||
} | ||
|
||
// metrics url 요청은 트래킹 필요 x | ||
private isAvailableMetricsUrl(url: string): boolean { | ||
const excludePaths = "metrics"; | ||
if (url.includes(excludePaths)) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> { | ||
const originUrl = context.switchToHttp().getRequest().url.toString(); | ||
|
||
const method = context.switchToHttp().getRequest().method.toString(); | ||
const labels = { | ||
controller: context.getClass().name, | ||
handler: context.getHandler().name, | ||
method: method, | ||
}; | ||
|
||
try { | ||
const requestSuccessTimer = this.requestSuccessHistogram.startTimer(labels); | ||
const requestFailTimer = this.requestFailHistogram.startTimer(labels); | ||
return next.handle().pipe( | ||
tap({ | ||
next: () => { | ||
if (this.isAvailableMetricsUrl(originUrl)) { | ||
requestSuccessTimer(); | ||
} | ||
// Handle the next event here | ||
}, | ||
error: () => { | ||
if (this.isAvailableMetricsUrl(originUrl)) { | ||
requestFailTimer(); | ||
this.failureCounter.labels({ ...labels }).inc(1); | ||
} | ||
// Handle the error event here | ||
}, | ||
}) | ||
); | ||
} catch (error) {} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/config/metrics/interceptors/response.prom.interceptor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common"; | ||
import { defaultIfEmpty, map } from "rxjs"; | ||
|
||
@Injectable() | ||
export class ResponseInterceptor implements NestInterceptor { | ||
intercept(_context: ExecutionContext, next: CallHandler) { | ||
const req: Request = _context.switchToHttp().getRequest(); | ||
|
||
const excludePaths = ["/api/capa-metrics", "/capa-metrics"]; | ||
|
||
return next | ||
.handle() | ||
.pipe(defaultIfEmpty(null)) | ||
.pipe( | ||
map((result) => { | ||
if (excludePaths.includes(req.url)) { | ||
return result; | ||
} | ||
}) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// metrics.module.ts | ||
import { Module } from "@nestjs/common"; | ||
import { PrometheusModule as Prometheus } from "@willsoto/nestjs-prometheus"; | ||
|
||
@Module({ | ||
imports: [ | ||
Prometheus.register({ | ||
path: "/metrics", | ||
defaultMetrics: { | ||
enabled: true, | ||
}, | ||
}), | ||
], | ||
}) | ||
export class MetricsModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters