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

Almost Done

parent 1d9b1808
No related branches found
No related tags found
1 merge request!1Master to main
This commit is part of merge request !1. Comments created here will be created in the context of that merge request.
.gitlab-ci.yml 0 → 100644
include:
- project: 'general/templates'
file: '/cicd/SAST-nodejs.gitlab-ci.yml'
- project: 'general/templates'
file: '/cicd/npm-audit.gitlab-ci.yml'
- project: 'general/templates'
file: '/cicd/sonarqube.gitlab-ci.yml'
- project: 'general/templates'
file: '/cicd/npm-outdated.gitlab-ci.yml'
variables:
SONAR_PROJECT_KEY: metrics
SONAR_TOKEN: 11922a8e774494f51e1d2f0e695949e4073e7df8
NPM_REGISTRY: https://npm.br-edv.brnet.int
NPM_TOKEN: 5w2Gy80rdH+2Tch0afNI6Q==
cache:
paths:
- node_modules/
- docs/
stages:
- build
- test
- quality
- publish
build:
stage: build
script:
- npm install
- npm run build
test:
stage: test
before_script:
- npm install -g jest
script:
- jest
artifacts:
paths:
- docs/test-report.html
- docs/coverage/lcov.info
publish:
stage: publish
script:
- npm config set strict-ssl false
- npm config set //${NPM_REGISTRY}/:_authToken ${NPM_TOKEN}
- npm publish --registry $NPM_REGISTRY
src/ src/
docs/ docs/
examples/
\ No newline at end of file
...@@ -27,4 +27,24 @@ And to enable the *_metrics*-Endpoint: ...@@ -27,4 +27,24 @@ And to enable the *_metrics*-Endpoint:
### Options ### Options
TODO: fill options The Following Options may be used to configure the behaviour.
\ No newline at end of file
- ignore: A String Array with routes to ignore, e.g. ['/foo'] . Default: []. Important: */_metrics* and */favicon.ico* are always ignored
- disableErrorCounter: Disable the Error Counter. Default: false
- disableRouteCounter: Disable the Route Counter. Default: false
- disableDurationCounter: Disable the Duration Counter. Default: false
## Examples
You can find prebuilt examples in the fitting folder.
Just call `node examples/dist/server.js 3000` to start a Test-Server on Port 3000.
Then use your Browser to call the Endpoints:
- /foo
- /bar
- /404
- /401
And check the results on the Endpoint */_metrics*
# TODO # TODO
- config
- tests - tests
- README: options, examples - get to gitlab-server
\ No newline at end of file
- publish to npm
...@@ -17,7 +17,12 @@ class App { ...@@ -17,7 +17,12 @@ class App {
this.router = express.Router() this.router = express.Router()
this.metrics = new Metrics({}) this.metrics = new Metrics({
ignore: ['/bar'],
disableErrorCounter: false,
disableRouteCounter: false,
disableDurationCounter: false
})
this.router.use(this.metrics.start.bind(this.metrics)) this.router.use(this.metrics.start.bind(this.metrics))
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"scripts": { "scripts": {
"prepublish":"npm run build",
"test": "jest", "test": "jest",
"test:mutation": "stryker run", "test:mutation": "stryker run",
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
...@@ -55,5 +56,8 @@ ...@@ -55,5 +56,8 @@
"pre-push": "npm run lint", "pre-push": "npm run lint",
"post-commit": "./ho-copy" "post-commit": "./ho-copy"
} }
},
"publishConfig": {
"@br:registry": "https://npm.br-edv.brnet.int"
} }
} }
/*
Import.
- Start with different option packages.
- Call all Routes
- Check if _metrics has a good start
*/
import * as express from 'express' import * as express from 'express'
import Prometheus = require('prom-client') import Prometheus = require('prom-client')
export interface Options {
ignore: string[]
disableRouteCounter: boolean
disableErrorCounter: boolean
disableDurationCounter: boolean
}
export class Metrics { export class Metrics {
private readonly _options: any private readonly _ignore: string[]
private readonly _disableRouteCounter: boolean
private readonly _disableErrorCounter: boolean
private readonly _disableDurationCounter: boolean
public readonly _httpRequestDurationMicroseconds: any public readonly _httpRequestDurationMicroseconds: any
public readonly _numOfRequests: any public readonly _numOfRequests: any
public readonly _numOfErrors: any public readonly _numOfErrors: any
constructor (options: any) { constructor (options: Partial<Options> = {}) {
this._options = options if (typeof options.ignore !== 'undefined') {
this._ignore = options.ignore
this._ignore.push('/_metrics')
this._ignore.push('/favicon.ico')
} else {
this._ignore = ['/_metrics', '/favicon.ico']
}
if (typeof options.disableRouteCounter !== 'undefined') {
this._disableRouteCounter = options.disableRouteCounter
} else {
this._disableRouteCounter = false
}
if (typeof options.disableErrorCounter !== 'undefined') {
this._disableErrorCounter = options.disableErrorCounter
} else {
this._disableErrorCounter = false
}
if (typeof options.disableDurationCounter !== 'undefined') {
this._disableDurationCounter = options.disableDurationCounter
} else {
this._disableDurationCounter = false
}
this._httpRequestDurationMicroseconds = new Prometheus.Histogram({ this._httpRequestDurationMicroseconds = new Prometheus.Histogram({
name: 'http_request_duration_ms', name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms', help: 'Duration of HTTP requests in ms',
...@@ -25,22 +58,27 @@ export class Metrics { ...@@ -25,22 +58,27 @@ export class Metrics {
help: 'Number of errors', help: 'Number of errors',
labelNames: ['error'] labelNames: ['error']
}) })
// TODO: config: ignore routes, disable metrics
} }
public start (req: express.Request, res: express.Response, next: express.NextFunction): void { public start (req: express.Request, res: express.Response, next: express.NextFunction): void {
res.locals.startEpoch = Date.now() res.locals.startEpoch = Date.now()
res.on('finish', () => { res.on('finish', () => {
if (req.originalUrl !== '/_metrics' && req.originalUrl !== './favicon.ico') { if (!this._ignore.includes(req.originalUrl)) {
const responseTimeInMs = Date.now() - res.locals.startEpoch const responseTimeInMs = Date.now() - res.locals.startEpoch
if (!this._disableDurationCounter) {
this._httpRequestDurationMicroseconds this._httpRequestDurationMicroseconds
.labels(req.method, req.originalUrl, res.statusCode.toString()) .labels(req.method, req.originalUrl, res.statusCode.toString())
.observe(responseTimeInMs) .observe(responseTimeInMs)
}
if (!this._disableRouteCounter) {
this._numOfRequests.inc({ route: req.originalUrl }) this._numOfRequests.inc({ route: req.originalUrl })
}
if (res.statusCode >= 400) { if (res.statusCode >= 400) {
if (!this._disableErrorCounter) {
this._numOfErrors.inc({ error: res.statusCode }) this._numOfErrors.inc({ error: res.statusCode })
} }
} }
}
}) })
next() next()
} }
...@@ -50,5 +88,4 @@ export class Metrics { ...@@ -50,5 +88,4 @@ export class Metrics {
res.end(Prometheus.register.metrics()) res.end(Prometheus.register.metrics())
} }
} }
export default Metrics export default Metrics
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment