Remove prometheus depenedency from backend-common

This commit is contained in:
Oliver Sand
2020-12-04 17:00:39 +01:00
parent 8225c58151
commit 12bbd748c5
5 changed files with 49 additions and 98 deletions
@@ -1,21 +1,34 @@
/*
* 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';
---
'@backstage/backend-common': minor
---
Removes the Prometheus integration from `backend-common`.
Rational behind this change is to keep the metrics integration of Backstage
generic. Instead of directly relying on Prometheus, Backstage will expose
metrics in a generic way. Integrators can then export the metrics in their
desired format. For example using Prometheus.
To keep the existing behavior, you need to integrate Prometheus in your
backend:
First, add a dependency on `express-prom-bundle` and `prom-client` to your backend.
```diff
// packages/backend/package.json
"dependencies": {
+ "express-prom-bundle": "^6.1.0",
+ "prom-client": "^12.0.0",
```
Then, add a handler for metrics and a simple instrumentation for the endpoints.
```typescript
// packages/backend/src/metrics.ts
import { useHotCleanup } from '@backstage/backend-common';
import { RequestHandler } from 'express';
import promBundle from 'express-prom-bundle';
import prom from 'prom-client';
import * as url from 'url';
const rootRegEx = new RegExp('^/([^/]*)/.*');
@@ -38,7 +51,7 @@ export function normalizePath(req: any): string {
*/
export function metricsHandler(): RequestHandler {
// We can only initialize the metrics once and have to clean them up between hot reloads
prom.register.clear();
useHotCleanup(module, () => prom.register.clear());
return promBundle({
includeMethod: true,
@@ -51,3 +64,20 @@ export function metricsHandler(): RequestHandler {
promClient: { collectDefaultMetrics: {} },
});
}
```
Last, extend your router configuration with the `metricsHandler`:
```diff
+import { metricsHandler } from './metrics';
...
const service = createServiceBuilder(module)
.loadConfig(config)
.addRouter('', await healthcheck(healthcheckEnv))
+ .addRouter('', metricsHandler())
.addRouter('/api', apiRouter);
```
Your Prometheus metrics will be available at the `/metrics` endpoint.
-2
View File
@@ -41,7 +41,6 @@
"cors": "^2.8.5",
"cross-fetch": "^3.0.6",
"express": "^4.17.1",
"express-prom-bundle": "^6.1.0",
"express-promise-router": "^3.0.3",
"fs-extra": "^9.0.1",
"git-url-parse": "^11.4.0",
@@ -51,7 +50,6 @@
"logform": "^2.1.1",
"minimist": "^1.2.5",
"morgan": "^1.10.0",
"prom-client": "^12.0.0",
"selfsigned": "^1.10.7",
"stoppable": "^1.1.0",
"tar": "^6.0.5",
@@ -39,7 +39,6 @@ import {
readHttpsSettings,
} from './config';
import { createHttpServer, createHttpsServer } from './hostFactory';
import { metricsHandler } from './metrics';
export const DEFAULT_PORT = 7000;
// '' is express default, which listens to all interfaces
@@ -66,7 +65,6 @@ export class ServiceBuilderImpl implements ServiceBuilder {
private corsOptions: cors.CorsOptions | undefined;
private cspOptions: Record<string, string[] | false> | undefined;
private httpsSettings: HttpsSettings | undefined;
private enableMetrics: boolean = true;
private routers: [string, Router][];
// Reference to the module where builder is created - needed for hot module
// reloading
@@ -109,9 +107,6 @@ export class ServiceBuilderImpl implements ServiceBuilder {
this.httpsSettings = httpsSettings;
}
// For now, configuration of metrics is a simple boolean and active by default
this.enableMetrics = backendConfig.getOptionalBoolean('metrics') !== false;
return this;
}
@@ -166,9 +161,6 @@ export class ServiceBuilderImpl implements ServiceBuilder {
app.use(cors(corsOptions));
}
app.use(compression());
if (this.enableMetrics) {
app.use(metricsHandler());
}
app.use(requestLoggingHandler());
for (const [root, route] of this.routers) {
app.use(root, route);
@@ -1,37 +0,0 @@
/*
* 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 { normalizePath } from './metrics';
describe('normalizePath', () => {
it('should normalize /path to /path', async () => {
const path = normalizePath({ url: 'http://server/path' });
expect(path).toBe('/path');
});
it('should normalize /path/test to /path', async () => {
const path = normalizePath({ url: 'http://server/path/test' });
expect(path).toBe('/path');
});
it('should normalize /api/plugin-name/test to /api/plugin-name', async () => {
const path = normalizePath({ url: 'http://server/api/plugin-name/test' });
expect(path).toBe('/api/plugin-name');
});
});
+1 -33
View File
@@ -7922,11 +7922,6 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
bintrees@1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
bl@^1.0.0:
version "1.2.2"
resolved "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
@@ -11724,14 +11719,6 @@ expect@^26.5.3:
jest-message-util "^26.5.2"
jest-regex-util "^26.0.0"
express-prom-bundle@^6.1.0:
version "6.1.0"
resolved "https://registry.npmjs.org/express-prom-bundle/-/express-prom-bundle-6.1.0.tgz#8fd72e5bedbbd686b8e7c49e0aecbc1b14b28743"
integrity sha512-krlvp5r6sgJ1IwL6M6/coMrNbAlwtpk+uyivfeyRMCupTK4HzIEQHH0gwrNhLiKyPmSbtZcSmtO6s+PRumRp5g==
dependencies:
on-finished "^2.3.0"
url-value-parser "^2.0.0"
express-promise-router@^3.0.3:
version "3.0.3"
resolved "https://registry.npmjs.org/express-promise-router/-/express-promise-router-3.0.3.tgz#5e6d22a5a3f013d71833172fe8d7ab780c3f6b70"
@@ -17917,7 +17904,7 @@ oidc-token-hash@^5.0.0:
resolved "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.0.tgz#acdfb1f4310f58e64d5d74a4e8671a426986e888"
integrity sha512-8Yr4CZSv+Tn8ZkN3iN2i2w2G92mUKClp4z7EGUfdsERiYSbj7P4i/NHm72ft+aUdsiFx9UdIPSTwbyzQ6C4URg==
on-finished@^2.3.0, on-finished@~2.3.0:
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
@@ -19514,13 +19501,6 @@ progress@^2.0.0:
resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
prom-client@^12.0.0:
version "12.0.0"
resolved "https://registry.npmjs.org/prom-client/-/prom-client-12.0.0.tgz#9689379b19bd3f6ab88a9866124db9da3d76c6ed"
integrity sha512-JbzzHnw0VDwCvoqf8y1WDtq4wSBAbthMB1pcVI/0lzdqHGJI3KBJDXle70XK+c7Iv93Gihqo0a5LlOn+g8+DrQ==
dependencies:
tdigest "^0.1.1"
promise-inflight@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
@@ -22950,13 +22930,6 @@ tarn@^3.0.1:
resolved "https://registry.npmjs.org/tarn/-/tarn-3.0.1.tgz#ebac2c6dbc6977d34d4526e0a7814200386a8aec"
integrity sha512-6usSlV9KyHsspvwu2duKH+FMUhqJnAh6J5J/4MITl8s94iSUQTLkJggdiewKv4RyARQccnigV48Z+khiuVZDJw==
tdigest@^0.1.1:
version "0.1.1"
resolved "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz#2e3cb2c39ea449e55d1e6cd91117accca4588021"
integrity sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=
dependencies:
bintrees "1.0.1"
telejson@^5.0.2:
version "5.0.2"
resolved "https://registry.npmjs.org/telejson/-/telejson-5.0.2.tgz#ed1e64be250cc1c757a53c19e1740b49832b3d51"
@@ -23961,11 +23934,6 @@ url-parse@^1.4.3, url-parse@^1.4.7:
querystringify "^2.1.1"
requires-port "^1.0.0"
url-value-parser@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/url-value-parser/-/url-value-parser-2.0.1.tgz#c8179a095ab9ec1f5aa17ca36af5af396b4e95ed"
integrity sha512-bexECeREBIueboLGM3Y1WaAzQkIn+Tca/Xjmjmfd0S/hFHSCEoFkNh0/D0l9G4K74MkEP/lLFRlYnxX3d68Qgw==
url@^0.11.0, url@~0.11.0:
version "0.11.0"
resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"