mirror of
https://github.com/BreizhHardware/express-prom-bundle.git
synced 2026-01-20 09:47:23 +01:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2478e617bb | ||
|
|
92db62dc90 | ||
|
|
3ffdeef8ae | ||
|
|
7c35f1beb6 | ||
|
|
c44d157cfe | ||
|
|
731fd3ec01 | ||
|
|
3f587fb760 | ||
|
|
3c2779d0d1 | ||
|
|
a3c15b1645 | ||
|
|
f4677ce6c6 | ||
|
|
958453eb91 | ||
|
|
0205d4cfc8 | ||
|
|
bffb4cf16e | ||
|
|
52fdbf030f | ||
|
|
c55d5f4862 | ||
|
|
75b1e2cafa | ||
|
|
e2a8869b7f | ||
|
|
c64772dfc9 | ||
|
|
c1b1022fb5 | ||
|
|
16dfa7f926 | ||
|
|
7e58bd3d06 | ||
|
|
adf15f03f4 | ||
|
|
6629c09dfa | ||
|
|
fe2d1d25ec | ||
|
|
a5d63925ce | ||
|
|
43ba2091d3 | ||
|
|
1909018c17 | ||
|
|
52f3a955df | ||
|
|
e2800e7d30 | ||
|
|
fff0384605 | ||
|
|
514745b23a | ||
|
|
77730b9df5 | ||
|
|
6d9da12d97 | ||
|
|
f1f36f0fb7 | ||
|
|
d2f0088f3c | ||
|
|
4f89424c79 | ||
|
|
33765b3654 | ||
|
|
0a1fda31de | ||
|
|
7654a4ec79 | ||
|
|
faeeb7b57b |
@@ -17,6 +17,7 @@
|
||||
"extends": "eslint:recommended",
|
||||
|
||||
"rules": {
|
||||
"indent": [1, 2],
|
||||
"array-bracket-spacing": [2, "never"],
|
||||
"block-scoped-var": 2,
|
||||
"brace-style": [2, "1tbs"],
|
||||
|
||||
@@ -2,12 +2,12 @@ language: node_js
|
||||
node_js:
|
||||
- "10"
|
||||
- "12"
|
||||
- "13"
|
||||
- "14"
|
||||
notifications:
|
||||
email: false
|
||||
before_install:
|
||||
- npm install prom-client
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
- npm run dtslint
|
||||
|
||||
- npm run dtslint-next
|
||||
|
||||
@@ -46,12 +46,13 @@ Which labels to include in `http_request_duration_seconds` metric:
|
||||
|
||||
* **includeStatusCode**: HTTP status code (200, 400, 404 etc.), default: **true**
|
||||
* **includeMethod**: HTTP method (GET, PUT, ...), default: **false**
|
||||
* **includePath**: URL path (see importent details below), default: **false**
|
||||
* **includePath**: URL path (see important details below), default: **false**
|
||||
* **customLabels**: an object containing extra labels, e.g. ```{project_name: 'hello_world'}```.
|
||||
Most useful together with **transformLabels** callback, otherwise it's better to use native Prometheus relabeling.
|
||||
* **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**
|
||||
|
||||
### metricType option ###
|
||||
|
||||
@@ -85,6 +86,7 @@ Additional options for **summary**:
|
||||
* **promClient**: options for promClient startup, e.g. **collectDefaultMetrics**. This option was added
|
||||
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`.
|
||||
|
||||
### More details on includePath option
|
||||
|
||||
|
||||
113
package-lock.json
generated
113
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "express-prom-bundle",
|
||||
"version": "5.1.5",
|
||||
"version": "6.3.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -115,9 +115,9 @@
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz",
|
||||
"integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
|
||||
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
@@ -210,7 +210,7 @@
|
||||
},
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -892,10 +892,21 @@
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
|
||||
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
|
||||
"dev": true
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
|
||||
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.0.0",
|
||||
@@ -1254,25 +1265,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.0.12",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz",
|
||||
"integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==",
|
||||
"version": "4.7.6",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
|
||||
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^2.5.0",
|
||||
"optimist": "^0.6.1",
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"uglify-js": "^3.1.4"
|
||||
"uglify-js": "^3.1.4",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
|
||||
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.10"
|
||||
}
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
@@ -1354,7 +1363,7 @@
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -1621,9 +1630,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
|
||||
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
@@ -1817,9 +1826,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"log-driver": {
|
||||
@@ -1957,6 +1966,12 @@
|
||||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
|
||||
"dev": true
|
||||
},
|
||||
"neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
@@ -2031,30 +2046,6 @@
|
||||
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=",
|
||||
"dev": true
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
|
||||
@@ -2207,9 +2198,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"prom-client": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-12.0.0.tgz",
|
||||
"integrity": "sha512-JbzzHnw0VDwCvoqf8y1WDtq4wSBAbthMB1pcVI/0lzdqHGJI3KBJDXle70XK+c7Iv93Gihqo0a5LlOn+g8+DrQ==",
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.0.0.tgz",
|
||||
"integrity": "sha512-M7ZNjIO6x+2R/vjSD13yjJPjpoZA8eEwH2Bp2Re0/PvzozD7azikv+SaBtZes4Q1ca/xHjZ4RSCuTag3YZLg1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tdigest": "^0.1.1"
|
||||
@@ -2355,7 +2346,7 @@
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -2516,7 +2507,7 @@
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "http://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
|
||||
"integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -2669,7 +2660,7 @@
|
||||
},
|
||||
"superagent": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "http://registry.npmjs.org/superagent/-/superagent-2.3.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/superagent/-/superagent-2.3.0.tgz",
|
||||
"integrity": "sha1-cDUpoHFOV+EjlZ3e+84ZOy5Q0RU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -2687,7 +2678,7 @@
|
||||
},
|
||||
"supertest": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "http://registry.npmjs.org/supertest/-/supertest-2.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/supertest/-/supertest-2.0.1.tgz",
|
||||
"integrity": "sha1-oFgIHXiPFRXUcA11Aogea3WeRM0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "express-prom-bundle",
|
||||
"version": "6.0.0",
|
||||
"version": "6.3.2",
|
||||
"description": "express middleware with popular prometheus metrics in one bundle",
|
||||
"main": "src/index.js",
|
||||
"keywords": [
|
||||
@@ -17,8 +17,10 @@
|
||||
"types": "types",
|
||||
"scripts": {
|
||||
"test": "node_modules/jasme/run.js",
|
||||
"lint": "eslint src",
|
||||
"coverage": "make coverage",
|
||||
"dtslint": "dtslint types"
|
||||
"dtslint": "dtslint types",
|
||||
"dtslint-next": "dtslint --onlyTestTsNext types"
|
||||
},
|
||||
"author": "Konstantin Pogorelov <or@pluseq.com>",
|
||||
"license": "MIT",
|
||||
@@ -36,13 +38,13 @@
|
||||
"jasme": "^6.0.0",
|
||||
"koa": "^2.6.2",
|
||||
"koa-connect": "^2.0.1",
|
||||
"prom-client": "^12.0.0",
|
||||
"prom-client": "^13.0.0",
|
||||
"supertest": "^3.3.0",
|
||||
"supertest-koa-agent": "^0.3.0",
|
||||
"typescript": "^3.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prom-client": "^12.0.0"
|
||||
"prom-client": ">=12.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -200,6 +200,46 @@ describe('index', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('bypass requests', done => {
|
||||
const app = express();
|
||||
const instance = bundle({
|
||||
bypass: (req)=> {
|
||||
// metrics added here to attempt skipping /metrics
|
||||
// this should fail though, because serving /metrics preceeds bypassing
|
||||
return !!req.url.match(/test|bad.word|metrics/)
|
||||
}
|
||||
});
|
||||
app.use(instance);
|
||||
app.use('/test', (req, res) => res.send('it worked'));
|
||||
app.use('/some/bad-word', (req, res) => res.send('it worked too'));
|
||||
app.use('/good-word', (req, res) => res.send('this will be counted'));
|
||||
const agent = supertest(app);
|
||||
agent
|
||||
.get('/test')
|
||||
.end(() => {
|
||||
agent
|
||||
.get('/some/bad-word')
|
||||
.end(() => {
|
||||
agent
|
||||
.get('/good-word')
|
||||
.end(() => {
|
||||
const metricHashMap = instance.metrics.http_request_duration_seconds.hashMap;
|
||||
expect(metricHashMap['status_code:200']).toBeDefined();
|
||||
|
||||
// only /good-word should be counted
|
||||
expect(metricHashMap['status_code:200'].count).toBe(1);
|
||||
|
||||
agent
|
||||
.get('/metrics')
|
||||
.end((err, res) => {
|
||||
expect(res.status).toBe(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('complains about deprecated options', () => {
|
||||
expect(() => bundle({prefix: 'hello'})).toThrow();
|
||||
});
|
||||
|
||||
75
src/index.js
75
src/index.js
@@ -17,20 +17,37 @@ function matchVsRegExps(element, regexps) {
|
||||
}
|
||||
|
||||
function clusterMetrics() {
|
||||
const aggregatorRegistry = new promClient.AggregatorRegistry();
|
||||
const aggregatorRegistry = new promClient.AggregatorRegistry();
|
||||
|
||||
const metricsMiddleware = function(req, res) {
|
||||
aggregatorRegistry.clusterMetrics((err, clusterMetrics) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
res.set('Content-Type', aggregatorRegistry.contentType);
|
||||
res.send(clusterMetrics);
|
||||
});
|
||||
};
|
||||
const metricsMiddleware = function(req, res) {
|
||||
function sendClusterMetrics(clusterMetrics) {
|
||||
res.set('Content-Type', aggregatorRegistry.contentType);
|
||||
res.send(clusterMetrics);
|
||||
}
|
||||
|
||||
return metricsMiddleware;
|
||||
function sendClusterMetricsError(err) {
|
||||
console.error(err);
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
|
||||
// since prom-client@13 clusterMetrics() method doesn't take cb param,
|
||||
// but we provide it anyway, as at this stage it's unknown which version of prom-client is used
|
||||
const response = aggregatorRegistry.clusterMetrics((err, clusterMetrics) => {
|
||||
if (err) {
|
||||
return sendClusterMetricsError(err);
|
||||
}
|
||||
sendClusterMetrics(clusterMetrics);
|
||||
});
|
||||
|
||||
// if we find out that it was a promise and our cb was useless...
|
||||
if (response && response.then) {
|
||||
response
|
||||
.then(result => sendClusterMetrics(result))
|
||||
.catch(err => sendClusterMetricsError(err));
|
||||
}
|
||||
};
|
||||
|
||||
return metricsMiddleware;
|
||||
}
|
||||
|
||||
function main(opts) {
|
||||
@@ -50,7 +67,8 @@ function main(opts) {
|
||||
normalizePath: main.normalizePath,
|
||||
formatStatusCode: main.normalizeStatusCode,
|
||||
metricType: 'histogram',
|
||||
promClient: {}
|
||||
promClient: {},
|
||||
promRegistry: promClient.register
|
||||
}, opts
|
||||
);
|
||||
|
||||
@@ -92,14 +110,16 @@ function main(opts) {
|
||||
labelNames: labels,
|
||||
percentiles: opts.percentiles || [0.5, 0.75, 0.95, 0.98, 0.99, 0.999],
|
||||
maxAgeSeconds: opts.maxAgeSeconds,
|
||||
ageBuckets: opts.ageBuckets
|
||||
ageBuckets: opts.ageBuckets,
|
||||
registers: [opts.promRegistry]
|
||||
});
|
||||
} else if (opts.metricType === 'histogram' || !opts.metricType) {
|
||||
return new promClient.Histogram({
|
||||
name: httpMetricName,
|
||||
help: 'duration histogram of http responses labeled with: ' + labels.join(', '),
|
||||
labelNames: labels,
|
||||
buckets: opts.buckets || [0.003, 0.03, 0.1, 0.3, 1.5, 10]
|
||||
buckets: opts.buckets || [0.003, 0.03, 0.1, 0.3, 1.5, 10],
|
||||
registers: [opts.promRegistry]
|
||||
});
|
||||
} else {
|
||||
throw new Error('metricType option must be histogram or summary');
|
||||
@@ -113,14 +133,25 @@ function main(opts) {
|
||||
if (opts.includeUp !== false) {
|
||||
metrics.up = new promClient.Gauge({
|
||||
name: 'up',
|
||||
help: '1 = up, 0 = not up'
|
||||
help: '1 = up, 0 = not up',
|
||||
registers: [opts.promRegistry]
|
||||
});
|
||||
metrics.up.set(1);
|
||||
}
|
||||
|
||||
const metricsMiddleware = function(req, res) {
|
||||
const metricsMiddleware = function(req, res, next) {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.end(promClient.register.metrics());
|
||||
|
||||
const metricsResponse = opts.promRegistry.metrics();
|
||||
// starting from prom-client@13 .metrics() returns a Promise
|
||||
if (metricsResponse.then) {
|
||||
metricsResponse
|
||||
.then(output => res.end(output))
|
||||
.catch(err => next(err));
|
||||
} else {
|
||||
// compatibility fallback for previous versions of prom-client@<=12
|
||||
res.end(metricsResponse);
|
||||
}
|
||||
};
|
||||
|
||||
const metricsMatch = opts.metricsPath instanceof RegExp ? opts.metricsPath
|
||||
@@ -130,7 +161,13 @@ function main(opts) {
|
||||
const path = req.originalUrl || req.url; // originalUrl gets lost in koa-connect?
|
||||
|
||||
if (opts.autoregister && path.match(metricsMatch)) {
|
||||
return metricsMiddleware(req, res);
|
||||
return metricsMiddleware(req, res);
|
||||
}
|
||||
|
||||
// bypass() is checked only after /metrics was processed
|
||||
// if you wish to disable /metrics use autoregister:false instead
|
||||
if (opts.bypass && opts.bypass(req)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (opts.excludeRoutes && matchVsRegExps(path, opts.excludeRoutes)) {
|
||||
|
||||
14
types/index.d.ts
vendored
14
types/index.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
import { Request, RequestHandler, Response } from 'express';
|
||||
import { DefaultMetricsCollectorConfiguration } from 'prom-client';
|
||||
import { DefaultMetricsCollectorConfiguration, Registry } from 'prom-client';
|
||||
|
||||
export {};
|
||||
|
||||
@@ -15,7 +15,7 @@ declare namespace express_prom_bundle {
|
||||
type NormalizePathEntry = [string | RegExp, string];
|
||||
type NormalizePathFn = (req: Request, opts: Opts) => string;
|
||||
type NormalizeStatusCodeFn = (res: Response) => number | string;
|
||||
type TransformLabelsFn = (labels: Labels, req: Request, res: Response) => Labels;
|
||||
type TransformLabelsFn = (labels: Labels, req: Request, res: Response) => void;
|
||||
|
||||
interface Opts {
|
||||
autoregister?: boolean;
|
||||
@@ -28,9 +28,13 @@ declare namespace express_prom_bundle {
|
||||
includePath?: boolean;
|
||||
includeUp?: boolean;
|
||||
|
||||
bypass?: (req: Request) => boolean;
|
||||
|
||||
metricType?: 'summary' | 'histogram';
|
||||
metricsPath?: string;
|
||||
httpDurationMetricName?: string;
|
||||
promClient?: { collectDefaultMetrics?: DefaultMetricsCollectorConfiguration };
|
||||
promRegistry?: Registry;
|
||||
normalizePath?: NormalizePathEntry[] | NormalizePathFn;
|
||||
formatStatusCode?: NormalizeStatusCodeFn;
|
||||
transformLabels?: TransformLabelsFn;
|
||||
@@ -44,6 +48,10 @@ declare namespace express_prom_bundle {
|
||||
};
|
||||
}
|
||||
|
||||
interface Middleware extends RequestHandler {
|
||||
metricsMiddleware: RequestHandler;
|
||||
}
|
||||
|
||||
const normalizePath: NormalizePathFn;
|
||||
const normalizeStatusCode: NormalizeStatusCodeFn;
|
||||
|
||||
@@ -55,4 +63,4 @@ interface express_prom_bundle {
|
||||
normalizeStatusCode: express_prom_bundle.NormalizeStatusCodeFn;
|
||||
}
|
||||
|
||||
declare function express_prom_bundle(opts: express_prom_bundle.Opts): RequestHandler;
|
||||
declare function express_prom_bundle(opts: express_prom_bundle.Opts): express_prom_bundle.Middleware;
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as promClient from 'prom-client';
|
||||
|
||||
import * as promBundle from 'express-prom-bundle';
|
||||
|
||||
// $ExpectType RequestHandler
|
||||
// $ExpectType Middleware
|
||||
const middleware: RequestHandler = promBundle({ includeMethod: true });
|
||||
|
||||
// $ExpectType: string
|
||||
@@ -11,7 +11,7 @@ middleware.name;
|
||||
|
||||
promClient.register.clear();
|
||||
|
||||
// $ExpectType RequestHandler
|
||||
// $ExpectType Middleware
|
||||
promBundle({
|
||||
normalizePath: [
|
||||
// collect paths like "/customer/johnbobson" as just one "/custom/#name"
|
||||
@@ -30,7 +30,7 @@ promBundle({
|
||||
|
||||
promClient.register.clear();
|
||||
|
||||
// $ExpectType RequestHandler
|
||||
// $ExpectType Middleware
|
||||
promBundle({
|
||||
buckets: [0.1, 0.4, 0.7],
|
||||
includeMethod: true,
|
||||
@@ -46,6 +46,7 @@ promBundle({
|
||||
collectDefaultMetrics: {
|
||||
}
|
||||
},
|
||||
promRegistry: new promClient.Registry(),
|
||||
urlValueParser: {
|
||||
minHexLength: 5,
|
||||
extraMasks: [
|
||||
|
||||
Reference in New Issue
Block a user