1 import { SequelizeInstrumentation } from 'opentelemetry-instrumentation-sequelize'
2 import { context, diag, DiagLogLevel, trace } from '@opentelemetry/api'
3 import { JaegerExporter } from '@opentelemetry/exporter-jaeger'
4 import { registerInstrumentations } from '@opentelemetry/instrumentation'
5 import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns'
6 import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'
7 import FsInstrumentation from '@opentelemetry/instrumentation-fs'
8 import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'
9 import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'
10 import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'
11 import { Resource } from '@opentelemetry/resources'
12 import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
13 import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
14 import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
15 import { logger } from '@server/helpers/logger'
16 import { CONFIG } from '@server/initializers/config'
18 const tracer = trace.getTracer('peertube')
20 function registerOpentelemetryTracing () {
21 if (CONFIG.OPEN_TELEMETRY.TRACING.ENABLED !== true) return
23 logger.info('Registering Open Telemetry tracing')
25 const customLogger = (level: string) => {
26 return (message: string, ...args: unknown[]) => {
27 let fullMessage = message
29 for (const arg of args) {
30 if (typeof arg === 'string') fullMessage += arg
34 logger[level](fullMessage)
39 error: customLogger('error'),
40 warn: customLogger('warn'),
41 info: customLogger('info'),
42 debug: customLogger('debug'),
43 verbose: customLogger('verbose')
46 const tracerProvider = new NodeTracerProvider({
47 resource: new Resource({
48 [SemanticResourceAttributes.SERVICE_NAME]: 'peertube'
52 registerInstrumentations({
55 new PgInstrumentation({
56 enhancedDatabaseReporting: true
58 new DnsInstrumentation(),
59 new HttpInstrumentation(),
60 new ExpressInstrumentation(),
61 new IORedisInstrumentation({
62 dbStatementSerializer: function (cmdName, cmdArgs) {
63 return [ cmdName, ...cmdArgs ].join(' ')
66 new FsInstrumentation(),
67 new SequelizeInstrumentation()
71 tracerProvider.addSpanProcessor(
72 new BatchSpanProcessor(
73 new JaegerExporter({ endpoint: CONFIG.OPEN_TELEMETRY.TRACING.JAEGER_EXPORTER.ENDPOINT })
77 tracerProvider.register()
80 async function wrapWithSpanAndContext <T> (spanName: string, cb: () => Promise<T>) {
81 const span = tracer.startSpan(spanName)
82 const activeContext = trace.setSpan(context.active(), span)
84 const result = await context.with(activeContext, () => cb())
91 registerOpentelemetryTracing,
93 wrapWithSpanAndContext