Class: Errsight::Logger

Inherits:
Logger
  • Object
show all
Defined in:
lib/errsight/logger.rb

Overview

A Logger-compatible class that forwards log entries to Errsight and optionally delegates to a backing logger.

Constant Summary collapse

LEVEL_MAP =
{
  DEBUG   => :debug,
  INFO    => :info,
  WARN    => :warning,
  ERROR   => :error,
  FATAL   => :fatal,
  UNKNOWN => :info
}.freeze
LEVEL_ORDER =
%i[debug info warning error fatal].freeze
EXCEPTION_FRAME_RE =

ActionDispatch::DebugExceptions logs a fully-formatted exception report via Rails.logger.fatal — class+msg, then a backtrace. Forwarding that blob as a single Event.message produces a giant title with no real backtrace column. The Rack CaptureMiddleware handles the underlying exception with structured fields, so we suppress these dumps here.

/:\d+:in ['`]/.freeze
EXCEPTION_FRAME_THRESHOLD =
3

Instance Method Summary collapse

Constructor Details

#initialize(backing_logger = nil) ⇒ Logger

Returns a new instance of Logger.



26
27
28
29
# File 'lib/errsight/logger.rb', line 26

def initialize(backing_logger = nil)
  super(IO::NULL)
  @backing_logger = backing_logger
end

Instance Method Details

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



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
74
# File 'lib/errsight/logger.rb', line 31

def add(severity, message = nil, progname = nil, &block)
  # Duck-typed forward — when this Logger is used as a broadcast
  # target by ActiveSupport::BroadcastLogger or the legacy
  # Logger.broadcast extension, the constructor can be called with
  # something that isn't a Logger (an IO, a Tagged-Logger wrapper,
  # etc). Sending #add to an IO raises NoMethodError. Rather than
  # try to enforce the type at construction (every host has its
  # own quirks), we just skip forwarding if the target can't
  # accept #add.
  @backing_logger.add(severity, message, progname, &block) if @backing_logger.respond_to?(:add)

  # Cheap early-return: skip all allocations when Errsight is disabled
  # or this severity is below the configured threshold. Rails.logger can
  # fire thousands of times per request at :debug; this path matters.
  config = Errsight.configuration
  return true unless config.enabled?

  level = LEVEL_MAP[severity] || :info
  return true if LEVEL_ORDER.index(level).to_i < LEVEL_ORDER.index(config.min_level).to_i

  message = block_given? ? yield : message
  message ||= progname
  return true if message.nil?

  message_str = message.to_s
  return true if exception_dump?(message_str)

   = {}
  if (request_id = Thread.current[:errsight_request_id])
    [:request_id] = request_id
  end

  # The Logger sits on Rails.logger's hot path. If Errsight.log raises
  # for any reason — config drift, queue full mid-shutdown, a
  # before_send callback bug — the customer's request handler must
  # not crash because they happened to log a line. Swallow and move
  # on; the original log line still went to @backing_logger above.
  begin
    Errsight.log(level: level, message: message_str, metadata: )
  rescue StandardError
    # best-effort
  end
  true
end