Class: Tracelit::RailsLoggerBridge::OTelLogger

Inherits:
Logger
  • Object
show all
Defined in:
lib/tracelit/rails_logger_bridge.rb

Overview

OTelLogger is a Logger subclass whose add method emits an OTel LogRecord instead of writing to an IO device. It is added as a broadcast target so the original Rails logger output is preserved.

The SDK Logger#on_emit defaults context: to OpenTelemetry::Context.current, which automatically correlates the log record to the current active span (trace_id + span_id) without any extra work here.

Instance Method Summary collapse

Constructor Details

#initialize(otel_logger) ⇒ OTelLogger

Returns a new instance of OTelLogger.



53
54
55
56
57
58
59
# File 'lib/tracelit/rails_logger_bridge.rb', line 53

def initialize(otel_logger)
  # Discard output — this logger only emits OTel records
  super(File::NULL)
  @otel_logger = otel_logger
  # Accept all severities so we don't filter below the original logger
  self.level = ::Logger::DEBUG
end

Instance Method Details

#add(severity, message = nil, progname = nil) ⇒ Object Also known as: log



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/tracelit/rails_logger_bridge.rb', line 61

def add(severity, message = nil, progname = nil)
  # Fix 10: Re-entrancy guard. OTel SDK internals can call OpenTelemetry.logger
  # which may route back through Rails.logger → this method. Without the
  # guard, that creates a feedback loop where every OTel internal warning
  # triggers another OTel log emit, infinitely.
  return if Thread.current[:tracelit_logging]

  Thread.current[:tracelit_logging] = true

  severity_number = SEVERITY_MAP[severity.to_i] || 9
  severity_text   = ::Logger::SEV_LABEL[severity.to_i] || "ANY"

  body = if message.nil?
    block_given? ? yield : progname
  else
    message
  end

  @otel_logger.on_emit(
    timestamp:       Time.now,
    severity_number: severity_number,
    severity_text:   severity_text,
    body:            body.to_s
  )
rescue StandardError
  # Never let OTel errors surface to the application
ensure
  Thread.current[:tracelit_logging] = nil
end

#closeObject



92
# File 'lib/tracelit/rails_logger_bridge.rb', line 92

def close; end