80 lines
1.6 KiB
Ruby
80 lines
1.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Released under the MIT License.
|
|
# Copyright, 2019-2024, by Samuel Williams.
|
|
# Copyright, 2021, by Robert Schulze.
|
|
# Copyright, 2024, by Patrik Wenger.
|
|
|
|
require_relative "generic"
|
|
|
|
module Console
|
|
module Event
|
|
# Represents a failure event.
|
|
#
|
|
# ```ruby
|
|
# Console::Event::Failure.for(exception).emit(self)
|
|
# ```
|
|
class Failure < Generic
|
|
def self.default_root
|
|
Dir.getwd
|
|
rescue # e.g. Errno::EMFILE
|
|
nil
|
|
end
|
|
|
|
def self.for(exception)
|
|
self.new(exception, self.default_root)
|
|
end
|
|
|
|
def self.log(subject, exception, **options)
|
|
Console.error(subject, **self.for(exception).to_hash, **options)
|
|
end
|
|
|
|
attr_reader :exception
|
|
|
|
def initialize(exception, root = Dir.getwd)
|
|
@exception = exception
|
|
@root = root
|
|
end
|
|
|
|
def to_hash
|
|
Hash.new.tap do |hash|
|
|
hash[:type] = :failure
|
|
hash[:root] = @root if @root
|
|
extract(@exception, hash)
|
|
end
|
|
end
|
|
|
|
def emit(*arguments, **options)
|
|
options[:severity] ||= :error
|
|
|
|
super
|
|
end
|
|
|
|
private
|
|
|
|
def extract(exception, hash)
|
|
hash[:class] = exception.class.name
|
|
|
|
if exception.respond_to?(:detailed_message)
|
|
message = exception.detailed_message
|
|
|
|
# We want to remove the trailling exception class as we format it differently:
|
|
message.sub!(/\s*\(.*?\)$/, "")
|
|
|
|
hash[:message] = message
|
|
else
|
|
hash[:message] = exception.message
|
|
end
|
|
|
|
hash[:backtrace] = exception.backtrace
|
|
|
|
if cause = exception.cause
|
|
hash[:cause] = Hash.new.tap do |cause_hash|
|
|
extract(cause, cause_hash)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|