Compare commits

...

28 Commits
6.3.2 ... 6.4.0

Author SHA1 Message Date
Konstantin Pogorelov
c436fa3c88 bump 6.4.0 2021-08-17 10:11:59 +03:00
Konstantin Pogorelov
77b02c7302 add README docs for urlPathReplacement, see #75 2021-08-17 10:11:10 +03:00
Konstantin Pogorelov
068ed93a61 Merge pull request #87 from prabhumarappan/add-url-value-replacement
Added replacement option for path
2021-08-17 10:03:20 +03:00
Konstantin Pogorelov
c5aa3f7388 Merge pull request #89 from jochen-schweizer/dependabot/npm_and_yarn/path-parse-1.0.7
Bump path-parse from 1.0.6 to 1.0.7
2021-08-17 10:01:56 +03:00
Konstantin Pogorelov
ca28ff4fe1 Merge pull request #85 from jochen-schweizer/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.19 to 4.17.21
2021-08-17 10:01:10 +03:00
Konstantin Pogorelov
52f47ed9f4 Merge pull request #84 from jochen-schweizer/dependabot/npm_and_yarn/handlebars-4.7.7
Bump handlebars from 4.7.6 to 4.7.7
2021-08-17 10:00:53 +03:00
Konstantin Pogorelov
a60996ebc3 Merge pull request #93 from RyanBard/update_types_with_exclude_routes
closes #92: Add excludeRoutes to types
2021-08-16 08:58:00 +03:00
Ryan Bard
e7c94ff307 closes #92: Add excludeRoutes to types
Signed-off-by: Ryan Bard <john.ryan.bard@gmail.com>
2021-08-15 20:04:26 -04:00
dependabot[bot]
884617bffe Bump path-parse from 1.0.6 to 1.0.7
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-10 17:34:10 +00:00
Prabhu Marappan
32b76d0970 Added replacement option for path 2021-06-06 16:51:53 +05:30
dependabot[bot]
845cd6ee46 Bump lodash from 4.17.19 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 21:16:33 +00:00
dependabot[bot]
0c3c949425 Bump handlebars from 4.7.6 to 4.7.7
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 17:31:28 +00:00
Konstantin Pogorelov
1ec800cde7 bump 6.3.6 2021-04-03 10:46:38 +02:00
Konstantin Pogorelov
661e7d5092 add types for metricType: summary 2021-04-03 10:39:46 +02:00
Konstantin Pogorelov
b569a71130 Merge pull request #83 from jochen-schweizer/dependabot/npm_and_yarn/y18n-4.0.1
Bump y18n from 4.0.0 to 4.0.1
2021-04-03 10:50:23 +02:00
dependabot[bot]
10c372c438 Bump y18n from 4.0.0 to 4.0.1
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 15:50:49 +00:00
Konstantin Pogorelov
3599c32876 bump 6.3.5 2021-03-28 21:59:44 +02:00
Konstantin Pogorelov
59ec729cb2 Merge pull request #81 from matheuslc/patch-1
Describes httpDurationMetricName option on README
2021-03-28 22:09:32 +02:00
Matheus Lucca do Carmo
c95cd1834c doc: Describes httpDurationMetricName option
Changing the name of the metric, you can use an already existent name and see your application in the same metric space.
2021-03-16 17:48:28 -03:00
Konstantin Pogorelov
d18316fee8 bump 6.3.4 2021-02-22 15:21:48 +01:00
Konstantin Pogorelov
ccb74f99b0 add an a sample with actual RegExp in advanced-example.js, relates to #80 2021-02-22 15:15:37 +01:00
Konstantin Pogorelov
2e093bc14d fix codestyle in types to keep dtslint happy, relates to #80 2021-02-22 15:15:00 +01:00
Konstantin Pogorelov
3f6b2746b9 Merge pull request #80 from thewizarodofoz/patch-1
urlValueParser extra and replace masks can be regexp
2021-02-22 14:59:11 +01:00
Oz Weiss
83ee0ce06e urlValueParser extra and replace masks can be regexp
https://github.com/disjunction/url-value-parser/blob/master/src/ValueDetector.js#L39

`replaceMasks` and `extraMasks` which are passed down to `url-value-parser` can be either string or RegExp.
2021-02-22 10:48:58 +02:00
Konstantin Pogorelov
5300d0ef82 bump 6.3.3 2021-02-19 12:46:56 +01:00
Konstantin Pogorelov
62abb62772 suppress error logging by providing NODE_ENV=test, relates to #78 2021-02-19 12:42:27 +01:00
Konstantin Pogorelov
bef92b77e1 Merge pull request #78 from FauxFaux/fix/handle-errors
fix: handle errors from prom-client
2021-02-19 12:17:05 +01:00
Chris West (Faux)
99d8fc1ea9 fix: handle errors from prom-client 2021-02-19 08:32:48 +00:00
11 changed files with 86 additions and 27 deletions

View File

@@ -1,7 +1,7 @@
.PHONY: coverage
test:
./node_modules/jasme/run.js
npm test
lint:
node_modules/eslint/bin/eslint.js src
node_modules/.bin/dtslint types

View File

@@ -53,6 +53,7 @@ Which labels to include in `http_request_duration_seconds` metric:
* **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`**.
### metricType option ###
@@ -79,10 +80,11 @@ Additional options for **summary**:
See the [docs](https://github.com/disjunction/url-value-parser) of url-value-parser module for details.
* **formatStatusCode**: `function(res)` producing final status code from express `res` object, e.g. you can combine `200`, `201` and `204` to just `2xx`.
* **transformLabels**: `function(labels, req, res)` transforms the **labels** object, e.g. setting dynamic values to **customLabels**
* **urlPathReplacement**: replacement string for the values (default: "#val")
### Other options ###
* **autoregister**: if `/metrics` endpoint should be registered. (Default: **true**)
* **autoregister**: if `/metrics` endpoint should be registered (default: **true**)
* **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)

View File

@@ -19,7 +19,8 @@ const bundle = promBundle({
urlValueParser: {
minHexLength: 5,
extraMasks: [
"^[0-9]+\\.[0-9]+\\.[0-9]+$" // replace dot-separated dates with #val
"^[0-9]+\\.[0-9]+\\.[0-9]+$", // replace dot-separated dates with #val, (regex as string)
/^[0-9]+\-[0-9]+\-[0-9]+$/ // replace dash-separated dates with #val (actual regex)
]
},
normalizePath: [

26
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "express-prom-bundle",
"version": "6.3.2",
"version": "6.4.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1265,9 +1265,9 @@
"dev": true
},
"handlebars": {
"version": "4.7.6",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
"dev": true,
"requires": {
"minimist": "^1.2.5",
@@ -1826,9 +1826,9 @@
}
},
"lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"log-driver": {
@@ -2156,9 +2156,9 @@
"dev": true
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-to-regexp": {
@@ -2980,9 +2980,9 @@
"dev": true
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true
},
"yargs": {

View File

@@ -1,6 +1,6 @@
{
"name": "express-prom-bundle",
"version": "6.3.2",
"version": "6.4.0",
"description": "express middleware with popular prometheus metrics in one bundle",
"main": "src/index.js",
"keywords": [
@@ -16,7 +16,7 @@
],
"types": "types",
"scripts": {
"test": "node_modules/jasme/run.js",
"test": "NODE_ENV=test node_modules/jasme/run.js",
"lint": "eslint src",
"coverage": "make coverage",
"dtslint": "dtslint types",

View File

@@ -409,6 +409,27 @@ describe('index', () => {
});
});
it('handles errors in collectors', done => {
const app = express();
const instance = bundle({});
app.use(instance);
new promClient.Gauge({
name: 'kaboom',
help: 'this metric explodes',
collect() {
throw new Error('kaboom!');
}
});
// the error will NOT be displayed if NODE_ENV=test (as defined in package.json)
supertest(app)
.get('/metrics')
.expect(500)
.end((err) => done(err));
});
it('customLabels={foo: "bar"} adds foo="bar" label to metrics', done => {
const app = express();
const instance = bundle({

View File

@@ -28,4 +28,9 @@ describe('normalizePath', () => {
});
expect(subject).toThrow();
});
it('uses urlPathReplacement when passed to transform the path', () => {
expect(normalizePath({url: '/a/12345'}, {urlPathReplacement: ':id'}))
.toBe('/a/:id');
});
});

View File

@@ -140,17 +140,20 @@ function main(opts) {
}
const metricsMiddleware = function(req, res, next) {
res.writeHead(200, {'Content-Type': 'text/plain'});
const sendSuccesss = (output) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(output);
};
const metricsResponse = opts.promRegistry.metrics();
// starting from prom-client@13 .metrics() returns a Promise
if (metricsResponse.then) {
metricsResponse
.then(output => res.end(output))
.then(output => sendSuccesss(output))
.catch(err => next(err));
} else {
// compatibility fallback for previous versions of prom-client@<=12
res.end(metricsResponse);
sendSuccesss(metricsResponse);
}
};
@@ -161,7 +164,7 @@ 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, next);
}
// bypass() is checked only after /metrics was processed

View File

@@ -11,6 +11,7 @@ module.exports = function(req, opts) {
// by middlewares such as 'router'. Note: this function is called onFinish
/// i.e. always in the tail of the middleware chain
let path = url.parse(req.originalUrl || req.url).pathname;
const urlPathReplacement = opts ? opts.urlPathReplacement : '#val';
const normalizePath = opts && opts.normalizePath;
if (Array.isArray(normalizePath)) {
@@ -26,5 +27,5 @@ module.exports = function(req, opts) {
if (!urlValueParser) {
urlValueParser = new UrlValueParser(opts && opts.urlValueParser);
}
return urlValueParser.replacePathValues(path);
return urlValueParser.replacePathValues(path, urlPathReplacement);
};

16
types/index.d.ts vendored
View File

@@ -19,7 +19,6 @@ declare namespace express_prom_bundle {
interface Opts {
autoregister?: boolean;
buckets?: number[];
customLabels?: { [key: string]: any };
@@ -30,7 +29,18 @@ declare namespace express_prom_bundle {
bypass?: (req: Request) => 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 };
@@ -43,8 +53,8 @@ declare namespace express_prom_bundle {
urlValueParser?: {
minHexLength?: number;
minBase64Length?: number;
replaceMasks?: string[];
extraMasks?: string[];
replaceMasks?: Array<RegExp | string>;
extraMasks?: Array<RegExp | string>;
};
}

View File

@@ -35,12 +35,13 @@ promBundle({
buckets: [0.1, 0.4, 0.7],
includeMethod: true,
includePath: true,
excludeRoutes: ['/foo', /^\/bar\/?$/],
customLabels: { year: null },
transformLabels: (labels: promBundle.Labels) => ({
...labels,
year: new Date().getFullYear()
}),
metricType: 'summary',
metricType: 'histogram',
metricsPath: '/prometheus',
promClient: {
collectDefaultMetrics: {
@@ -59,6 +60,21 @@ promBundle({
formatStatusCode: (res: Response) => res.statusCode + 100
});
promClient.register.clear();
promBundle({
metricType: 'summary',
maxAgeSeconds: 600,
ageBuckets: 5
});
promClient.register.clear();
promBundle({
metricType: 'summary',
percentiles: [0.01, 0.1, 0.9, 0.99]
});
// TypeScript workaround to write a readonly field
type Writable<T> = { -readonly [K in keyof T]: T[K] };
const wPromBundle: Writable<promBundle> = promBundle;