feat(backend-common): introduce metrics for the backend

Add a /metrics endpoint that exposes metrics about the backend. It provides general runtime metrics (memory, gc, utilization) as well as request metrics.
This commit is contained in:
Oliver Sand
2020-08-27 14:40:22 +02:00
parent 70ccbd304c
commit 8f6038951f
4 changed files with 74 additions and 1 deletions
+2
View File
@@ -37,11 +37,13 @@
"compression": "^1.7.4",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-prom-bundle": "^6.1.0",
"express-promise-router": "^3.0.3",
"helmet": "^4.0.0",
"knex": "^0.21.1",
"lodash": "^4.17.15",
"morgan": "^1.10.0",
"prom-client": "^12.0.0",
"selfsigned": "^1.10.7",
"stoppable": "^1.1.0",
"winston": "^3.2.1"
@@ -37,6 +37,7 @@ import {
HttpsSettings,
} from './config';
import { createHttpServer, createHttpsServer } from './hostFactory';
import { metricsHandler } from './metrics';
const DEFAULT_PORT = 7000;
// '' is express default, which listens to all interfaces
@@ -131,6 +132,7 @@ export class ServiceBuilderImpl implements ServiceBuilder {
}
app.use(compression());
app.use(express.json());
app.use(metricsHandler());
app.use(requestLoggingHandler());
for (const [root, route] of this.routers) {
app.use(root, route);
@@ -0,0 +1,37 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import prom from 'prom-client';
import promBundle from 'express-prom-bundle';
import { RequestHandler } from 'express';
/**
* Adds a /metrics endpoint, register default runtime metrics and instrument the router.
*/
export function metricsHandler(): RequestHandler {
// We can only initialize the metrics once and have to clean them up between hot reloads
prom.register.clear();
return promBundle({
includeMethod: true,
includePath: true,
// Using includePath alone is problematic, as it will include path labels with high
// cardinality (e.g. path params). Instead we would have to template them. However, this
// is difficult, as every backend plugin might use different routes. Instead we only take
// the first directory of the path, to have at least an idea how each plugin performs:
normalizePath: [['^/([^/]*)/.*', '/$1']],
promClient: { collectDefaultMetrics: {} },
});
}