class SemanticLogger::Appender::Bugsnag

def bugsnag_notify(exception, hash, level)

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

def call(log, logger)

Returns [Hash] of parameters to send to Bugsnag.
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

def extract_exception(log)

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

def initialize(level: :error, **args, &block)

The Proc must return true or false.
Proc: Only include log messages where the supplied Proc returns true
regular expression. All other messages will be ignored.
RegExp: Only include log messages where the class name matches the supplied.
filter: [Regexp|Proc]

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

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

Create Bugsnag Error / Exception Appender
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
end

def log(log)

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

def log_level(level)

Bugsnag supports: error, warning or info
def log_level(level)
  case level
  when :error, :fatal
    "error"
  when :warn
    "warning"
  else
    "info"
  end
end