Skip to content
Snippets Groups Projects
Unverified Commit 98d515e0 authored by Sigmund, Dominik's avatar Sigmund, Dominik
Browse files

Added Client Counter, Renamed default metrics, dependency updates

parent 3019c7e9
Branches
No related tags found
1 merge request!1Master to main
...@@ -35,6 +35,8 @@ where TYPE is one of: ...@@ -35,6 +35,8 @@ where TYPE is one of:
- `MetricType.HISTOGRAM` - `MetricType.HISTOGRAM`
- `MetricType.SUMMARY` - `MetricType.SUMMARY`
Your names should follow the best practices: <https://prometheus.io/docs/practices/naming/>
All metrics can take a labelNames property in the configuration object. All labelNames that the metric support needs to be declared here. There are 2 ways to add values to the labels All metrics can take a labelNames property in the configuration object. All labelNames that the metric support needs to be declared here. There are 2 ways to add values to the labels
```js ```js
...@@ -116,8 +118,50 @@ The Following Options may be used to configure the behaviour. ...@@ -116,8 +118,50 @@ The Following Options may be used to configure the behaviour.
- disableErrorCounter: Disable the Error Counter. Default: false - disableErrorCounter: Disable the Error Counter. Default: false
- disableRouteCounter: Disable the Route Counter. Default: false - disableRouteCounter: Disable the Route Counter. Default: false
- disableDurationCounter: Disable the Duration Counter. Default: false - disableDurationCounter: Disable the Duration Counter. Default: false
- disableClientCounter: Disables the Counter for client Connections (using Hostname and IP). Default: false
- disableDefaultMetrics: Disable the Collection of default metrics. Default: false - disableDefaultMetrics: Disable the Collection of default metrics. Default: false
#### errorCounter
Counts Errors, labeled by the Error-Code:
```js
name: 'http_errors_total',
help: 'Number of errors',
labelNames: ['error']
```
#### routeCounter
Counts Route-Calls, labeled by the Route:
```js
name: 'http_requests_total',
help: 'Number of requests made to a route',
labelNames: ['route']
```
#### durationCounter
Histogram over times for any call.
```js
name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms',
labelNames: ['method', 'route', 'code'],
buckets: [0.10, 5, 15, 50, 100, 200, 300, 400, 500]
```
#### clientCounter
Count Connections from Clients, labeled by hostname and ip.
```js
name: 'http_clients_total',
help: 'Hostname and IP for Client with count of connections',
labelNames: ['hostname', 'ip']
```
#### Default Metrics #### Default Metrics
- process_cpu_user_seconds_total Total user CPU time spent in seconds. - process_cpu_user_seconds_total Total user CPU time spent in seconds.
... ...
......
This diff is collapsed.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
docs/mutation/stryker-80x80.png

6.05 KiB

This diff is collapsed.
...@@ -22,11 +22,12 @@ class App { ...@@ -22,11 +22,12 @@ class App {
disableErrorCounter: false, disableErrorCounter: false,
disableRouteCounter: false, disableRouteCounter: false,
disableDurationCounter: false, disableDurationCounter: false,
disableDefaultMetrics: false disableDefaultMetrics: false,
disableClientCounter: false
}) })
this.metrics.addCustomMetric({ this.metrics.addCustomMetric({
name: 'test', name: 'sometest',
help: 'Some Test Metric' help: 'Some Test Metric'
}, MetricType.COUNTER) }, MetricType.COUNTER)
...@@ -38,7 +39,7 @@ class App { ...@@ -38,7 +39,7 @@ class App {
res.status(200).send('foo') res.status(200).send('foo')
}) })
this.router.get('/bar', (req:express.Request, res:express.Response) => { this.router.get('/bar', (req:express.Request, res:express.Response) => {
this.metrics["test"].inc() this.metrics.customMetrics["sometest"].inc()
res.status(200).send('bar') res.status(200).send('bar')
}) })
this.router.get('/404', (req:express.Request, res:express.Response) => { this.router.get('/404', (req:express.Request, res:express.Response) => {
... ...
......
This diff is collapsed.
{ {
"name": "@plastdev/metrics", "name": "@general/metrics",
"version": "1.2.1", "version": "1.2.1",
"description": "A small express middleware to get base metrics for any node.js app", "description": "A small express middleware to get base metrics for any node.js app",
"main": "dist/index.js", "main": "dist/index.js",
...@@ -25,34 +25,34 @@ ...@@ -25,34 +25,34 @@
"license": "Unlicense", "license": "Unlicense",
"dependencies": { "dependencies": {
"express": "^4.17.1", "express": "^4.17.1",
"prom-client": "^12.0.0" "prom-client": "^14.0.0"
}, },
"devDependencies": { "devDependencies": {
"@stryker-mutator/core": "^3.2.4", "@stryker-mutator/core": "^5.4.0",
"@stryker-mutator/jest-runner": "^3.2.4", "@stryker-mutator/jest-runner": "^5.4.0",
"@stryker-mutator/typescript": "^3.2.4", "@stryker-mutator/typescript": "^4.0.0",
"@types/express": "^4.17.6", "@types/express": "^4.17.13",
"@types/jest": "^26.0.0", "@types/jest": "^27.0.2",
"@types/node": "^14.0.13", "@types/node": "^16.10.1",
"@types/superagent": "^4.1.7", "@types/superagent": "^4.1.13",
"@types/supertest": "^2.0.9", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^3.2.0", "@typescript-eslint/eslint-plugin": "^4.31.2",
"eslint": "^7.2.0", "eslint": "^7.32.0",
"eslint-config-standard-with-typescript": "^18.0.2", "eslint-config-standard-with-typescript": "^21.0.1",
"eslint-plugin-import": "^2.21.2", "eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^5.1.0",
"eslint-plugin-security": "^1.4.0", "eslint-plugin-security": "^1.4.0",
"eslint-plugin-standard": "^4.0.1", "eslint-plugin-standard": "^4.1.0",
"eslint-plugin-tsdoc": "^0.2.5", "eslint-plugin-tsdoc": "^0.2.14",
"husky": "^4.2.5", "husky": "^7.0.2",
"jest": "^26.0.1", "jest": "^27.2.2",
"jest-html-reporters": "^1.2.1", "jest-html-reporters": "^2.1.6",
"mock-express-request": "^0.2.2", "mock-express-request": "^0.2.2",
"standard": "^14.3.4", "standard": "^16.0.3",
"supertest": "^4.0.2", "supertest": "^6.1.6",
"ts-jest": "^26.1.0", "ts-jest": "^27.0.5",
"typescript": "^3.9.5" "typescript": "^4.4.3"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
... ...
......
import { Metrics } from './index' import { Metrics, MetricType } from './index'
const MockExpressRequest = require('mock-express-request') const MockExpressRequest = require('mock-express-request')
...@@ -21,11 +21,12 @@ describe('metrics', () => { ...@@ -21,11 +21,12 @@ describe('metrics', () => {
jest.resetModules() jest.resetModules()
}) })
describe('constructor / options', () => { describe('constructor / options', () => {
it('should enable all 3 checks and default metrics by default', () => { it('should enable all 4 metrics and default metrics by default', () => {
const metrics = new Metrics({}) const metrics = new Metrics({})
expect(metrics._disableDurationCounter).toBeFalsy() expect(metrics._disableDurationCounter).toBeFalsy()
expect(metrics._disableErrorCounter).toBeFalsy() expect(metrics._disableErrorCounter).toBeFalsy()
expect(metrics._disableRouteCounter).toBeFalsy() expect(metrics._disableRouteCounter).toBeFalsy()
expect(metrics._disableClientCounter).toBeFalsy()
expect(metrics._disableDefaultMetrics).toBeFalsy() expect(metrics._disableDefaultMetrics).toBeFalsy()
}) })
it('should disable Route Counter if option is given', () => { it('should disable Route Counter if option is given', () => {
...@@ -35,6 +36,7 @@ describe('metrics', () => { ...@@ -35,6 +36,7 @@ describe('metrics', () => {
expect(metrics._disableDurationCounter).toBeFalsy() expect(metrics._disableDurationCounter).toBeFalsy()
expect(metrics._disableErrorCounter).toBeFalsy() expect(metrics._disableErrorCounter).toBeFalsy()
expect(metrics._disableRouteCounter).toBeTruthy() expect(metrics._disableRouteCounter).toBeTruthy()
expect(metrics._disableClientCounter).toBeFalsy()
expect(metrics._disableDefaultMetrics).toBeFalsy() expect(metrics._disableDefaultMetrics).toBeFalsy()
}) })
it('should disable Error Counter if option is given', () => { it('should disable Error Counter if option is given', () => {
...@@ -44,6 +46,7 @@ describe('metrics', () => { ...@@ -44,6 +46,7 @@ describe('metrics', () => {
expect(metrics._disableDurationCounter).toBeFalsy() expect(metrics._disableDurationCounter).toBeFalsy()
expect(metrics._disableErrorCounter).toBeTruthy() expect(metrics._disableErrorCounter).toBeTruthy()
expect(metrics._disableRouteCounter).toBeFalsy() expect(metrics._disableRouteCounter).toBeFalsy()
expect(metrics._disableClientCounter).toBeFalsy()
expect(metrics._disableDefaultMetrics).toBeFalsy() expect(metrics._disableDefaultMetrics).toBeFalsy()
}) })
it('should disable Duration Counter if option is given', () => { it('should disable Duration Counter if option is given', () => {
...@@ -53,6 +56,18 @@ describe('metrics', () => { ...@@ -53,6 +56,18 @@ describe('metrics', () => {
expect(metrics._disableDurationCounter).toBeTruthy() expect(metrics._disableDurationCounter).toBeTruthy()
expect(metrics._disableErrorCounter).toBeFalsy() expect(metrics._disableErrorCounter).toBeFalsy()
expect(metrics._disableRouteCounter).toBeFalsy() expect(metrics._disableRouteCounter).toBeFalsy()
expect(metrics._disableClientCounter).toBeFalsy()
expect(metrics._disableDefaultMetrics).toBeFalsy()
})
it('should disable Cient Counter if option is given', () => {
const metrics = new Metrics({
disableClientCounter: true
})
expect(metrics._disableDurationCounter).toBeFalsy()
expect(metrics._disableErrorCounter).toBeFalsy()
expect(metrics._disableRouteCounter).toBeFalsy()
expect(metrics._disableClientCounter).toBeTruthy()
expect(metrics._disableDefaultMetrics).toBeFalsy() expect(metrics._disableDefaultMetrics).toBeFalsy()
}) })
...@@ -63,6 +78,7 @@ describe('metrics', () => { ...@@ -63,6 +78,7 @@ describe('metrics', () => {
expect(metrics._disableDurationCounter).toBeFalsy() expect(metrics._disableDurationCounter).toBeFalsy()
expect(metrics._disableErrorCounter).toBeFalsy() expect(metrics._disableErrorCounter).toBeFalsy()
expect(metrics._disableRouteCounter).toBeFalsy() expect(metrics._disableRouteCounter).toBeFalsy()
expect(metrics._disableClientCounter).toBeFalsy()
expect(metrics._disableDefaultMetrics).toBeTruthy() expect(metrics._disableDefaultMetrics).toBeTruthy()
}) })
...@@ -83,8 +99,50 @@ describe('metrics', () => { ...@@ -83,8 +99,50 @@ describe('metrics', () => {
expect(metrics._ignore).toContain('/favicon.ico') expect(metrics._ignore).toContain('/favicon.ico')
}) })
}) })
describe('addCustomMetric()', () => {
it('should add a metric of type COUNTER', () => {
const metrics = new Metrics()
metrics.addCustomMetric({
name: 'test_counter',
help: 'counter test'
}, MetricType.COUNTER)
expect(metrics.customMetrics.test_counter).toBeDefined()
})
it('should add a metric of type GAUGE', () => {
const metrics = new Metrics()
metrics.addCustomMetric({
name: 'test_gauge',
help: 'gauge test'
}, MetricType.GAUGE)
expect(metrics.customMetrics.test_gauge).toBeDefined()
})
it('should add a metric of type HISTOGRAM', () => {
const metrics = new Metrics()
metrics.addCustomMetric({
name: 'test_histogram',
help: 'histogram test'
}, MetricType.HISTOGRAM)
expect(metrics.customMetrics.test_histogram).toBeDefined()
})
it('should add a metric of type SUMMARY', () => {
const metrics = new Metrics()
metrics.addCustomMetric({
name: 'test_summary',
help: 'summary test'
}, MetricType.SUMMARY)
expect(metrics.customMetrics.test_summary).toBeDefined()
})
it('should add no metrics if there is a different type', () => {
const metrics = new Metrics()
metrics.addCustomMetric({
name: 'test_error',
help: 'error test'
}, 4)
expect(metrics.customMetrics.test_error).toBeUndefined()
})
})
describe('collect()', () => { describe('collect()', () => {
it('should measure all 3 checks by default', () => { it('should measure all 4 metrics by default', () => {
const metrics = new Metrics({}) const metrics = new Metrics({})
const req = new MockExpressRequest() const req = new MockExpressRequest()
req.originalUrl = '/test' req.originalUrl = '/test'
...@@ -92,8 +150,9 @@ describe('metrics', () => { ...@@ -92,8 +150,9 @@ describe('metrics', () => {
const res = mockResponse() const res = mockResponse()
metrics.collect(req, res, () => { /**/ }) metrics.collect(req, res, () => { /**/ })
metrics.collect(req, mockResponse(400), () => { /**/ }) metrics.collect(req, mockResponse(400), () => { /**/ })
expect(metrics._client.register._metrics.numOfRequests.hashMap['route:/test'].value).toBe(2) expect(metrics._client.register._metrics.http_requests_total.hashMap['route:/test'].value).toBe(2)
expect(metrics._client.register._metrics.numOfErrors.hashMap['error:400'].value).toBe(1) expect(metrics._client.register._metrics.http_errors_total.hashMap['error:400'].value).toBe(1)
expect(metrics._client.register._metrics.http_clients_total.hashMap['hostname:www.localhost.com,ip:localhost'].value).toBe(2)
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:200,method:GET,route:/test'].count).toBe(1) expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:200,method:GET,route:/test'].count).toBe(1)
}) })
...@@ -106,8 +165,9 @@ describe('metrics', () => { ...@@ -106,8 +165,9 @@ describe('metrics', () => {
req.method = 'GET' req.method = 'GET'
const res = mockResponse(404) const res = mockResponse(404)
metrics.collect(req, res, () => { /**/ }) metrics.collect(req, res, () => { /**/ })
expect(metrics._client.register._metrics.numOfErrors.hashMap['error:404'].value).toBe(1) expect(metrics._client.register._metrics.http_errors_total.hashMap['error:404'].value).toBe(1)
expect(metrics._client.register._metrics.numOfRequests).toBeUndefined() expect(metrics._client.register._metrics.http_requests_total).toBeUndefined()
expect(metrics._client.register._metrics.http_clients_total.hashMap['hostname:www.localhost.com,ip:localhost'].value).toBe(1)
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:404,method:GET,route:/test'].count).toBe(1) expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:404,method:GET,route:/test'].count).toBe(1)
}) })
it('should disable Error Counter if option is given', () => { it('should disable Error Counter if option is given', () => {
...@@ -119,8 +179,9 @@ describe('metrics', () => { ...@@ -119,8 +179,9 @@ describe('metrics', () => {
req.method = 'GET' req.method = 'GET'
const res = mockResponse(404) const res = mockResponse(404)
metrics.collect(req, res, () => { /**/ }) metrics.collect(req, res, () => { /**/ })
expect(metrics._client.register._metrics.numOfErrors).toBeUndefined() expect(metrics._client.register._metrics.http_errors_total).toBeUndefined()
expect(metrics._client.register._metrics.numOfRequests.hashMap['route:/test'].value).toBe(1) expect(metrics._client.register._metrics.http_requests_total.hashMap['route:/test'].value).toBe(1)
expect(metrics._client.register._metrics.http_clients_total.hashMap['hostname:www.localhost.com,ip:localhost'].value).toBe(1)
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:404,method:GET,route:/test'].count).toBe(1) expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:404,method:GET,route:/test'].count).toBe(1)
}) })
it('should disable Duration Counter if option is given', () => { it('should disable Duration Counter if option is given', () => {
...@@ -132,10 +193,25 @@ describe('metrics', () => { ...@@ -132,10 +193,25 @@ describe('metrics', () => {
req.method = 'GET' req.method = 'GET'
const res = mockResponse(404) const res = mockResponse(404)
metrics.collect(req, res, () => { /**/ }) metrics.collect(req, res, () => { /**/ })
expect(metrics._client.register._metrics.numOfErrors.hashMap['error:404'].value).toBe(1) expect(metrics._client.register._metrics.http_errors_total.hashMap['error:404'].value).toBe(1)
expect(metrics._client.register._metrics.numOfRequests.hashMap['route:/test'].value).toBe(1) expect(metrics._client.register._metrics.http_requests_total.hashMap['route:/test'].value).toBe(1)
expect(metrics._client.register._metrics.http_clients_total.hashMap['hostname:www.localhost.com,ip:localhost'].value).toBe(1)
expect(metrics._client.register._metrics.http_request_duration_ms).toBeUndefined() expect(metrics._client.register._metrics.http_request_duration_ms).toBeUndefined()
}) })
it('should disable Client Counter if option is given', () => {
const metrics = new Metrics({
disableClientCounter: true
})
const req = new MockExpressRequest()
req.originalUrl = '/test'
req.method = 'GET'
const res = mockResponse(404)
metrics.collect(req, res, () => { /**/ })
expect(metrics._client.register._metrics.http_errors_total.hashMap['error:404'].value).toBe(1)
expect(metrics._client.register._metrics.http_requests_total.hashMap['route:/test'].value).toBe(1)
expect(metrics._client.register._metrics.http_clients_total).toBeUndefined()
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:404,method:GET,route:/test'].count).toBe(1)
})
it('should ignore urls in _ignore', () => { it('should ignore urls in _ignore', () => {
const metrics = new Metrics({}) const metrics = new Metrics({})
const req = new MockExpressRequest() const req = new MockExpressRequest()
...@@ -143,37 +219,60 @@ describe('metrics', () => { ...@@ -143,37 +219,60 @@ describe('metrics', () => {
req.method = 'GET' req.method = 'GET'
const res = mockResponse() const res = mockResponse()
metrics.collect(req, res, () => { /**/ }) metrics.collect(req, res, () => { /**/ })
expect(metrics._client.register._metrics.numOfRequests.hashMap).toMatchObject({}) expect(metrics._client.register._metrics.http_errors_total.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.numOfErrors.hashMap).toMatchObject({}) expect(metrics._client.register._metrics.http_requests_total.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap).toMatchObject({}) expect(metrics._client.register._metrics.http_request_duration_ms.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.http_clients_total.hashMap).toMatchObject({})
}) })
}) })
describe('endpoint()', () => { describe('endpoint()', () => {
it('should display all 3 basic metrics and default metrics by default', () => { it('should display all 4 basic metrics and default metrics by default', async () => {
const metrics = new Metrics({}) const metrics = new Metrics({})
const req = new MockExpressRequest() const req = new MockExpressRequest()
const res = mockResponse() const res = mockResponse()
metrics.endpoint(req, res) await metrics.endpoint(req, res)
expect(res._status).toBe(200) expect(res._status).toBe(200)
expect(res._set['Content-Type']).toBe('text/plain; version=0.0.4; charset=utf-8') expect(res._set['Content-Type']).toBe('text/plain; version=0.0.4; charset=utf-8')
expect(res._end).toMatch(/http_request_duration_ms/) expect(res._end).toMatch(/http_request_duration_ms/)
expect(res._end).toMatch(/numOfRequests/) expect(res._end).toMatch(/http_errors_total/)
expect(res._end).toMatch(/numOfErrors/) expect(res._end).toMatch(/http_requests_total/)
expect(res._end).toMatch(/http_clients_total/)
expect(res._end).toMatch(/process_cpu_user_seconds_total/) expect(res._end).toMatch(/process_cpu_user_seconds_total/)
}) })
it('should not scrape default metrics if disabled', () => { it('should not scrape default metrics if disabled', async () => {
const metrics = new Metrics({ const metrics = new Metrics({
disableDefaultMetrics: true disableDefaultMetrics: true
}) })
const req = new MockExpressRequest() const req = new MockExpressRequest()
const res = mockResponse() const res = mockResponse()
metrics.endpoint(req, res) await metrics.endpoint(req, res)
expect(res._status).toBe(200) expect(res._status).toBe(200)
expect(res._set['Content-Type']).toBe('text/plain; version=0.0.4; charset=utf-8') expect(res._set['Content-Type']).toBe('text/plain; version=0.0.4; charset=utf-8')
expect(res._end).toMatch(/http_request_duration_ms/) expect(res._end).toMatch(/http_request_duration_ms/)
expect(res._end).toMatch(/numOfRequests/) expect(res._end).toMatch(/http_errors_total/)
expect(res._end).toMatch(/numOfErrors/) expect(res._end).toMatch(/http_requests_total/)
expect(res._end).toMatch(/http_clients_total/)
expect(res._end).not.toMatch(/process_cpu_user_seconds_total/) expect(res._end).not.toMatch(/process_cpu_user_seconds_total/)
}) })
}) })
describe('resetMetrics()', () => {
it('should reset metrics if asked', () => {
const metrics = new Metrics({})
const req = new MockExpressRequest()
req.originalUrl = '/test'
req.method = 'GET'
const res = mockResponse()
metrics.collect(req, res, () => { /**/ })
metrics.collect(req, mockResponse(400), () => { /**/ })
expect(metrics._client.register._metrics.http_requests_total.hashMap['route:/test'].value).toBe(2)
expect(metrics._client.register._metrics.http_errors_total.hashMap['error:400'].value).toBe(1)
expect(metrics._client.register._metrics.http_clients_total.hashMap['hostname:www.localhost.com,ip:localhost'].value).toBe(2)
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap['code:200,method:GET,route:/test'].count).toBe(1)
metrics.resetMetrics()
expect(metrics._client.register._metrics.http_errors_total.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.http_requests_total.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.http_request_duration_ms.hashMap).toMatchObject({})
expect(metrics._client.register._metrics.http_clients_total.hashMap).toMatchObject({})
})
})
}) })
...@@ -6,6 +6,7 @@ export interface Options { ...@@ -6,6 +6,7 @@ export interface Options {
disableErrorCounter: boolean disableErrorCounter: boolean
disableDurationCounter: boolean disableDurationCounter: boolean
disableDefaultMetrics: boolean disableDefaultMetrics: boolean
disableClientCounter: boolean
} }
export interface CustomMetric { export interface CustomMetric {
...@@ -27,12 +28,14 @@ export class Metrics { ...@@ -27,12 +28,14 @@ export class Metrics {
public readonly _disableErrorCounter: boolean public readonly _disableErrorCounter: boolean
public readonly _disableDurationCounter: boolean public readonly _disableDurationCounter: boolean
public readonly _disableDefaultMetrics: boolean public readonly _disableDefaultMetrics: boolean
public readonly _disableClientCounter: boolean
public readonly _client: any public readonly _client: any
public readonly _httpRequestDurationMicroseconds: any public readonly _httpRequestDurationMicroseconds: any
public readonly _numOfRequests: any public readonly _numOfRequests: any
public readonly _numOfErrors: any public readonly _numOfErrors: any
public readonly _clients: any
public readonly customMetrics: any public readonly customMetrics: any
...@@ -67,19 +70,24 @@ export class Metrics { ...@@ -67,19 +70,24 @@ export class Metrics {
} else { } else {
this._disableDefaultMetrics = false this._disableDefaultMetrics = false
} }
if (typeof options.disableClientCounter !== 'undefined') {
this._disableClientCounter = options.disableClientCounter
} else {
this._disableClientCounter = false
}
if (!this._disableDefaultMetrics) { if (!this._disableDefaultMetrics) {
this._client.collectDefaultMetrics() this._client.collectDefaultMetrics()
} }
if (!this._disableErrorCounter) { if (!this._disableErrorCounter) {
this._numOfErrors = new this._client.Counter({ this._numOfErrors = new this._client.Counter({
name: 'numOfErrors', name: 'http_errors_total',
help: 'Number of errors', help: 'Number of errors',
labelNames: ['error'] labelNames: ['error']
}) })
} }
if (!this._disableRouteCounter) { if (!this._disableRouteCounter) {
this._numOfRequests = new this._client.Counter({ this._numOfRequests = new this._client.Counter({
name: 'numOfRequests', name: 'http_requests_total',
help: 'Number of requests made to a route', help: 'Number of requests made to a route',
labelNames: ['route'] labelNames: ['route']
}) })
...@@ -92,6 +100,13 @@ export class Metrics { ...@@ -92,6 +100,13 @@ export class Metrics {
buckets: [0.10, 5, 15, 50, 100, 200, 300, 400, 500] buckets: [0.10, 5, 15, 50, 100, 200, 300, 400, 500]
}) })
} }
if (!this._disableClientCounter) {
this._clients = new this._client.Counter({
name: 'http_clients_total',
help: 'Hostname and IP for Client with count of connections',
labelNames: ['hostname', 'ip']
})
}
} }
public addCustomMetric = (options: CustomMetric, type: MetricType): void => { public addCustomMetric = (options: CustomMetric, type: MetricType): void => {
...@@ -126,6 +141,9 @@ export class Metrics { ...@@ -126,6 +141,9 @@ export class Metrics {
if (!this._disableRouteCounter) { if (!this._disableRouteCounter) {
this._numOfRequests.inc({ route: req.originalUrl }) this._numOfRequests.inc({ route: req.originalUrl })
} }
if (!this._disableClientCounter) {
this._clients.inc({ hostname: req.hostname, ip: req.ip })
}
if (res.statusCode >= 400) { if (res.statusCode >= 400) {
if (!this._disableErrorCounter) { if (!this._disableErrorCounter) {
this._numOfErrors.inc({ error: res.statusCode }) this._numOfErrors.inc({ error: res.statusCode })
...@@ -136,10 +154,10 @@ export class Metrics { ...@@ -136,10 +154,10 @@ export class Metrics {
next() next()
} }
public endpoint = (req: express.Request, res: express.Response): void => { public endpoint = async (req: express.Request, res: express.Response): Promise<void> => {
res.set('Content-Type', this._client.register.contentType) res.set('Content-Type', this._client.register.contentType)
res.status(200) res.status(200)
res.end(this._client.register.metrics()) res.end(await this._client.register.metrics())
} }
public resetMetrics = (): void => { public resetMetrics = (): void => {
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment