diff --git a/README.md b/README.md index 6259aee..88f6404 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Additional options for **summary**: to keep `express-prom-bundle` runnable using confit (e.g. with kraken.js) without writing any JS code, see [advanced example](https://github.com/jochen-schweizer/express-prom-bundle/blob/master/advanced-example.js) * **promRegistry**: Optional `promClient.Registry` instance to attach metrics to. Defaults to global `promClient.register`. +* **metricsApp**: Allows you to attach the metrics endpoint to a different express app. You probably want to use it in combination with `autoregister: false`. ### More details on includePath option diff --git a/spec/index.spec.js b/spec/index.spec.js index 55e3152..b4cf671 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -590,5 +590,23 @@ describe('index', () => { }); }); }); + + it('additional metricsApp can be used', done => { + const app = express(); + const metricsApp = express(); + const bundled = bundle({metricsApp}); + + app.use(bundled); + + const agent = supertest(app); + const metricsAgent = supertest(metricsApp); + agent.get('/').end(() => { + metricsAgent.get('/metrics').end((err, res) => { + expect(res.status).toBe(200); + expect(res.text).toMatch(/status_code="404"/); + done(); + }); + }); + }); }); }); diff --git a/src/index.js b/src/index.js index 6f85193..cc6969e 100644 --- a/src/index.js +++ b/src/index.js @@ -68,7 +68,8 @@ function main(opts) { formatStatusCode: main.normalizeStatusCode, metricType: 'histogram', promClient: {}, - promRegistry: promClient.register + promRegistry: promClient.register, + metricsApp: null, }, opts ); @@ -204,6 +205,13 @@ function main(opts) { next(); }; + if (opts.metricsApp) { + opts.metricsApp.get(opts.metricsPath || '/metrics', async (req, res, next) => { + res.set('Content-Type', opts.promRegistry.contentType); + return res.end(await opts.promRegistry.metrics()); + }); + } + middleware.metrics = metrics; middleware.promClient = promClient; middleware.metricsMiddleware = metricsMiddleware; diff --git a/types/index.d.ts b/types/index.d.ts index 16ef31b..6bdc5a7 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,6 +1,6 @@ // TypeScript Version: 2.8 -import { Request, RequestHandler, Response } from 'express'; +import { Request, RequestHandler, Response, Express } from 'express'; import { DefaultMetricsCollectorConfiguration, Registry } from 'prom-client'; export {}; @@ -49,6 +49,7 @@ declare namespace express_prom_bundle { formatStatusCode?: NormalizeStatusCodeFn; transformLabels?: TransformLabelsFn; urlPathReplacement?: string; + metricsApp?: Express; // https://github.com/disjunction/url-value-parser#options urlValueParser?: { diff --git a/types/test.ts b/types/test.ts index 42061b5..176cd54 100644 --- a/types/test.ts +++ b/types/test.ts @@ -1,10 +1,11 @@ -import { Request, RequestHandler, Response } from 'express'; +import * as express from 'express'; + import * as promClient from 'prom-client'; import * as promBundle from 'express-prom-bundle'; // $ExpectType Middleware -const middleware: RequestHandler = promBundle({ includeMethod: true }); +const middleware: express.RequestHandler = promBundle({ includeMethod: true }); // $ExpectType: string middleware.name; @@ -57,7 +58,8 @@ promBundle({ normalizePath: [ ['^/foo', '/example'] // replace /foo with /example ], - formatStatusCode: (res: Response) => res.statusCode + 100 + formatStatusCode: (res: express.Response) => res.statusCode + 100, + metricsApp: express() }); promClient.register.clear(); @@ -79,14 +81,14 @@ promBundle({ type Writable = { -readonly [K in keyof T]: T[K] }; const wPromBundle: Writable = promBundle; -wPromBundle.normalizePath = (req: Request, opts: promBundle.Opts) => { +wPromBundle.normalizePath = (req: express.Request, opts: promBundle.Opts) => { const path = promBundle.normalizePath(req, opts); // count all docs as one path, but /docs/login as a separate one return path.match(/^\/docs/) && !path.match(/^\/login/) ? '/docs/*' : path; }; -wPromBundle.normalizeStatusCode = (res: Response) => res.statusCode.toString(); +wPromBundle.normalizeStatusCode = (res: express.Response) => res.statusCode.toString(); // $ExpectType RequestHandler promBundle.clusterMetrics();