From 5141e77bceba29f56db39f30422abc1dad020f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Fri, 30 Sep 2022 15:28:50 +0200 Subject: [PATCH] fix: add appName to http response time metrics (#2117) --- src/lib/__snapshots__/create-config.test.ts.snap | 2 ++ src/lib/app.ts | 2 +- src/lib/metrics.test.ts | 2 +- src/lib/metrics.ts | 8 +++++--- src/lib/middleware/response-time-metrics.ts | 12 +++++++++++- src/lib/types/experimental.ts | 4 ++++ src/server-dev.ts | 1 + 7 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index 86ade12382..dedf17411f 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -73,6 +73,7 @@ exports[`should create default config 1`] = ` "embedProxyFrontend": false, "personalAccessTokens": false, "publicSignup": false, + "responseTimeWithAppName": false, }, }, "flagResolver": FlagResolver { @@ -84,6 +85,7 @@ exports[`should create default config 1`] = ` "embedProxyFrontend": false, "personalAccessTokens": false, "publicSignup": false, + "responseTimeWithAppName": false, }, "externalResolver": { "isEnabled": [Function], diff --git a/src/lib/app.ts b/src/lib/app.ts index a92ef7eaef..5458519d3e 100644 --- a/src/lib/app.ts +++ b/src/lib/app.ts @@ -42,7 +42,7 @@ export default async function getApp( app.set('port', config.server.port); app.locals.baseUriPath = baseUriPath; if (config.server.serverMetrics && config.eventBus) { - app.use(responseTimeMetrics(config.eventBus)); + app.use(responseTimeMetrics(config.eventBus, config.flagResolver)); } app.use(requestLogger(config)); diff --git a/src/lib/metrics.test.ts b/src/lib/metrics.test.ts index 930590640a..a9b7cb195e 100644 --- a/src/lib/metrics.test.ts +++ b/src/lib/metrics.test.ts @@ -53,7 +53,7 @@ test('should collect metrics for requests', async () => { const metrics = await prometheusRegister.metrics(); expect(metrics).toMatch( - /http_request_duration_milliseconds{quantile="0\.99",path="somePath",method="GET",status="200"}.*1337/, + /http_request_duration_milliseconds{quantile="0\.99",path="somePath",method="GET",status="200",appName="undefined"}.*1337/, ); }); diff --git a/src/lib/metrics.ts b/src/lib/metrics.ts index f37191036b..1ff13dc4f7 100644 --- a/src/lib/metrics.ts +++ b/src/lib/metrics.ts @@ -57,7 +57,7 @@ export default class MetricsMonitor { const requestDuration = new client.Summary({ name: 'http_request_duration_milliseconds', help: 'App response time', - labelNames: ['path', 'method', 'status'], + labelNames: ['path', 'method', 'status', 'appName'], percentiles: [0.1, 0.5, 0.9, 0.95, 0.99], maxAgeSeconds: 600, ageBuckets: 5, @@ -143,8 +143,10 @@ export default class MetricsMonitor { eventBus.on( events.REQUEST_TIME, - ({ path, method, time, statusCode }) => { - requestDuration.labels(path, method, statusCode).observe(time); + ({ path, method, time, statusCode, appName }) => { + requestDuration + .labels(path, method, statusCode, appName) + .observe(time); }, ); diff --git a/src/lib/middleware/response-time-metrics.ts b/src/lib/middleware/response-time-metrics.ts index 6d533c6fd9..21cc6fd816 100644 --- a/src/lib/middleware/response-time-metrics.ts +++ b/src/lib/middleware/response-time-metrics.ts @@ -1,21 +1,31 @@ import * as responseTime from 'response-time'; import EventEmitter from 'events'; import { REQUEST_TIME } from '../metric-events'; +import { IFlagResolver } from '../types/experimental'; // eslint-disable-next-line @typescript-eslint/naming-convention const _responseTime = responseTime.default; -export function responseTimeMetrics(eventBus: EventEmitter): any { +export function responseTimeMetrics( + eventBus: EventEmitter, + flagResolver: IFlagResolver, +): any { return _responseTime((req, res, time) => { const { statusCode } = res; const pathname = req.route ? req.baseUrl + req.route.path : '(hidden)'; + let appName; + if (flagResolver.isEnabled('responseTimeWithAppName')) { + appName = req.headers['unleash-appname']; + } + const timingInfo = { path: pathname, method: req.method, statusCode, time, + appName, }; eventBus.emit(REQUEST_TIME, timingInfo); }); diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 697a19015e..ac78de9bfa 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -26,6 +26,10 @@ export const defaultExperimentalOptions = { process.env.UNLEASH_EXPERIMENTAL_PUBLIC_SIGNUP, false, ), + responseTimeWithAppName: parseEnvVarBoolean( + process.env.UNLEASH_EXPERIMENTAL_RESPONSE_TIME_WITH_APP_NAME, + false, + ), }, externalResolver: { isEnabled: (): boolean => false }, }; diff --git a/src/server-dev.ts b/src/server-dev.ts index ed8ea5d1c8..696e8d5ca8 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -37,6 +37,7 @@ process.nextTick(async () => { embedProxyFrontend: true, batchMetrics: true, anonymiseEventLog: false, + responseTimeWithAppName: true, }, }, authentication: {