tracing.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import type { Span, Tracer } from '@opentelemetry/api'
  2. import { logger } from '@server/helpers/logger.js'
  3. import { CONFIG } from '@server/initializers/config.js'
  4. let tracer: Tracer | TrackerMock
  5. async function registerOpentelemetryTracing () {
  6. if (CONFIG.OPEN_TELEMETRY.TRACING.ENABLED !== true) {
  7. tracer = new TrackerMock()
  8. return
  9. }
  10. const { diag, DiagLogLevel, trace } = await import('@opentelemetry/api')
  11. tracer = trace.getTracer('peertube')
  12. const [
  13. { JaegerExporter },
  14. { registerInstrumentations },
  15. DnsInstrumentation,
  16. ExpressInstrumentation,
  17. { FsInstrumentation },
  18. { HttpInstrumentation },
  19. IORedisInstrumentation,
  20. PgInstrumentation,
  21. { SequelizeInstrumentation },
  22. Resource,
  23. BatchSpanProcessor,
  24. NodeTracerProvider,
  25. SemanticResourceAttributes
  26. ] = await Promise.all([
  27. import('@opentelemetry/exporter-jaeger'),
  28. import('@opentelemetry/instrumentation'),
  29. import('@opentelemetry/instrumentation-dns'),
  30. import('@opentelemetry/instrumentation-express'),
  31. import('@opentelemetry/instrumentation-fs'),
  32. import('@opentelemetry/instrumentation-http'),
  33. import('@opentelemetry/instrumentation-ioredis'),
  34. import('@opentelemetry/instrumentation-pg'),
  35. import('opentelemetry-instrumentation-sequelize'),
  36. import('@opentelemetry/resources'),
  37. import('@opentelemetry/sdk-trace-base'),
  38. import('@opentelemetry/sdk-trace-node'),
  39. import('@opentelemetry/semantic-conventions')
  40. ])
  41. logger.info('Registering Open Telemetry tracing')
  42. const customLogger = (level: string) => {
  43. return (message: string, ...args: unknown[]) => {
  44. let fullMessage = message
  45. for (const arg of args) {
  46. if (typeof arg === 'string') fullMessage += arg
  47. else break
  48. }
  49. logger[level](fullMessage)
  50. }
  51. }
  52. diag.setLogger({
  53. error: customLogger('error'),
  54. warn: customLogger('warn'),
  55. info: customLogger('info'),
  56. debug: customLogger('debug'),
  57. verbose: customLogger('verbose')
  58. }, DiagLogLevel.INFO)
  59. const tracerProvider = new NodeTracerProvider.default.NodeTracerProvider({
  60. resource: new Resource.default.Resource({
  61. [SemanticResourceAttributes.default.SemanticResourceAttributes.SERVICE_NAME]: 'peertube'
  62. })
  63. })
  64. registerInstrumentations({
  65. tracerProvider,
  66. instrumentations: [
  67. new PgInstrumentation.default.PgInstrumentation({
  68. enhancedDatabaseReporting: true
  69. }),
  70. new DnsInstrumentation.default.DnsInstrumentation(),
  71. new HttpInstrumentation(),
  72. new ExpressInstrumentation.default.ExpressInstrumentation(),
  73. new IORedisInstrumentation.default.IORedisInstrumentation({
  74. dbStatementSerializer: function (cmdName, cmdArgs) {
  75. return [ cmdName, ...cmdArgs ].join(' ')
  76. }
  77. }),
  78. new FsInstrumentation(),
  79. new SequelizeInstrumentation()
  80. ]
  81. })
  82. tracerProvider.addSpanProcessor(
  83. new BatchSpanProcessor.default.BatchSpanProcessor(
  84. new JaegerExporter({ endpoint: CONFIG.OPEN_TELEMETRY.TRACING.JAEGER_EXPORTER.ENDPOINT })
  85. )
  86. )
  87. tracerProvider.register()
  88. }
  89. async function wrapWithSpanAndContext <T> (spanName: string, cb: () => Promise<T>) {
  90. const { context, trace } = await import('@opentelemetry/api')
  91. if (CONFIG.OPEN_TELEMETRY.TRACING.ENABLED !== true) {
  92. return cb()
  93. }
  94. const span = tracer.startSpan(spanName)
  95. const activeContext = trace.setSpan(context.active(), span as Span)
  96. const result = await context.with(activeContext, () => cb())
  97. span.end()
  98. return result
  99. }
  100. export {
  101. registerOpentelemetryTracing,
  102. tracer,
  103. wrapWithSpanAndContext
  104. }
  105. // ---------------------------------------------------------------------------
  106. // Private
  107. // ---------------------------------------------------------------------------
  108. class TrackerMock {
  109. startSpan () {
  110. return new SpanMock()
  111. }
  112. }
  113. class SpanMock {
  114. end () {
  115. }
  116. }