class Honeybadger::Notice
Constants
- BACKTRACE_FILTERS
@api private A list of backtrace filters to run all the time.
- GEM_ROOT_CACHE
@api private Cache gem path substitutions for backtrace lines.
- PROJECT_ROOT_CACHE
@api private Cache project path substitutions for backtrace lines.
- TAG_SANITIZER
@api private The Regexp used to strip invalid characters from individual tags.
- TAG_SEPERATOR
@api private The String character used to split tag strings.
Attributes
The action (if any) that was called in this request.
The API key used to deliver this notice.
The backtrace from the given exception or hash.
The exception cause if available.
@return [Cause] A list of exception causes (see {Cause})
CGI variables such as HTTP_METHOD.
The component (if any) which was used in this request (usually the controller).
The context Hash.
The component (if any) which was used in this request (usually the controller).
The component (if any) which was used in this request (usually the controller).
Custom details data
The name of the class of error (example: RuntimeError).
The message from the exception, or a general description of the error.
The exception that caused this notice, if any.
Custom fingerprint for error, used to group similar errors together.
The unique ID of this notice which can be used to reference the error in Honeybadger
.
Local variables are extracted from first frame of backtrace.
A hash of parameters from the query string or post body.
A hash of parameters from the query string or post body.
A hash of session data from the request.
The URL at which the error occurred (if any).
Public Class Methods
@api private
# File lib/honeybadger/notice.rb, line 187 def initialize(config, opts = {}) @now = Time.now.utc @pid = Process.pid @id = SecureRandom.uuid @stats = Util::Stats.all @opts = opts @config = config @rack_env = opts.fetch(:rack_env, nil) @request_sanitizer = Util::Sanitizer.new(filters: params_filters) @exception = unwrap_exception(opts[:exception]) self.error_class = exception_attribute(:error_class, 'Notice') {|exception| exception.class.name } self.error_message = exception_attribute(:error_message, 'No message provided') do |exception| message = exception.respond_to?(:detailed_message) ? exception.detailed_message(highlight: false).sub(" (#{exception.class.name})", '') # Gems like error_highlight append the exception class name : exception.message "#{exception.class.name}: #{message}" end self.backtrace = exception_attribute(:backtrace, caller) self.cause = opts.key?(:cause) ? opts[:cause] : (exception_cause(@exception) || $!) self.context = construct_context_hash(opts, exception) self.local_variables = local_variables_from_exception(exception, config) self.api_key = opts[:api_key] || config[:api_key] self.tags = construct_tags(opts[:tags]) | construct_tags(context[:tags]) self.url = opts[:url] || request_hash[:url] || nil self.action = opts[:action] || request_hash[:action] || nil self.component = opts[:controller] || opts[:component] || request_hash[:component] || nil self.params = opts[:parameters] || opts[:params] || request_hash[:params] || {} self.session = opts[:session] || request_hash[:session] || {} self.cgi_data = opts[:cgi_data] || request_hash[:cgi_data] || {} self.details = opts[:details] || {} self.session = opts[:session][:data] if opts[:session] && opts[:session][:data] self.breadcrumbs = opts[:breadcrumbs] || Breadcrumbs::Collector.new(config) # Fingerprint must be calculated last since callback operates on `self`. self.fingerprint = fingerprint_from_opts(opts) end
Public Instance Methods
@api private Template used to create JSON payload.
@return [Hash] JSON representation of notice.
# File lib/honeybadger/notice.rb, line 236 def as_json(*args) request = construct_request_hash request[:context] = s(context) request[:local_variables] = local_variables if local_variables { api_key: s(api_key), notifier: NOTIFIER, breadcrumbs: sanitized_breadcrumbs, error: { token: id, class: s(error_class), message: s(error_message), backtrace: s(parsed_backtrace), fingerprint: fingerprint_hash, tags: s(tags), causes: s(prepare_causes(causes)) }, details: s(details), request: request, server: { project_root: s(config[:root]), revision: s(config[:revision]), environment_name: s(config[:env]), hostname: s(config[:hostname]), stats: stats, time: now, pid: pid } } end
# File lib/honeybadger/notice.rb, line 82 def cause=(cause) @cause = cause @causes = unwrap_causes(cause) end
@api private Determines if this notice will be discarded.
# File lib/honeybadger/notice.rb, line 290 def halted? !!@halted end
@api private Determines if this notice should be ignored.
# File lib/honeybadger/notice.rb, line 277 def ignore? ignore_by_origin? || ignore_by_class? || ignore_by_callbacks? end
The parsed exception backtrace. Lines in this backtrace that are from installed gems have the base path for gem installs replaced by “[GEM_ROOT]”, while those in the project have “[PROJECT_ROOT]”. @return [Array<{:number, :file, :method => String}>]
# File lib/honeybadger/notice.rb, line 151 def parsed_backtrace @parsed_backtrace ||= parse_backtrace(backtrace) end
Converts the notice to JSON.
@return [Hash] The JSON representation of the notice.
# File lib/honeybadger/notice.rb, line 271 def to_json(*a) ::JSON.generate(as_json(*a)) end
Private Instance Methods
# File lib/honeybadger/notice.rb, line 361 def construct_backtrace_filters(opts) [ config.backtrace_filter ].compact | BACKTRACE_FILTERS end
# File lib/honeybadger/notice.rb, line 411 def construct_context_hash(opts, exception) context = {} context.merge!(Context(opts[:global_context])) context.merge!(exception_context(exception)) context.merge!(Context(opts[:context])) context end
Construct the request data.
Returns¶ ↑
Returns Hash request data.
# File lib/honeybadger/notice.rb, line 374 def construct_request_hash request = { url: url, component: component, action: action, params: params, session: session, cgi_data: cgi_data, sanitizer: request_sanitizer } request.delete_if {|k,v| config.excluded_request_keys.include?(k) } Util::RequestPayload.build(request) end
Gets a property named “attribute” of an exception, either from the args hash or actual exception (in order of precedence).
- attribute
-
A Symbol existing as a key in args and/or attribute on Exception.
- default
-
Default value if no other value is found (optional).
- block
-
An optional block which receives an Exception and returns the desired value.
Returns¶ ↑
Returns attribute value from args or exception, otherwise default.
# File lib/honeybadger/notice.rb, line 320 def exception_attribute(attribute, default = nil, &block) opts[attribute] || (exception && from_exception(attribute, &block)) || default end
Fetch cause from exception.
- exception
-
Exception to fetch cause from.
Returns¶ ↑
Returns the Exception cause.
# File lib/honeybadger/notice.rb, line 528 def exception_cause(exception) e = exception if e.respond_to?(:cause) && e.cause && e.cause.is_a?(Exception) e.cause elsif e.respond_to?(:original_exception) && e.original_exception && e.original_exception.is_a?(Exception) e.original_exception elsif e.respond_to?(:continued_exception) && e.continued_exception && e.continued_exception.is_a?(Exception) e.continued_exception end end
Get optional context from exception.
Returns¶ ↑
Returns the Hash context.
# File lib/honeybadger/notice.rb, line 391 def exception_context(exception) # This extra check exists because the exception itself is not expected to # convert to a hash. object = exception if exception.respond_to?(:to_honeybadger_context) object ||= {}.freeze Context(object) end
# File lib/honeybadger/notice.rb, line 419 def fingerprint_from_opts(opts) callback = opts[:fingerprint] callback ||= config.exception_fingerprint if callback.respond_to?(:call) callback.call(self) else callback end end
# File lib/honeybadger/notice.rb, line 430 def fingerprint_hash return unless fingerprint Digest::SHA1.hexdigest(fingerprint.to_s) end
Gets a property named attribute
from an exception.
If a block is given, it will be used when getting the property from an exception. The block should accept and exception and return the value for the property.
If no block is given, a method with the same name as attribute
will be invoked for the value.
# File lib/honeybadger/notice.rb, line 332 def from_exception(attribute) return unless exception if block_given? yield(exception) else exception.send(attribute) end end
# File lib/honeybadger/notice.rb, line 305 def ignore_by_callbacks? config.exception_filter && config.exception_filter.call(self) end
Determines if error class should be ignored.
- ignored_class_name
-
The name of the ignored class. May be a string or regexp (optional).
Returns¶ ↑
Returns true or false.
# File lib/honeybadger/notice.rb, line 348 def ignore_by_class?(ignored_class = nil) @ignore_by_class ||= Proc.new do |ignored_class| case error_class when (ignored_class.respond_to?(:name) ? ignored_class.name : ignored_class) true else exception && ignored_class.is_a?(Class) && exception.class < ignored_class end end ignored_class ? @ignore_by_class.call(ignored_class) : config.ignored_classes.any?(&@ignore_by_class) end
# File lib/honeybadger/notice.rb, line 299 def ignore_by_origin? return false if opts[:origin] != :rake return false if config[:'exceptions.rescue_rake'] true end
Fetch local variables from first frame of backtrace.
- exception
-
The Exception containing the bindings stack.
Returns¶ ↑
Returns a Hash of local variables.
# File lib/honeybadger/notice.rb, line 456 def local_variables_from_exception(exception, config) return nil unless send_local_variables?(config) return {} unless Exception === exception return {} unless exception.respond_to?(:__honeybadger_bindings_stack) return {} if exception.__honeybadger_bindings_stack.empty? if config[:root] binding = exception.__honeybadger_bindings_stack.find { |b| if BINDING_HAS_SOURCE_LOCATION b.source_location[0] else b.eval('__FILE__') end =~ /^#{Regexp.escape(config[:root].to_s)}/ } end binding ||= exception.__honeybadger_bindings_stack[0] vars = binding.eval('local_variables') results = vars.inject([]) { |acc, arg| begin result = binding.eval(arg.to_s) acc << [arg, result] rescue NameError # Do Nothing end acc } result_hash = Hash[results] request_sanitizer.sanitize(result_hash) end
# File lib/honeybadger/notice.rb, line 571 def params_filters config.params_filters + rails_params_filters end
Parse Backtrace
from exception backtrace.
- backtrace
-
The Array backtrace from exception.
Returns¶ ↑
Returns the Backtrace
.
# File lib/honeybadger/notice.rb, line 503 def parse_backtrace(backtrace) Backtrace.parse( backtrace, filters: construct_backtrace_filters(opts), config: config, source_radius: config[:'exceptions.source_radius'] ).to_a end
Convert list of causes into payload format.
- causes
-
Array of
Cause
instances.
Returns¶ ↑
Returns the Array of causes in Hash payload format.
# File lib/honeybadger/notice.rb, line 561 def prepare_causes(causes) causes.map {|c| { class: c.error_class, message: c.error_message, backtrace: parse_backtrace(c.backtrace) } } end
# File lib/honeybadger/notice.rb, line 575 def rails_params_filters rack_env && Array(rack_env['action_dispatch.parameter_filter']) or [] end
# File lib/honeybadger/notice.rb, line 367 def request_hash @request_hash ||= Util::RequestHash.from_env(rack_env) end
# File lib/honeybadger/notice.rb, line 447 def s(data) Util::Sanitizer.sanitize(data) end
Create a list of causes.
- cause
-
The first cause to unwrap.
Returns¶ ↑
Returns the Array of Cause
instances.
# File lib/honeybadger/notice.rb, line 544 def unwrap_causes(cause) causes, c, i = [], cause, 0 while c && i < MAX_EXCEPTION_CAUSES causes << Cause.new(c) i += 1 c = exception_cause(c) end causes end
Unwrap the exception so that original exception is ignored or reported.
- exception
-
The exception which was rescued.
Returns¶ ↑
Returns the Exception to report.
# File lib/honeybadger/notice.rb, line 518 def unwrap_exception(exception) return exception unless config[:'exceptions.unwrap'] exception_cause(exception) || exception end
Deprecated
↑ topAttributes
Excerpt from source file.