All files / logger-pino correlation.ts

100% Statements 73/73
86.66% Branches 13/15
100% Functions 2/2
100% Lines 73/73

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 741x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 2x 4x 2x 4x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 1x 3x 1x 1x 1x 1x 1x 1x 1x 3x  
/**
 * Mixin functions that inject trace/span context fields into Pino log records.
 *
 * IMPORTANT for 'datadog' mode: dd-trace MUST be initialized BEFORE this
 * module (and before pino) is first imported. The recommended entrypoint pattern:
 *
 * ```typescript
 * // tracing.ts — must be the FIRST import in main.ts / server entrypoint
 * import ddTrace from 'dd-trace'
 * ddTrace.init({ service: process.env.DD_SERVICE, logInjection: false })
 * ```
 *
 * Then in main.ts:
 * ```typescript
 * import './tracing'           // FIRST
 * import { createPinoLogger } from '@starbemtech/star-node-stack-helper'
 * ```
 */
 
export type CorrelationFields = Record<string, unknown>
 
/**
 * Returns Datadog trace context fields (`dd.trace_id`, `dd.span_id`, etc.)
 * from the currently active dd-trace span.
 * Falls back to empty object if dd-trace is not installed or no span is active.
 */
export function getDatadogCorrelationFields(): CorrelationFields {
  try {
    // Dynamic require — safe peer dep: if not installed, falls through to catch
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const tracer = require('dd-trace')
    const span = tracer?.scope?.()?.active?.()
    if (!span) return {}
    const ctx = span.context?.()
    if (!ctx) return {}
    const traceId: string | undefined = ctx.toTraceId?.()
    const spanId: string | undefined = ctx.toSpanId?.()
    if (!traceId && !spanId) return {}
    return {
      dd: {
        trace_id: traceId,
        span_id: spanId,
        service: process.env['DD_SERVICE'],
        env: process.env['DD_ENV'],
        version: process.env['DD_VERSION'],
      },
    }
  } catch {
    return {}
  }
}
 
/**
 * Returns OpenTelemetry trace context fields (`trace_id`, `span_id`)
 * from the currently active OTel span.
 * Falls back to empty object if @opentelemetry/api is not installed.
 */
export function getOtelCorrelationFields(): CorrelationFields {
  try {
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    const api = require('@opentelemetry/api')
    const span = api?.trace?.getActiveSpan?.()
    if (!span) return {}
    const ctx = span.spanContext?.()
    if (!ctx?.traceId) return {}
    return {
      trace_id: ctx.traceId as string,
      span_id: ctx.spanId as string,
    }
  } catch {
    return {}
  }
}