mirror of
https://github.com/BreizhHardware/express-prom-bundle.git
synced 2026-01-19 00:37:36 +01:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
522e9ad64d | ||
|
|
db8710d5d0 | ||
|
|
f9a0a7622a | ||
|
|
fd33d98c15 | ||
|
|
5978ea7b73 | ||
|
|
71467e6a17 | ||
|
|
c6b24f6eca | ||
|
|
1ac5fba5c4 | ||
|
|
ca8b0ba1e0 | ||
|
|
2ebc2618de | ||
|
|
df46ecaa9a | ||
|
|
abdfe2d93a | ||
|
|
33ab388106 | ||
|
|
02865e531d | ||
|
|
1a1d8e0b54 | ||
|
|
8371c551d5 | ||
|
|
10a58635e1 | ||
|
|
5f44228f69 | ||
|
|
fd5ff1cfe0 | ||
|
|
edfb9992ed | ||
|
|
0ce44722a5 | ||
|
|
407ea4b0d7 | ||
|
|
63b6d89caa | ||
|
|
5e2b284903 | ||
|
|
c693affcac | ||
|
|
a0eef5d0e2 | ||
|
|
efbab7dcdb | ||
|
|
0bda9934c1 | ||
|
|
5bf6b153e6 | ||
|
|
1171fb5be1 | ||
|
|
ea9f34aa3e | ||
|
|
c541824657 | ||
|
|
7eae5d4b7f |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,4 +2,4 @@
|
||||
node_modules
|
||||
coverage
|
||||
/.vscode
|
||||
|
||||
.env
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "10"
|
||||
- "12"
|
||||
- "14"
|
||||
- "18"
|
||||
notifications:
|
||||
email: false
|
||||
before_install:
|
||||
@@ -10,4 +8,4 @@ before_install:
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
- npm run dtslint-next
|
||||
- npm run test-types
|
||||
|
||||
31
README.md
31
README.md
@@ -4,7 +4,9 @@
|
||||
|
||||
Express middleware with popular prometheus metrics in one bundle. It's also compatible with koa v1 and v2 (see below).
|
||||
|
||||
Since version 5 it uses **prom-client** as a peer dependency. See: https://github.com/siimon/prom-client
|
||||
This library uses **prom-client v15+** as a peer dependency. See: https://github.com/siimon/prom-client
|
||||
|
||||
If you need a support for older versions of prom-client (v12-v14), downgrade to express-prom-bundle v6.6.0
|
||||
|
||||
Included metrics:
|
||||
|
||||
@@ -52,8 +54,8 @@ Which labels to include in `http_request_duration_seconds` metric:
|
||||
* **includeUp**: include an auxiliary "up"-metric which always returns 1, default: **true**
|
||||
* **metricsPath**: replace the `/metrics` route with a **regex** or exact **string**. Note: it is highly recommended to just stick to the default
|
||||
* **metricType**: histogram/summary selection. See more details below
|
||||
* **bypass**: function taking express request as an argument and determines whether the given request should be excluded in the metrics, default: **() => false**
|
||||
* **httpDurationMetricName**: Allows you change the name of HTTP duration metric, default: **`http_request_duration_seconds`**.
|
||||
* **upMetricName**: Allows you change the name of up metric, default: **`up`**.
|
||||
|
||||
### metricType option ###
|
||||
|
||||
@@ -68,6 +70,7 @@ Additional options for **summary**:
|
||||
* **percentiles**: percentiles used for `http_request_duration_seconds` summary
|
||||
* **ageBuckets**: ageBuckets configures how many buckets we have in our sliding window for the summary
|
||||
* **maxAgeSeconds**: the maxAgeSeconds will tell how old a bucket can be before it is reset
|
||||
* **pruneAgedBuckets**: When enabled, timed out buckets will be removed entirely. By default, buckets are reset to 0.
|
||||
|
||||
### Transformation callbacks ###
|
||||
|
||||
@@ -90,6 +93,19 @@ Additional options for **summary**:
|
||||
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`.
|
||||
* **bypass**: An object that takes onRequest and onFinish callbacks that determines whether the given request should be excluded in the metrics. Default:
|
||||
|
||||
```js
|
||||
{
|
||||
onRequest: (req) => false,
|
||||
onFinish: (req, res) => false
|
||||
}
|
||||
```
|
||||
|
||||
`onRequest` is run directly in the middleware chain, before the request is processed. `onFinish` is run after the request has been processed, and has access to the express response object in addition to the request object. Both callbacks are optional, and if one or both returns true the request is excluded.
|
||||
|
||||
As a shorthand, just the onRequest callback can be used instead of the object.
|
||||
|
||||
|
||||
### More details on includePath option
|
||||
|
||||
@@ -147,6 +163,17 @@ For more details:
|
||||
* [normalizePath.js](https://github.com/jochen-schweizer/express-prom-bundle/blob/master/src/normalizePath.js) - source code for path processing
|
||||
|
||||
|
||||
#### Example 3 (return express route definition):
|
||||
|
||||
```javascript
|
||||
app.use(promBundle(/* options? */));
|
||||
|
||||
promBundle.normalizePath = (req, opts) => {
|
||||
// Return the path of the express route (i.e. /v1/user/:id or /v1/timer/automated/:userid/:timerid")
|
||||
return req.route?.path ?? "NULL";
|
||||
};
|
||||
```
|
||||
|
||||
## express example
|
||||
|
||||
setup std. metrics but exclude `up`-metric:
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const promClient = require('prom-client');
|
||||
|
||||
// replace this with require('.') when running from library code
|
||||
const promBundle = require('express-prom-bundle');
|
||||
|
||||
const bundle = promBundle({
|
||||
|
||||
5157
package-lock.json
generated
5157
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "express-prom-bundle",
|
||||
"version": "6.5.0",
|
||||
"version": "8.0.1",
|
||||
"description": "express middleware with popular prometheus metrics in one bundle",
|
||||
"main": "src/index.js",
|
||||
"keywords": [
|
||||
@@ -14,43 +14,42 @@
|
||||
"src",
|
||||
"types/index.d.ts"
|
||||
],
|
||||
"types": "types",
|
||||
"types": "types/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "NODE_ENV=test node_modules/jasme/run.js",
|
||||
"lint": "eslint src",
|
||||
"coverage": "make coverage",
|
||||
"dtslint": "dtslint types",
|
||||
"dtslint-next": "dtslint --onlyTestTsNext types"
|
||||
"test-types": "tsd"
|
||||
},
|
||||
"author": "Konstantin Pogorelov <or@pluseq.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "^5.0.0",
|
||||
"on-finished": "^2.3.0",
|
||||
"url-value-parser": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.16.1",
|
||||
"coveralls": "^3.0.2",
|
||||
"dtslint": "^0.7.1",
|
||||
"dts": "^0.1.1",
|
||||
"eslint": "^5.11.0",
|
||||
"express": "^4.16.4",
|
||||
"express": "^5.0.1",
|
||||
"istanbul": "^0.4.5",
|
||||
"jasme": "^6.0.0",
|
||||
"koa": "^2.6.2",
|
||||
"koa-connect": "^2.0.1",
|
||||
"prom-client": "^13.0.0",
|
||||
"prom-client": "^15.0.0",
|
||||
"supertest": "^3.3.0",
|
||||
"supertest-koa-agent": "^0.3.0",
|
||||
"tsd": "^0.30.3",
|
||||
"typescript": "^3.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prom-client": ">=12.0.0"
|
||||
"prom-client": ">=15.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jochen-schweizer/express-prom-bundle.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,20 @@ const supertestKoa = require('supertest-koa-agent');
|
||||
const promClient = require('prom-client');
|
||||
const cluster = require('cluster');
|
||||
|
||||
// for some reason in prom-client 15 the hashmap has a trailing comma
|
||||
function extractBucket (instance, key) {
|
||||
const hashmap = instance.metrics.http_request_duration_seconds.hashMap;
|
||||
if (hashmap[key]) {
|
||||
return hashmap[key];
|
||||
} else {
|
||||
return hashmap[key + ','];
|
||||
}
|
||||
}
|
||||
|
||||
function getMetricCount (s) {
|
||||
return s.replace(/^#.*$\n|^$\n/gm, '').trim().split('\n').length;
|
||||
}
|
||||
|
||||
describe('index', () => {
|
||||
beforeEach(() => {
|
||||
promClient.register.clear();
|
||||
@@ -158,10 +172,9 @@ describe('index', () => {
|
||||
agent
|
||||
.get('/test')
|
||||
.end(() => {
|
||||
const metricHashMap = instance.metrics.http_request_duration_seconds.hashMap;
|
||||
expect(metricHashMap['status_code:200']).toBeDefined();
|
||||
const labeled = metricHashMap['status_code:200'];
|
||||
expect(labeled.count).toBe(1);
|
||||
const bucket = extractBucket(instance, 'status_code:200');
|
||||
expect(bucket).toBeDefined();
|
||||
expect(bucket.count).toBe(1);
|
||||
|
||||
agent
|
||||
.get('/metrics')
|
||||
@@ -223,11 +236,11 @@ describe('index', () => {
|
||||
agent
|
||||
.get('/good-word')
|
||||
.end(() => {
|
||||
const metricHashMap = instance.metrics.http_request_duration_seconds.hashMap;
|
||||
expect(metricHashMap['status_code:200']).toBeDefined();
|
||||
const bucket = extractBucket(instance, 'status_code:200');
|
||||
expect(bucket).toBeDefined();
|
||||
|
||||
// only /good-word should be counted
|
||||
expect(metricHashMap['status_code:200'].count).toBe(1);
|
||||
expect(bucket.count).toBe(1);
|
||||
|
||||
agent
|
||||
.get('/metrics')
|
||||
@@ -240,6 +253,44 @@ describe('index', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('bypass requests, checking res', done => {
|
||||
const app = express();
|
||||
const instance = bundle({
|
||||
bypass: {
|
||||
onFinish: (req, res) => res.statusCode === 404
|
||||
}
|
||||
});
|
||||
app.use(instance);
|
||||
app.use('/200', (req, res) => res.send(''));
|
||||
app.use('/404', (req, res) => res.status(404).send(''));
|
||||
app.use('/500', (req, res) => res.status(500).send(''));
|
||||
|
||||
const agent = supertest(app);
|
||||
agent.get('/200')
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
return agent
|
||||
.get('/404')
|
||||
.expect(404);
|
||||
})
|
||||
.then(() => {
|
||||
return agent
|
||||
.get('/500')
|
||||
.expect(500);
|
||||
})
|
||||
.then(() => {
|
||||
// only /200 and /500 should be counted
|
||||
expect(extractBucket(instance, 'status_code:200').count).toBe(1);
|
||||
expect(extractBucket(instance, 'status_code:404')).not.toBeDefined();
|
||||
expect(extractBucket(instance, 'status_code:500').count).toBe(1);
|
||||
|
||||
return agent
|
||||
.get('/metrics')
|
||||
.expect(200);
|
||||
})
|
||||
.then(done);
|
||||
});
|
||||
|
||||
it('complains about deprecated options', () => {
|
||||
expect(() => bundle({prefix: 'hello'})).toThrow();
|
||||
});
|
||||
@@ -295,7 +346,7 @@ describe('index', () => {
|
||||
|
||||
describe('usage of normalizePath()', () => {
|
||||
|
||||
it('normalizePath can be replaced gloablly', done => {
|
||||
it('normalizePath can be replaced globally', done => {
|
||||
const app = express();
|
||||
const original = bundle.normalizePath;
|
||||
bundle.normalizePath = () => 'dummy';
|
||||
@@ -319,6 +370,40 @@ describe('index', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('respects pruneAgedBuckets', done => {
|
||||
const app = express();
|
||||
const metricsApp = express();
|
||||
const bundled = bundle({
|
||||
metricsApp,
|
||||
metricType: 'summary',
|
||||
includePath: true,
|
||||
maxAgeSeconds: 1,
|
||||
percentiles: [0.5],
|
||||
ageBuckets: 1,
|
||||
pruneAgedBuckets: true,
|
||||
});
|
||||
|
||||
app.use(bundled);
|
||||
|
||||
const agent = supertest(app);
|
||||
const metricsAgent = supertest(metricsApp);
|
||||
agent.get('/foo')
|
||||
.then(() => metricsAgent.get('/metrics'))
|
||||
.then(response => {
|
||||
expect(response.status).toBe(200);
|
||||
// up + bucket, sum, count
|
||||
expect(getMetricCount(response.text)).toBe(4);
|
||||
})
|
||||
.then(() => new Promise(r => setTimeout(r, 1010)))
|
||||
.then(() => metricsAgent.get('/metrics'))
|
||||
.then(response => {
|
||||
expect(response.status).toBe(200);
|
||||
// only up
|
||||
expect(getMetricCount(response.text)).toBe(1);
|
||||
})
|
||||
.finally(done);
|
||||
});
|
||||
|
||||
it('normalizePath function can be overridden', done => {
|
||||
const app = express();
|
||||
const instance = bundle({
|
||||
@@ -499,15 +584,37 @@ describe('index', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('calls promClient.collectDefaultMetrics', () => {
|
||||
const spy = spyOn(promClient, 'collectDefaultMetrics');
|
||||
bundle({
|
||||
promClient: {
|
||||
collectDefaultMetrics: {
|
||||
describe('option collectDefaultMetrics', () => {
|
||||
it('it gets called', () => {
|
||||
const spy = spyOn(promClient, 'collectDefaultMetrics');
|
||||
bundle({
|
||||
promClient: {
|
||||
collectDefaultMetrics: {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(spy).toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
it('prefix is used for up metric', (done) => {
|
||||
const instance = bundle({
|
||||
promClient: {
|
||||
collectDefaultMetrics: {
|
||||
prefix: 'hello_'
|
||||
}
|
||||
}
|
||||
});
|
||||
const app = express();
|
||||
app.use(instance);
|
||||
const agent = supertest(app);
|
||||
agent
|
||||
.get('/metrics')
|
||||
.end((err, res) => {
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.text).toMatch(/^hello_up\s1/m);
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(spy).toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
describe('usage of clusterMetrics()', () => {
|
||||
|
||||
@@ -6,7 +6,11 @@ const normalizeStatusCode = require('../src/normalizeStatusCode');
|
||||
describe('normalizeStatusCode', () => {
|
||||
it('returns run callback if configured', () => {
|
||||
expect(
|
||||
normalizeStatusCode({status_code: 500})
|
||||
normalizeStatusCode({status_code: 500, headersSent: true})
|
||||
).toBe(500);
|
||||
});
|
||||
|
||||
it('returns 499 if headers are not sent', () => {
|
||||
expect(normalizeStatusCode({statusCode: 200, headersSent: false})).toBe(499);
|
||||
});
|
||||
});
|
||||
|
||||
24
src/index.js
24
src/index.js
@@ -91,6 +91,7 @@ function main(opts) {
|
||||
}
|
||||
|
||||
const httpMetricName = opts.httpDurationMetricName || 'http_request_duration_seconds';
|
||||
const upMetricName = opts.upMetricName || 'up';
|
||||
|
||||
function makeHttpMetric() {
|
||||
const labels = ['status_code'];
|
||||
@@ -112,7 +113,8 @@ function main(opts) {
|
||||
percentiles: opts.percentiles || [0.5, 0.75, 0.95, 0.98, 0.99, 0.999],
|
||||
maxAgeSeconds: opts.maxAgeSeconds,
|
||||
ageBuckets: opts.ageBuckets,
|
||||
registers: [opts.promRegistry]
|
||||
registers: [opts.promRegistry],
|
||||
pruneAgedBuckets: opts.pruneAgedBuckets
|
||||
});
|
||||
} else if (opts.metricType === 'histogram' || !opts.metricType) {
|
||||
return new promClient.Histogram({
|
||||
@@ -132,8 +134,12 @@ function main(opts) {
|
||||
};
|
||||
|
||||
if (opts.includeUp !== false) {
|
||||
let prefix = '';
|
||||
if (opts.promClient && opts.promClient.collectDefaultMetrics) {
|
||||
prefix = opts.promClient.collectDefaultMetrics.prefix || '';
|
||||
}
|
||||
metrics.up = new promClient.Gauge({
|
||||
name: 'up',
|
||||
name: prefix + upMetricName,
|
||||
help: '1 = up, 0 = not up',
|
||||
registers: [opts.promRegistry]
|
||||
});
|
||||
@@ -161,6 +167,14 @@ function main(opts) {
|
||||
const metricsMatch = opts.metricsPath instanceof RegExp ? opts.metricsPath
|
||||
: new RegExp('^' + (opts.metricsPath || '/metrics') + '/?$');
|
||||
|
||||
if (typeof opts.bypass === 'function') {
|
||||
opts.bypass = {
|
||||
onRequest: opts.bypass
|
||||
};
|
||||
} else if (!opts.bypass) {
|
||||
opts.bypass = {};
|
||||
}
|
||||
|
||||
const middleware = function (req, res, next) {
|
||||
const path = req.originalUrl || req.url; // originalUrl gets lost in koa-connect?
|
||||
|
||||
@@ -170,7 +184,7 @@ function main(opts) {
|
||||
|
||||
// bypass() is checked only after /metrics was processed
|
||||
// if you wish to disable /metrics use autoregister:false instead
|
||||
if (opts.bypass && opts.bypass(req)) {
|
||||
if (opts.bypass.onRequest && opts.bypass.onRequest(req)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
@@ -182,6 +196,10 @@ function main(opts) {
|
||||
const timer = metrics[httpMetricName].startTimer(labels);
|
||||
|
||||
onFinished(res, () => {
|
||||
if (opts.bypass.onFinish && opts.bypass.onFinish(req, res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.includeStatusCode) {
|
||||
labels.status_code = opts.formatStatusCode(res, opts);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const CLIENT_CLOSED_REQUEST_CODE = 499;
|
||||
|
||||
module.exports = function(res) {
|
||||
return res.status_code || res.statusCode;
|
||||
if (res.headersSent) {
|
||||
return res.status_code || res.statusCode;
|
||||
} else {
|
||||
return CLIENT_CLOSED_REQUEST_CODE;
|
||||
}
|
||||
};
|
||||
|
||||
41
types/index.d.ts
vendored
41
types/index.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
import { Request, RequestHandler, Response, Express } from 'express';
|
||||
import { DefaultMetricsCollectorConfiguration, Registry } from 'prom-client';
|
||||
import { DefaultMetricsCollectorConfiguration, Registry, RegistryContentType } from 'prom-client';
|
||||
|
||||
export {};
|
||||
|
||||
@@ -17,7 +17,7 @@ declare namespace express_prom_bundle {
|
||||
type NormalizeStatusCodeFn = (res: Response) => number | string;
|
||||
type TransformLabelsFn = (labels: Labels, req: Request, res: Response) => void;
|
||||
|
||||
interface Opts {
|
||||
interface BaseOptions {
|
||||
autoregister?: boolean;
|
||||
|
||||
customLabels?: { [key: string]: any };
|
||||
@@ -27,23 +27,19 @@ declare namespace express_prom_bundle {
|
||||
includePath?: boolean;
|
||||
includeUp?: boolean;
|
||||
|
||||
bypass?: (req: Request) => boolean;
|
||||
bypass?:
|
||||
| ((req: Request) => boolean)
|
||||
| {
|
||||
onRequest?: (req: Request) => boolean;
|
||||
onFinish?: (req: Request, res: Response) => boolean;
|
||||
};
|
||||
|
||||
excludeRoutes?: Array<string | RegExp>;
|
||||
|
||||
metricType?: 'summary' | 'histogram';
|
||||
|
||||
// https://github.com/siimon/prom-client#histogram
|
||||
buckets?: number[];
|
||||
|
||||
// https://github.com/siimon/prom-client#summary
|
||||
percentiles?: number[];
|
||||
maxAgeSeconds?: number;
|
||||
ageBuckets?: number;
|
||||
|
||||
metricsPath?: string;
|
||||
httpDurationMetricName?: string;
|
||||
promClient?: { collectDefaultMetrics?: DefaultMetricsCollectorConfiguration };
|
||||
upMetricName?: string;
|
||||
promClient?: { collectDefaultMetrics?: DefaultMetricsCollectorConfiguration<RegistryContentType> };
|
||||
promRegistry?: Registry;
|
||||
normalizePath?: NormalizePathEntry[] | NormalizePathFn;
|
||||
formatStatusCode?: NormalizeStatusCodeFn;
|
||||
@@ -60,6 +56,23 @@ declare namespace express_prom_bundle {
|
||||
};
|
||||
}
|
||||
|
||||
/** @see https://github.com/siimon/prom-client#summary */
|
||||
type SummaryOptions = BaseOptions & {
|
||||
metricType?: 'summary';
|
||||
percentiles?: number[];
|
||||
maxAgeSeconds?: number;
|
||||
ageBuckets?: number;
|
||||
pruneAgedBuckets?: boolean;
|
||||
}
|
||||
|
||||
/** @see https://github.com/siimon/prom-client#histogram */
|
||||
type HistogramOptions = BaseOptions & {
|
||||
metricType?: 'histogram';
|
||||
buckets?: number[];
|
||||
}
|
||||
|
||||
type Opts = SummaryOptions | HistogramOptions;
|
||||
|
||||
interface Middleware extends RequestHandler {
|
||||
metricsMiddleware: RequestHandler;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import * as express from 'express';
|
||||
|
||||
import express, { RequestHandler } from 'express';
|
||||
import { expectType } from 'tsd'
|
||||
import * as promClient from 'prom-client';
|
||||
import promBundle, {
|
||||
type Middleware
|
||||
} from '..';
|
||||
|
||||
import * as promBundle from 'express-prom-bundle';
|
||||
|
||||
// $ExpectType Middleware
|
||||
const middleware: express.RequestHandler = promBundle({ includeMethod: true });
|
||||
|
||||
// $ExpectType: string
|
||||
middleware.name;
|
||||
expectType<string>(middleware.name);
|
||||
|
||||
promClient.register.clear();
|
||||
|
||||
// $ExpectType Middleware
|
||||
promBundle({
|
||||
expectType<Middleware>(promBundle({
|
||||
normalizePath: [
|
||||
// collect paths like "/customer/johnbobson" as just one "/custom/#name"
|
||||
['^/customer/.*', '/customer/#name'],
|
||||
@@ -27,12 +25,11 @@ promBundle({
|
||||
'ORD[0-9]{5,}' // replace strings like ORD1243423, ORD673562 as #val
|
||||
]
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
promClient.register.clear();
|
||||
|
||||
// $ExpectType Middleware
|
||||
promBundle({
|
||||
expectType<Middleware>(promBundle({
|
||||
buckets: [0.1, 0.4, 0.7],
|
||||
includeMethod: true,
|
||||
includePath: true,
|
||||
@@ -60,7 +57,7 @@ promBundle({
|
||||
],
|
||||
formatStatusCode: (res: express.Response) => res.statusCode + 100,
|
||||
metricsApp: express()
|
||||
});
|
||||
}));
|
||||
|
||||
promClient.register.clear();
|
||||
|
||||
@@ -90,8 +87,5 @@ wPromBundle.normalizePath = (req: express.Request, opts: promBundle.Opts) => {
|
||||
|
||||
wPromBundle.normalizeStatusCode = (res: express.Response) => res.statusCode.toString();
|
||||
|
||||
// $ExpectType RequestHandler
|
||||
promBundle.clusterMetrics();
|
||||
expectType<RequestHandler>(promBundle.clusterMetrics());
|
||||
|
||||
// Missing test
|
||||
// const stringReturn: string = promBundle.normalizePath({}, {});
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"baseUrl": ".",
|
||||
"paths": { "express-prom-bundle": ["."] },
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "dtslint/dtslint.json"
|
||||
}
|
||||
Reference in New Issue
Block a user