2022-07-05 08:43:21 -05:00
|
|
|
import { Application, Request, Response } from 'express'
|
|
|
|
import { Meter, metrics } from '@opentelemetry/api-metrics'
|
|
|
|
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'
|
|
|
|
import { MeterProvider } from '@opentelemetry/sdk-metrics-base'
|
|
|
|
import { logger } from '@server/helpers/logger'
|
|
|
|
import { CONFIG } from '@server/initializers/config'
|
2022-07-19 04:58:19 -05:00
|
|
|
import { JobQueueObserversBuilder, NodeJSObserversBuilder, StatsObserversBuilder } from './metric-helpers'
|
2022-07-05 08:43:21 -05:00
|
|
|
|
|
|
|
class OpenTelemetryMetrics {
|
|
|
|
|
|
|
|
private static instance: OpenTelemetryMetrics
|
|
|
|
|
|
|
|
private meter: Meter
|
|
|
|
|
|
|
|
private onRequestDuration: (req: Request, res: Response) => void
|
|
|
|
|
|
|
|
private constructor () {}
|
|
|
|
|
|
|
|
init (app: Application) {
|
|
|
|
if (CONFIG.OPEN_TELEMETRY.METRICS.ENABLED !== true) return
|
|
|
|
|
|
|
|
app.use((req, res, next) => {
|
|
|
|
res.once('finish', () => {
|
|
|
|
if (!this.onRequestDuration) return
|
|
|
|
|
|
|
|
this.onRequestDuration(req as Request, res as Response)
|
|
|
|
})
|
|
|
|
|
|
|
|
next()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
registerMetrics () {
|
|
|
|
if (CONFIG.OPEN_TELEMETRY.METRICS.ENABLED !== true) return
|
|
|
|
|
|
|
|
logger.info('Registering Open Telemetry metrics')
|
|
|
|
|
|
|
|
const provider = new MeterProvider()
|
|
|
|
|
|
|
|
provider.addMetricReader(new PrometheusExporter({ port: CONFIG.OPEN_TELEMETRY.METRICS.PROMETHEUS_EXPORTER.PORT }))
|
|
|
|
|
|
|
|
metrics.setGlobalMeterProvider(provider)
|
|
|
|
|
|
|
|
this.meter = metrics.getMeter('default')
|
|
|
|
|
|
|
|
this.buildRequestObserver()
|
|
|
|
|
2022-07-19 04:58:19 -05:00
|
|
|
const nodeJSObserversBuilder = new NodeJSObserversBuilder(this.meter, provider)
|
|
|
|
nodeJSObserversBuilder.buildObservers()
|
2022-07-05 08:43:21 -05:00
|
|
|
|
2022-07-19 04:58:19 -05:00
|
|
|
const jobQueueObserversBuilder = new JobQueueObserversBuilder(this.meter)
|
|
|
|
jobQueueObserversBuilder.buildObservers()
|
2022-07-05 08:43:21 -05:00
|
|
|
|
2022-07-19 04:58:19 -05:00
|
|
|
const statsObserversBuilder = new StatsObserversBuilder(this.meter)
|
|
|
|
statsObserversBuilder.buildObservers()
|
2022-07-05 08:43:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
private buildRequestObserver () {
|
|
|
|
const requestDuration = this.meter.createHistogram('http_request_duration_ms', {
|
|
|
|
unit: 'milliseconds',
|
|
|
|
description: 'Duration of HTTP requests in ms'
|
|
|
|
})
|
|
|
|
|
|
|
|
this.onRequestDuration = (req: Request, res: Response) => {
|
|
|
|
const duration = Date.now() - res.locals.requestStart
|
|
|
|
|
|
|
|
requestDuration.record(duration, {
|
|
|
|
path: this.buildRequestPath(req.originalUrl),
|
|
|
|
method: req.method,
|
|
|
|
statusCode: res.statusCode + ''
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private buildRequestPath (path: string) {
|
|
|
|
return path.split('?')[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
static get Instance () {
|
|
|
|
return this.instance || (this.instance = new this())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export {
|
|
|
|
OpenTelemetryMetrics
|
|
|
|
}
|