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

basic functions complete

parents
Branches
No related tags found
1 merge request!1Master to main
{
"plugins": [
"security",
"eslint-plugin-tsdoc",
"@typescript-eslint/eslint-plugin"
],
"extends": [
"plugin:security/recommended",
"plugin:@typescript-eslint/recommended",
"standard-with-typescript"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"tsdoc/syntax": "warn",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/restrict-template-expressions": ["error", {"allowNumber": true}],
"@typescript-eslint/no-var-requires": "off",
"security/detect-non-literal-fs-filename": "off",
"security/detect-object-injection": "off",
"security/detect-child-process": "off"
}
}
\ No newline at end of file
node_modules/
coverage/
stryker.log
.stryer-tmp
*.DS_Store
dist/
src/config.json
.scannerwork/
# stryker temp files
.stryker-tmp
ho-copy
src/
docs/
\ No newline at end of file
# Metrics
[![pipeline status](https://it-devops-01.br-edv.brnet.int/general/metrics/badges/master/pipeline.svg)](https://it-devops-01.br-edv.brnet.int/general/metrics/commits/master)
[![coverage report](https://it-devops-01.br-edv.brnet.int/general/metrics/badges/master/coverage.svg)](https://it-devops-01.br-edv.brnet.int/general/metrics/commits/master)
[![Quality Gate Status](https://it-devops-01.br-edv.brnet.int:8999/api/project_badges/measure?project=metrics&metric=alert_status)](https://it-devops-01.br-edv.brnet.int:8999/dashboard?id=metrics)
A small express middleware to get base metrics for any node.js app.
## Installation
- `npm config set @br:registry https://npm.br-edv.brnet.int`
- `npm install --save @br/metrics`
## Usage
`import { Metrics } from '@br/metrics'`
`let metrics = new Metrics(options)`
Note: The options Part may be omitted, as all parts are optional.
Before your Routes:
`router.use(metrics.start.bind(metrics))`
And to enable the *_metrics*-Endpoint:
`router.get('/_metrics', metrics.endpoint)`
### Options
TODO: fill options
\ No newline at end of file
# TODO
- config
- tests
- README: options, examples
\ No newline at end of file
'use strict'
import * as http from 'http'
import * as express from 'express'
import { Metrics } from '../../dist/index'
class App {
public app: express.Application
private readonly router: express.Router
public readonly server: http.Server
private readonly metrics: Metrics
constructor (port: number) {
this.app = express()
this.router = express.Router()
this.metrics = new Metrics({})
this.router.use(this.metrics.start.bind(this.metrics))
this.router.get('/favicon.ico', (req, res) => res.status(204)) // No Favicon here
this.router.get('/foo', (req:express.Request, res:express.Response) => {
res.status(200).send('foo')
})
this.router.get('/bar', (req:express.Request, res:express.Response) => {
res.status(200).send('bar')
})
this.router.get('/404', (req:express.Request, res:express.Response) => {
res.status(404).end()
})
this.router.get('/401', (req:express.Request, res:express.Response) => {
res.status(401).end()
})
this.router.get('/_metrics', this.metrics.endpoint)
this.app.use(this.router)
this.server = http.createServer(this.app)
this.server.listen(port)
console.log(`metrics-example is running on Port ${port as number}`)
}
}
export default App
import App from './app'
let app
app = new App(parseInt(process.argv[2]))
console.log(`metrics-example running on Port ${process.argv[2]}`)
module.exports = {
roots: ['<rootDir>/src/'],
preset: 'ts-jest',
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
collectCoverage: true,
coverageReporters: ['json', 'lcov', 'text', 'clover', 'html'],
coverageDirectory: 'docs/coverage',
reporters: [
'default',
['jest-html-reporters', {
publicPath: './docs',
filename: 'test-report.html',
pageTitle: 'BePo Backend :: Test Results'
}]
]
}
Source diff could not be displayed: it is too large. Options to address this: view the blob.
{
"name": "@br/metrics",
"version": "1.0.0",
"description": "A small express middleware to get base metrics for any node.js app",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "jest",
"test:mutation": "stryker run",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint --fix src/**/*.ts",
"sast": "sonar-scanner -Dsonar.projectKey=metrics -Dsonar.sources=src/ -Dsonar.host.url=http://it-devops-01.br-edv.brnet.int:9000 -Dsonar.login=0f940d3f0fc8f7d80aeb3e1ebde7232913a818d3",
"check": "npm audit && npm outdated",
"build": "tsc",
"build:examples": "tsc --project tsconfig-examples.json"
},
"keywords": [
"metrics",
"prometheus"
],
"author": "Dominik Sigmund <dominik.sigmund@br.de>",
"license": "Unlicense",
"dependencies": {
"express": "^4.17.1",
"prom-client": "^12.0.0"
},
"devDependencies": {
"@stryker-mutator/core": "^3.1.0",
"@stryker-mutator/jest-runner": "^3.1.0",
"@stryker-mutator/typescript": "^3.1.0",
"@types/express": "^4.17.4",
"@types/jest": "^25.1.4",
"@types/node": "^13.9.1",
"@types/superagent": "^4.1.7",
"@types/supertest": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"eslint": "^6.8.0",
"eslint-config-standard-with-typescript": "^15.0.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-security": "^1.4.0",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-tsdoc": "^0.2.3",
"husky": "^4.2.3",
"jest": "^25.1.0",
"jest-html-reporters": "^1.2.1",
"standard": "^14.3.3",
"supertest": "^4.0.2",
"ts-jest": "^25.2.1",
"typescript": "^3.8.3"
},
"husky": {
"hooks": {
"pre-push": "npm run lint",
"post-commit": "./ho-copy"
}
}
}
import * as express from 'express'
import Prometheus = require('prom-client')
export class Metrics {
private readonly _options: any
public readonly _httpRequestDurationMicroseconds: any
public readonly _numOfRequests: any
public readonly _numOfErrors: any
constructor (options: any) {
this._options = options
this._httpRequestDurationMicroseconds = new Prometheus.Histogram({
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]
})
this._numOfRequests = new Prometheus.Counter({
name: 'numOfRequests',
help: 'Number of requests made to a route',
labelNames: ['route']
})
this._numOfErrors = new Prometheus.Counter({
name: 'numOfErrors',
help: 'Number of errors',
labelNames: ['error']
})
// TODO: config: ignore routes, disable metrics
}
public start (req: express.Request, res: express.Response, next: express.NextFunction): void {
res.locals.startEpoch = Date.now()
res.on('finish', () => {
if (req.originalUrl !== '/_metrics' && req.originalUrl !== './favicon.ico') {
const responseTimeInMs = Date.now() - res.locals.startEpoch
this._httpRequestDurationMicroseconds
.labels(req.method, req.originalUrl, res.statusCode.toString())
.observe(responseTimeInMs)
this._numOfRequests.inc({ route: req.originalUrl })
if (res.statusCode >= 400) {
this._numOfErrors.inc({ error: res.statusCode })
}
}
})
next()
}
public endpoint (req: express.Request, res: express.Response): void {
res.set('Content-Type', Prometheus.register.contentType)
res.end(Prometheus.register.metrics())
}
}
export default Metrics
{
"$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json",
"mutator": "typescript",
"packageManager": "npm",
"reporters": [
"html",
"clear-text",
"progress",
"dashboard"
],
"htmlReporter": {
"baseDir": "docs/mutation"
},
"testRunner": "jest",
"transpilers": [],
"coverageAnalysis": "off",
"tsconfigFile": "tsconfig.json",
"mutate": [
"src/**/*.ts",
"!src/**/*.spec.ts"
]
}
\ No newline at end of file
{
"compilerOptions": {
"target":"ES6",
"module": "commonjs",
"lib": ["es2017"],
"strict": true,
"declaration": true,
"sourceMap": true,
"outDir": "./examples/dist/",
"rootDir": "./examples/src/",
"resolveJsonModule": true,
"watch": false
},
"exclude": [
"node_modules",
"./examples/dist/",
"./src",
"./dist"
]
}
\ No newline at end of file
{
"compilerOptions": {
"target":"ES6",
"module": "commonjs",
"lib": ["es2017"],
"strict": true,
"declaration": true,
"sourceMap": true,
"outDir": "./dist/",
"rootDir": "./src/",
"resolveJsonModule": true,
"watch": false
},
"exclude": [
"node_modules",
"./dist/",
"./examples"
]
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment