class Honeybadger::Notice

Experimental RBS support (using type sampling data from the type_fusion project).

# sig/honeybadger/notice.rbs

class Honeybadger::Notice
  def cause=: (SQLite3::ConstraintException cause) -> untyped
  def exception_attribute: (Symbol attribute, ?String default, ) -> String
  def from_exception: (Symbol attribute) -> untyped
  def halted?: () -> false
  def ignore_by_origin?: () -> false
  def params_filters: () -> untyped
  def request_hash: () -> untyped
  def send_local_variables?: (Honeybadger::Config config) -> false
end

def as_json(*args)

Returns:
  • (Hash) - JSON representation of notice.

Other tags:
    Api: - private
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

def cause=(cause)

Experimental RBS support (using type sampling data from the type_fusion project).

def cause=: (SQLite3::ConstraintException cause) -> untyped

This signature was generated using 1 sample from 1 application.

def cause=(cause)
  @cause = cause
  @causes = unwrap_causes(cause)
end

def construct_backtrace_filters(opts)

def construct_backtrace_filters(opts)
  [
    config.backtrace_filter
  ].compact | BACKTRACE_FILTERS
end

def construct_context_hash(opts, exception)

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

def construct_request_hash

Returns Hash request data.

Construct the request data.
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

def construct_tags(tags)

def construct_tags(tags)
  ret = []
  Array(tags).flatten.each do |val|
    val.to_s.split(TAG_SEPERATOR).each do |tag|
      tag.gsub!(TAG_SANITIZER, STRING_EMPTY)
      ret << tag if tag =~ NOT_BLANK
    end
  end
  ret
end

def exception_attribute(attribute, default = nil, &block)

Experimental RBS support (using type sampling data from the type_fusion project).

def exception_attribute: (Symbol attribute, ?String default, ) -> String

This signature was generated using 2 samples from 1 application.

Returns attribute value from args or exception, otherwise default.

desired value.
block - An optional block which receives an Exception and returns the
default - Default value if no other value is found (optional).
Exception.
attribute - A Symbol existing as a key in #args and/or attribute on

the #args hash or actual exception (in order of precedence).
Gets a property named "attribute" of an exception, either from
def exception_attribute(attribute, default = nil, &block)
  opts[attribute] || (exception && from_exception(attribute, &block)) || default
end

def exception_cause(exception)

Returns the Exception cause.

exception - Exception to fetch cause from.

Fetch cause from exception.
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

def exception_context(exception)

Returns the Hash context.

Get optional context from exception.
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

def fingerprint_from_opts(opts)

def fingerprint_from_opts(opts)
  callback = opts[:fingerprint]
  callback ||= config.exception_fingerprint
  if callback.respond_to?(:call)
    callback.call(self)
  else
    callback
  end
end

def fingerprint_hash

def fingerprint_hash
  return unless fingerprint
  Digest::SHA1.hexdigest(fingerprint.to_s)
end

def from_exception(attribute)

Experimental RBS support (using type sampling data from the type_fusion project).

def from_exception: (Symbol attribute) -> untyped

This signature was generated using 1 sample from 1 application.

invoked for the value.
If no block is given, a method with the same name as +attribute+ will be

the property.
exception. The block should accept and exception and return the value for
If a block is given, it will be used when getting the property from an

Gets a property named +attribute+ from an exception.
def from_exception(attribute)
  return unless exception
  if block_given?
    yield(exception)
  else
    exception.send(attribute)
  end
end

def halt!

Returns nothing.

Halts the notice and the before_notify callback chain.
def halt!
  @halted ||= true
end

def halted?

Experimental RBS support (using type sampling data from the type_fusion project).

def halted?: () -> false

This signature was generated using 2 samples from 1 application.

Other tags:
    Api: - private
def halted?
  !!@halted
end

def ignore?

Other tags:
    Api: - private
def ignore?
  ignore_by_origin? || ignore_by_class? || ignore_by_callbacks?
end

def ignore_by_callbacks?

def ignore_by_callbacks?
  config.exception_filter &&
    config.exception_filter.call(self)
end

def ignore_by_class?(ignored_class = nil)

Returns true or false.

string or regexp (optional).
ignored_class_name - The name of the ignored class. May be a

Determines if error class should be ignored.
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

def ignore_by_origin?

Experimental RBS support (using type sampling data from the type_fusion project).

def ignore_by_origin?: () -> false

This signature was generated using 1 sample from 1 application.

def ignore_by_origin?
  return false if opts[:origin] != :rake
  return false if config[:'exceptions.rescue_rake']
  true
end

def initialize(config, opts = {})

Other tags:
    Api: - private
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

def local_variables_from_exception(exception, config)

Returns a Hash of local variables.

exception - The Exception containing the bindings stack.

Fetch local variables from first frame of backtrace.
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

def params_filters

Experimental RBS support (using type sampling data from the type_fusion project).

def params_filters: () -> untyped

This signature was generated using 2 samples from 1 application.

def params_filters
  config.params_filters + rails_params_filters
end

def parse_backtrace(backtrace)

Returns the Backtrace.

backtrace - The Array backtrace from exception.

Parse Backtrace from exception backtrace.
def parse_backtrace(backtrace)
  Backtrace.parse(
    backtrace,
    filters: construct_backtrace_filters(opts),
    config: config,
    source_radius: config[:'exceptions.source_radius']
  ).to_a
end

def parsed_backtrace

Returns:
  • (Array<{:number, :file, :method => String}>) -
def parsed_backtrace
  @parsed_backtrace ||= parse_backtrace(backtrace)
end

def prepare_causes(causes)

Returns the Array of causes in Hash payload format.

causes - Array of Cause instances.

Convert list of causes into payload format.
def prepare_causes(causes)
  causes.map {|c|
    {
      class: c.error_class,
      message: c.error_message,
      backtrace: parse_backtrace(c.backtrace)
    }
  }
end

def rails_params_filters

def rails_params_filters
  rack_env && Array(rack_env['action_dispatch.parameter_filter']) or []
end

def request_hash

Experimental RBS support (using type sampling data from the type_fusion project).

def request_hash: () -> untyped

This signature was generated using 2 samples from 1 application.

def request_hash
  @request_hash ||= Util::RequestHash.from_env(rack_env)
end

def s(data)

def s(data)
  Util::Sanitizer.sanitize(data)
end

def sanitized_breadcrumbs

parameters
Sanitize metadata to keep it at a single level and remove any filtered
def sanitized_breadcrumbs
  sanitizer = Util::Sanitizer.new(max_depth: 1, filters: params_filters)
  breadcrumbs.each do |breadcrumb|
    breadcrumb.metadata = sanitizer.sanitize(breadcrumb.metadata)
  end
  breadcrumbs.to_h
end

def send_local_variables?(config)

Experimental RBS support (using type sampling data from the type_fusion project).

def send_local_variables?: (Honeybadger::Config config) -> false

This signature was generated using 1 sample from 1 application.

Returns true to send local_variables.

Should local variables be sent?
def send_local_variables?(config)
  config[:'exceptions.local_variables']
end

def tags=(tags)

def tags=(tags)
  @tags = construct_tags(tags)
end

def to_json(*a)

Returns:
  • (Hash) - The JSON representation of the notice.
def to_json(*a)
  ::JSON.generate(as_json(*a))
end

def unwrap_causes(cause)

Returns the Array of Cause instances.

cause - The first cause to unwrap.

Create a list of causes.
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

def unwrap_exception(exception)

Returns the Exception to report.

exception - The exception which was rescued.

reported.
Unwrap the exception so that original exception is ignored or
def unwrap_exception(exception)
  return exception unless config[:'exceptions.unwrap']
  exception_cause(exception) || exception
end