class SemanticLogger::Appender::Bugsnag

Public Class Methods

new(level: :error, **args, &block) click to toggle source

Create Bugsnag Error / Exception Appender

Parameters

level: [:trace | :debug | :info | :warn | :error | :fatal]
  Override the log level for this appender.
  Default: :error

formatter: [Object|Proc]
  An instance of a class that implements #call, or a Proc to be used to format
  the output from this appender
  Default: Use the built-in formatter (See: #call)

filter: [Regexp|Proc]
  RegExp: Only include log messages where the class name matches the supplied.
  regular expression. All other messages will be ignored.
  Proc: Only include log messages where the supplied Proc returns true
        The Proc must return true or false.
Calls superclass method SemanticLogger::Subscriber::new
# File lib/semantic_logger/appender/bugsnag.rb, line 32
def initialize(level: :error, **args, &block)
  raise "Bugsnag only supports :info, :warn, or :error log levels" unless %i[info warn error fatal].include?(level)

  # Replace the Bugsnag logger so that we can identify its log messages and not forward them to Bugsnag
  ::Bugsnag.configure { |config| config.logger = SemanticLogger[Bugsnag] }

  super(level: level, **args, &block)
end

Public Instance Methods

call(log, logger) click to toggle source

Returns [Hash] of parameters to send to Bugsnag.

# File lib/semantic_logger/appender/bugsnag.rb, line 42
def call(log, logger)
  hash = SemanticLogger::Formatters::Raw.new.call(log, logger)
  hash.delete(:message) if hash[:exception] && (hash[:message] == hash[:exception][:message])
  hash.delete(:time)
  hash.delete(:level_index)
  hash.delete(:exception)
  hash[:file] = "#{hash[:file]}:#{hash.delete(:line)}" if hash.key?(:file)
  hash
end
log(log) click to toggle source
# File lib/semantic_logger/appender/bugsnag.rb, line 52
def log(log)
  # Ignore logs coming from Bugsnag itself
  return false if log.name == "Bugsnag"

  # Send error messages as Runtime exceptions
  exception = extract_exception(log)
  hash      = formatter.call(log, self)
  bugsnag_notify(exception, hash, log_level(log.level))
  true
end

Private Instance Methods

bugsnag_notify(exception, hash, level) click to toggle source
# File lib/semantic_logger/appender/bugsnag.rb, line 65
def bugsnag_notify(exception, hash, level)
  if ::Bugsnag::VERSION.to_i >= 6
    ::Bugsnag.notify(exception) do |report|
      report.severity = level
      hash.each_pair { |key, value| report.add_tab(key, value) }
    end
  else
    hash[:severity] = level
    ::Bugsnag.notify(exception, hash)
  end
end
extract_exception(log) click to toggle source
# File lib/semantic_logger/appender/bugsnag.rb, line 77
def extract_exception(log)
  if log.exception
    # Manually constructed Exception, without a backtrace.
    log.exception.set_backtrace(log.backtrace) if !log.exception.backtrace && log.backtrace
    return log.exception
  end

  error = RuntimeError.new(log.message)
  error.set_backtrace(log.backtrace) if log.backtrace
  error
end
log_level(level) click to toggle source

Bugsnag supports: error, warning or info

# File lib/semantic_logger/appender/bugsnag.rb, line 90
def log_level(level)
  case level
  when :error, :fatal
    "error"
  when :warn
    "warning"
  else
    "info"
  end
end