Skip to content
Snippets Groups Projects
Select Git revision
9 results Searching

versioneer.py

Blame
  • index.ts 4.24 KiB
    import * as express from 'express'
    
    export interface Options {
      ignore: string[]
      disableRouteCounter: boolean
      disableErrorCounter: boolean
      disableDurationCounter: boolean
      disableDefaultMetrics: boolean
    }
    
    export interface CustomMetric {
      name: string
      help: string
      labelNames: string[]
    }
    
    export class Metrics {
      public readonly _ignore: string[]
      public readonly _disableRouteCounter: boolean
      public readonly _disableErrorCounter: boolean
      public readonly _disableDurationCounter: boolean
      public readonly _disableDefaultMetrics: boolean
    
      public readonly _client: any
    
      public readonly _httpRequestDurationMicroseconds: any
      public readonly _numOfRequests: any
      public readonly _numOfErrors: any
    
      public readonly _customMetrics: any
    
      constructor (options: Partial<Options> = {}) {
        this._client = require('prom-client')
        this._customMetrics = {}
    
        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
        }
        if (typeof options.disableDefaultMetrics !== 'undefined') {
          this._disableDefaultMetrics = options.disableDefaultMetrics
        } else {
          this._disableDefaultMetrics = false
        }
        if (!this._disableDefaultMetrics) {
          this._client.collectDefaultMetrics()
        }
        if (!this._disableErrorCounter) {
          this._numOfErrors = new this._client.Counter({
            name: 'numOfErrors',
            help: 'Number of errors',
            labelNames: ['error']
          })
        }
        if (!this._disableRouteCounter) {
          this._numOfRequests = new this._client.Counter({
            name: 'numOfRequests',
            help: 'Number of requests made to a route',
            labelNames: ['route']
          })
        }
        if (!this._disableDurationCounter) {
          this._httpRequestDurationMicroseconds = new this._client.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]
          })
        }
      }
    
      public addCustomMetric = (options: CustomMetric): void => {
        this._customMetrics[options.name] = new this._client.Gauge({
          name: options.name,
          help: options.help,
          labelNames: options.labelNames
        })
      }
    
      public incCustomMetric = (name: string, label: string, value: string): void => {
        const inc: any = {}
        inc[label] = value
        this._customMetrics[name].inc(inc)
      }
    
      public decCustomMetric = (name: string, label: string, value: string): void => {
        const dec: any = {}
        dec[label] = value
        this._customMetrics[name].dec(dec)
      }
    
      public collect = (req: express.Request, res: express.Response, next: express.NextFunction): void => {
        res.locals.startEpoch = Date.now()
        res.on('finish', () => {
          if (!this._ignore.includes(req.originalUrl)) {
            const responseTimeInMs = Date.now() - res.locals.startEpoch
            if (!this._disableDurationCounter) {
              this._httpRequestDurationMicroseconds
                .labels(req.method, req.originalUrl, res.statusCode.toString())
                .observe(responseTimeInMs)
            }
            if (!this._disableRouteCounter) {
              this._numOfRequests.inc({ route: req.originalUrl })
            }
            if (res.statusCode >= 400) {
              if (!this._disableErrorCounter) {
                this._numOfErrors.inc({ error: res.statusCode })
              }
            }
          }
        })
        next()
      }
    
      public endpoint = (req: express.Request, res: express.Response): void => {
        res.set('Content-Type', this._client.register.contentType)
        res.status(200)
        res.end(this._client.register.metrics())
      }
    }
    export default Metrics