Compare commits

...

65 Commits
5.0.2 ... 6.2.0

Author SHA1 Message Date
Konstantin Pogorelov
c55d5f4862 fix duplicate httpDurationMetricName in types 2020-10-06 13:05:26 +02:00
Konstantin Pogorelov
75b1e2cafa bump 6.2.0 2020-10-06 12:54:37 +02:00
Konstantin Pogorelov
e2a8869b7f Merge pull request #43 from GabrielCastro/patch-1
update types to correct transformLabels
2020-10-06 12:51:26 +02:00
Konstantin Pogorelov
c64772dfc9 Merge pull request #55 from dpc/dpc-patch-1
Add a missing option to `Opts`
2020-10-06 12:49:33 +02:00
Konstantin Pogorelov
c1b1022fb5 Merge pull request #56 from Collaborne/pr/middleware-result
Declare that the metricsMiddleware is accessible on the bundle as well
2020-10-06 12:48:39 +02:00
Konstantin Pogorelov
16dfa7f926 bump version to 6.1.0 2020-07-22 18:24:43 +02:00
Konstantin Pogorelov
7e58bd3d06 Merge pull request #47 from jochen-schweizer/dependabot/npm_and_yarn/eslint-utils-1.4.3
Bump eslint-utils from 1.3.1 to 1.4.3
2020-07-22 18:19:46 +02:00
Konstantin Pogorelov
adf15f03f4 Merge pull request #52 from jochen-schweizer/dependabot/npm_and_yarn/acorn-6.4.1
Bump acorn from 6.0.4 to 6.4.1
2020-07-22 18:19:28 +02:00
Konstantin Pogorelov
6629c09dfa Merge pull request #60 from anxolin/add-missing-metric-name-opt
Add missing metric name parameter
2020-07-22 18:16:32 +02:00
Konstantin Pogorelov
fe2d1d25ec Merge pull request #64 from jochen-schweizer/dependabot/npm_and_yarn/handlebars-4.7.6
Bump handlebars from 4.0.12 to 4.7.6
2020-07-22 18:16:03 +02:00
Konstantin Pogorelov
a5d63925ce Merge pull request #62 from jonaskello/patch-1
Fix spelling
2020-07-22 18:15:30 +02:00
dependabot[bot]
43ba2091d3 Bump handlebars from 4.0.12 to 4.7.6
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.0.12 to 4.7.6.
- [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.0.12...v4.7.6)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-22 16:13:09 +00:00
dependabot[bot]
1909018c17 Bump acorn from 6.0.4 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.0.4 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.0.4...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-22 16:13:05 +00:00
dependabot[bot]
52f3a955df Bump eslint-utils from 1.3.1 to 1.4.3
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.3.1 to 1.4.3.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.3.1...v1.4.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-22 16:12:59 +00:00
Konstantin Pogorelov
e2800e7d30 Merge pull request #53 from jochen-schweizer/dependabot/npm_and_yarn/js-yaml-3.13.1
Bump js-yaml from 3.12.0 to 3.13.1
2020-07-22 18:12:31 +02:00
Konstantin Pogorelov
fff0384605 Merge pull request #63 from jochen-schweizer/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.11 to 4.17.19
2020-07-22 18:12:11 +02:00
Konstantin Pogorelov
514745b23a Merge pull request #46 from aaronleesmith/feature/customizable-prom-registry
Allows for customizing promRegistry when creating prom bundle.
2020-07-22 18:10:08 +02:00
dependabot[bot]
77730b9df5 Bump lodash from 4.17.11 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-16 00:02:18 +00:00
Jonas Kello
6d9da12d97 Fix spelling 2020-06-06 18:59:44 +02:00
Anxo Rodriguez
f1f36f0fb7 Add missing metric name parameter 2020-04-27 19:36:43 +02:00
Andreas Kohn
d2f0088f3c Declare that the metricsMiddleware is accessible on the bundle as well
Related-to: #49
2020-04-09 21:09:38 +02:00
Dawid Ciężarkiewicz
4f89424c79 Add a missing option to Opts 2020-04-09 09:28:22 -07:00
dependabot[bot]
33765b3654 Bump js-yaml from 3.12.0 to 3.13.1
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.0 to 3.13.1.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.12.0...3.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-21 18:08:10 +00:00
Konstantin Pogorelov
1a8f38c983 Merge pull request #51 from sam-github/update-prom-client
Update to prom-client v12, requiring Node >=10
2020-03-21 19:07:39 +01:00
Konstantin Pogorelov
23cedb9f05 bump to 6.0.0 2020-03-21 18:49:56 +01:00
Sam Roberts
20c6a7de24 Update to prom-client v12, requiring Node >=10
v12 drops support for versions of Node.js that are no longer supported
(as-of January, 2020), and also removes the timeout option from
collectDefaultMetrics().

Remove 6 and 8 from Travis, and add 12 and 13 (so all the non-EOL versions
of Node.js are tested).
2020-03-06 16:39:47 -08:00
Aaron Smith
0a1fda31de Fixes lint issue. 2019-09-19 11:39:11 -06:00
Aaron Smith
7654a4ec79 Allows for customizing promRegistry when creating prom bundle. 2019-09-19 11:10:43 -06:00
Gabriel Castro
faeeb7b57b update types to correct transformLabels returning
`transformLabels` should return void as the library expects
the labels object to be modified in place and does not use the return value
2019-07-22 16:38:14 -04:00
Konstantin Pogorelov
a21bd439cf bump 5.1.5 2019-05-01 14:53:47 +02:00
Konstantin Pogorelov
90f2d90e46 add dtslint to the main lint target 2019-05-01 14:53:38 +02:00
Konstantin Pogorelov
71c0e52020 Merge pull request #38 from raszi/fix-types
fix(types): fix type definitions and add tests
2019-05-01 14:50:34 +02:00
KARASZI István
78e25d6587 Add back index.d.ts 2019-05-01 14:15:45 +02:00
KARASZI István
02f3fe9008 Simplify type definition 2019-04-30 22:54:46 +02:00
KARASZI István
2a5e25dd77 Fix line ending 2019-04-30 22:46:49 +02:00
KARASZI István
f770ab800d Try to fix Node 6 issue 2019-04-30 22:46:03 +02:00
KARASZI István
6041bee4dd Run dtslint on Travis 2019-04-30 22:40:33 +02:00
KARASZI István
a92b4cfbe6 Remove unnecessary newline 2019-04-30 22:36:23 +02:00
KARASZI István
8df2778337 Fix types and add tests 2019-04-30 22:26:39 +02:00
Konstantin Pogorelov
b00d88c4a7 bump 5.1.4 2019-04-16 13:13:12 +02:00
Konstantin Pogorelov
11988cb025 Merge pull request #37 from cerodriguezl/fix-ts-definition
Fix the definition of the Opts interface
2019-04-16 13:12:39 +02:00
Konstantin Pogorelov
df6854ee04 Merge pull request #36 from gabordobrei/master
make transformLabels optional in index.d.ts
2019-04-16 13:08:14 +02:00
Carlos Rodriguez
48d883b7f2 Fix the definition of the Opts interface
The `buckets` property was defined as a `Tuple` (`[number]`) instead of an Array
(`number[]`).
2019-04-15 18:21:35 -05:00
Gábor Döbrei
b835e90560 make transformLabels optional in index.d.ts 2019-04-15 15:53:11 +02:00
Konstantin Pogorelov
088ff5a063 make customLabels optional in index.d.ts 2019-04-09 22:15:36 +02:00
Konstantin Pogorelov
fd12de6ea3 bump 5.1.3 2019-04-09 22:10:00 +02:00
Konstantin Pogorelov
0b8706dd42 remove trailing spaces 2019-04-09 22:09:44 +02:00
Konstantin Pogorelov
982ff86543 Merge pull request #35 from aaronleesmith/master
add customLabels to index.d.ts
2019-04-09 22:05:51 +02:00
Aaron Smith
5f39d8f357 Update index.d.ts
Custom labels was added as an option but never added to the typescript definition file, breaking the usage during typescript compilation.
2019-04-09 13:54:17 -06:00
Konstantin Pogorelov
d405e3f584 bump 5.1.2 2019-04-08 12:02:45 +02:00
Konstantin Pogorelov
ff147d8fc4 Merge pull request #34 from cliedeman/fix-typedef
typedefs: normalizePath should return a string
2019-04-08 12:01:47 +02:00
Ciaran Liedeman
43f5a2b04f typedefs: normalizePath should return a string 2019-04-08 10:21:53 +02:00
Konstantin Pogorelov
09ee5d954a bump 5.1.1 2019-04-05 18:10:33 +02:00
Konstantin Pogorelov
33cca0d2cf remove .npmignore because files are now whitelisted 2019-04-05 18:09:56 +02:00
Konstantin Pogorelov
2040c043fd Merge branch 'cliedeman-feat/typescript-definitions' 2019-04-05 18:02:10 +02:00
Konstantin Pogorelov
f6466d007b Merge pull request #33 from cliedeman/feat/typescript-definitions
Added Typescript definitions
2019-04-05 18:01:33 +02:00
Konstantin Pogorelov
e68466d7af experimental workaround for testing cluster on travis 2019-04-05 17:56:22 +02:00
Ciaran Liedeman
6b49ffab08 Added Typescript definitions 2019-04-04 11:31:41 +02:00
Konstantin Pogorelov
cb128c7520 bump 5.1.0 2019-03-14 13:37:08 +01:00
Konstantin Pogorelov
d336165848 extract metricType as a seprate odc section 2019-03-14 13:36:54 +01:00
Konstantin Pogorelov
cfe0065146 minor wording changes 2019-03-14 13:17:47 +01:00
Konstantin Pogorelov
963a66a25e Merge pull request #30 from caraboides/master
pass maxAgeSeconds & ageBuckets to summary metrics
2019-03-14 13:06:33 +01:00
Christian Hennig
389684b426 Documentation for sliding window for summary metrics 2019-03-14 11:58:10 +01:00
Konstantin Pogorelov
846ccfc641 Update src/index.js
Co-Authored-By: caraboides <caraboides@googlemail.com>
2019-03-14 12:47:08 +02:00
Christian Hennig
17fe5f4c70 pass maxAgeSeconds & ageBuckets to summary metrics 2019-03-14 10:18:55 +01:00
13 changed files with 920 additions and 94 deletions

View File

@@ -1,8 +0,0 @@
advanced-example.js
docker-compose.yml
spec
.travis.yml
.eslintrc
coverage
.vscode
Makefile

View File

@@ -1,9 +1,13 @@
language: node_js
node_js:
- "6"
- "8"
- "10"
- "12"
- "13"
notifications:
email: false
before_install:
- npm install prom-client
script:
- npm test
- npm run dtslint

View File

@@ -4,6 +4,7 @@ test:
./node_modules/jasme/run.js
lint:
node_modules/eslint/bin/eslint.js src
node_modules/.bin/dtslint types
coverage:
node_modules/istanbul/lib/cli.js cover \
-i 'src/*' \

View File

@@ -46,13 +46,29 @@ 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
Extra transformation callbacks:
### metricType option ###
Two metric types are supported for `http_request_duration_seconds` metric:
* [histogram](https://prometheus.io/docs/concepts/metric_types/#histogram) (default)
* [summary](https://prometheus.io/docs/concepts/metric_types/#summary)
Additional options for **histogram**:
* **buckets**: buckets used for the `http_request_duration_seconds` histogram
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
### Transformation callbacks ###
* **normalizePath**: `function(req)` or `Array`
* if function is provided, then it should generate path value from express `req`
@@ -64,18 +80,13 @@ Extra transformation callbacks:
* **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**
Metric type:
### Other options ###
* **metricType**: two metric types are supported for `http_request_duration_seconds` metric: [histogram](https://prometheus.io/docs/concepts/metric_types/#histogram) and [summary](https://prometheus.io/docs/concepts/metric_types/#summary), default: **histogram**
Other options:
* **buckets**: buckets used for `http_request_duration_seconds` histogram
* **percentiles**: percentiles used for `http_request_duration_seconds` summary
* **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)
* **promRegistry**: Optional `promClient.Registry` instance to attach metrics to. Defaults to global `promClient.register`.
### More details on includePath option
@@ -234,7 +245,6 @@ while replacing all HEX values starting from 5 characters and all IP addresses i
"buckets": [0.1, 1, 5],
"promClient": {
"collectDefaultMetrics": {
"timeout": 2000
}
},
"urlValueParser": {

View File

@@ -14,7 +14,6 @@ const bundle = promBundle({
metricsPath: '/prometheus',
promClient: {
collectDefaultMetrics: {
timeout: 1000
}
},
urlValueParser: {

762
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "express-prom-bundle",
"version": "5.0.2",
"version": "6.2.0",
"description": "express middleware with popular prometheus metrics in one bundle",
"main": "src/index.js",
"keywords": [
@@ -10,9 +10,15 @@
"path",
"method"
],
"files": [
"src",
"types/index.d.ts"
],
"types": "types",
"scripts": {
"test": "node_modules/jasme/run.js",
"coverage": "make coverage"
"coverage": "make coverage",
"dtslint": "dtslint types"
},
"author": "Konstantin Pogorelov <or@pluseq.com>",
"license": "MIT",
@@ -21,24 +27,28 @@
"url-value-parser": "^2.0.0"
},
"devDependencies": {
"@types/express": "^4.16.1",
"coveralls": "^3.0.2",
"dtslint": "^0.7.1",
"eslint": "^5.11.0",
"express": "^4.16.4",
"istanbul": "^0.4.5",
"jasme": "^6.0.0",
"koa": "^2.6.2",
"koa-connect": "^2.0.1",
"prom-client": "^12.0.0",
"supertest": "^3.3.0",
"supertest-koa-agent": "^0.3.0"
"supertest-koa-agent": "^0.3.0",
"typescript": "^3.4.5"
},
"peerDependencies": {
"prom-client": "^11.1.2"
"prom-client": "^12.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/jochen-schweizer/express-prom-bundle.git"
},
"engines": {
"node": ">=6.0.0"
"node": ">=10"
}
}

View File

@@ -443,11 +443,10 @@ describe('index', () => {
bundle({
promClient: {
collectDefaultMetrics: {
timeout: 3000
}
}
});
expect(spy).toHaveBeenCalledWith({timeout: 3000});
expect(spy).toHaveBeenCalledWith({});
});
describe('usage of clusterMetrics()', () => {
@@ -472,7 +471,10 @@ describe('index', () => {
const agent = supertest(app);
// create a fake worker, which would not respond in time
cluster.workers = [{send: () => {}}];
cluster.workers = [{
isConnected: () => true,
send: () => {}
}];
const errorSpy = spyOn(console, 'error'); // mute console.error

View File

@@ -50,7 +50,8 @@ function main(opts) {
normalizePath: main.normalizePath,
formatStatusCode: main.normalizeStatusCode,
metricType: 'histogram',
promClient: {}
promClient: {},
promRegistry: promClient.register
}, opts
);
@@ -90,14 +91,18 @@ function main(opts) {
name: httpMetricName,
help: 'duration summary of http responses labeled with: ' + labels.join(', '),
labelNames: labels,
percentiles: opts.percentiles || [0.5, 0.75, 0.95, 0.98, 0.99, 0.999]
percentiles: opts.percentiles || [0.5, 0.75, 0.95, 0.98, 0.99, 0.999],
maxAgeSeconds: opts.maxAgeSeconds,
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');
@@ -111,14 +116,15 @@ 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) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(promClient.register.metrics());
res.end(opts.promRegistry.metrics());
};
const metricsMatch = opts.metricsPath instanceof RegExp ? opts.metricsPath

64
types/index.d.ts vendored Normal file
View File

@@ -0,0 +1,64 @@
// TypeScript Version: 2.8
import { Request, RequestHandler, Response } from 'express';
import { DefaultMetricsCollectorConfiguration, Registry } from 'prom-client';
export {};
export = express_prom_bundle;
declare namespace express_prom_bundle {
interface Labels {
[key: string]: string | number;
}
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) => void;
interface Opts {
autoregister?: boolean;
buckets?: number[];
customLabels?: { [key: string]: any };
includeStatusCode?: boolean;
includeMethod?: boolean;
includePath?: boolean;
includeUp?: boolean;
metricType?: 'summary' | 'histogram';
metricsPath?: string;
httpDurationMetricName?: string;
promClient?: { collectDefaultMetrics?: DefaultMetricsCollectorConfiguration };
promRegistry?: Registry;
normalizePath?: NormalizePathEntry[] | NormalizePathFn;
formatStatusCode?: NormalizeStatusCodeFn;
transformLabels?: TransformLabelsFn;
// https://github.com/disjunction/url-value-parser#options
urlValueParser?: {
minHexLength?: number;
minBase64Length?: number;
replaceMasks?: string[];
extraMasks?: string[];
};
}
interface Middleware extends RequestHandler {
metricsMiddleware: RequestHandler;
}
const normalizePath: NormalizePathFn;
const normalizeStatusCode: NormalizeStatusCodeFn;
function clusterMetrics(): RequestHandler;
}
interface express_prom_bundle {
normalizePath: express_prom_bundle.NormalizePathFn;
normalizeStatusCode: express_prom_bundle.NormalizeStatusCodeFn;
}
declare function express_prom_bundle(opts: express_prom_bundle.Opts): express_prom_bundle.Middleware;

79
types/test.ts Normal file
View File

@@ -0,0 +1,79 @@
import { Request, RequestHandler, Response } from 'express';
import * as promClient from 'prom-client';
import * as promBundle from 'express-prom-bundle';
// $ExpectType Middleware
const middleware: RequestHandler = promBundle({ includeMethod: true });
// $ExpectType: string
middleware.name;
promClient.register.clear();
// $ExpectType Middleware
promBundle({
normalizePath: [
// collect paths like "/customer/johnbobson" as just one "/custom/#name"
['^/customer/.*', '/customer/#name'],
// collect paths like "/bobjohnson/order-list" as just one "/#name/order-list"
['^.*/order-list', '/#name/order-list']
],
urlValueParser: {
minHexLength: 5,
extraMasks: [
'ORD[0-9]{5,}' // replace strings like ORD1243423, ORD673562 as #val
]
}
});
promClient.register.clear();
// $ExpectType Middleware
promBundle({
buckets: [0.1, 0.4, 0.7],
includeMethod: true,
includePath: true,
customLabels: { year: null },
transformLabels: (labels: promBundle.Labels) => ({
...labels,
year: new Date().getFullYear()
}),
metricType: 'summary',
metricsPath: '/prometheus',
promClient: {
collectDefaultMetrics: {
}
},
promRegistry: new promClient.Registry(),
urlValueParser: {
minHexLength: 5,
extraMasks: [
'^[0-9]+\\.[0-9]+\\.[0-9]+$' // replace dot-separated dates with #val
]
},
normalizePath: [
['^/foo', '/example'] // replace /foo with /example
],
formatStatusCode: (res: Response) => res.statusCode + 100
});
// TypeScript workaround to write a readonly field
type Writable<T> = { -readonly [K in keyof T]: T[K] };
const wPromBundle: Writable<promBundle> = promBundle;
wPromBundle.normalizePath = (req: 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();
// $ExpectType RequestHandler
promBundle.clusterMetrics();
// Missing test
// const stringReturn: string = promBundle.normalizePath({}, {});

14
types/tsconfig.json Normal file
View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": ".",
"paths": { "express-prom-bundle": ["."] },
"noEmit": true,
"forceConsistentCasingInFileNames": true
}
}

3
types/tslint.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "dtslint/dtslint.json"
}