class Airbrake::Notice

Represents a chunk of information that is meant to be either sent to Airbrake or ignored completely.

@since v1.0.0

Constants

CONTEXT

@return [Hash{Symbol=>String,Hash}] the information to be displayed in the

Context tab in the dashboard
DEFAULT_SEVERITY

@return [String]

HOSTNAME

@return [String] the name of the host machine

JSON_EXCEPTIONS

@return [Array<StandardError>] the list of possible exceptions that might

be raised when an object is converted to JSON
MAX_NOTICE_SIZE

@return [Integer] the maxium size of the JSON payload in bytes

PAYLOAD_MAX_SIZE

@return [Integer] the maximum size of hashes, arrays and strings in the

notice.
TRUNCATABLE_KEYS

@return [Array<Symbol>] parts of a Notice’s payload that can be modified

by the truncator
WRITABLE_KEYS

@return [Array<Symbol>] the list of keys that can be be overwritten with

{Airbrake::Notice#[]=}

Public Class Methods

new(exception, params = {}) click to toggle source

@api private

# File lib/airbrake-ruby/notice.rb, line 50
def initialize(exception, params = {})
  @config = Airbrake::Config.instance
  @truncator = Airbrake::Truncator.new(PAYLOAD_MAX_SIZE)

  @payload = {
    errors: NestedException.new(exception).as_json,
    context: context(exception),
    environment: {
      program_name: $PROGRAM_NAME,
    },
    session: {},
    params: params,
  }

  stash[:exception] = exception
end

Public Instance Methods

[](key) click to toggle source

Reads a value from notice’s payload.

@return [Object] @raise [Airbrake::Error] if the notice is ignored

# File lib/airbrake-ruby/notice.rb, line 91
def [](key)
  raise_if_ignored
  @payload[key]
end
[]=(key, value) click to toggle source

Writes a value to the payload hash. Restricts unrecognized writes.

@example

notice[:params][:my_param] = 'foobar'

@return [void] @raise [Airbrake::Error] if the notice is ignored @raise [Airbrake::Error] if the key is not recognized @raise [Airbrake::Error] if the root value is not a Hash

# File lib/airbrake-ruby/notice.rb, line 105
def []=(key, value)
  raise_if_ignored

  unless WRITABLE_KEYS.include?(key)
    raise Airbrake::Error,
          ":#{key} is not recognized among #{WRITABLE_KEYS}"
  end

  unless value.respond_to?(:to_hash)
    raise Airbrake::Error, "Got #{value.class} value, wanted a Hash"
  end

  @payload[key] = value.to_hash
end
to_json(*_args) click to toggle source

Converts the notice to JSON. Calls to_json on each object inside notice’s payload. Truncates notices, JSON representation of which is bigger than {MAX_NOTICE_SIZE}.

@return [Hash{String=>String}, nil] @api private

# File lib/airbrake-ruby/notice.rb, line 73
def to_json(*_args)
  loop do
    begin
      json = @payload.to_json
    rescue *JSON_EXCEPTIONS => ex
      logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")
    else
      return json if json && json.bytesize <= MAX_NOTICE_SIZE
    end

    break if truncate == 0
  end
end

Private Instance Methods

context(exception) click to toggle source
# File lib/airbrake-ruby/notice.rb, line 122
def context(exception)
  {
    version: @config.app_version,
    versions: @config.versions,
    # We ensure that root_directory is always a String, so it can always be
    # converted to JSON in a predictable manner (when it's a Pathname and in
    # Rails environment, it converts to unexpected JSON).
    rootDirectory: @config.root_directory.to_s,
    environment: @config.environment,

    # Make sure we always send hostname.
    hostname: HOSTNAME,

    severity: DEFAULT_SEVERITY,
    error_message: @truncator.truncate(exception.message),
  }.merge(CONTEXT).delete_if { |_key, val| val.nil? || val.empty? }
end
truncate() click to toggle source
# File lib/airbrake-ruby/notice.rb, line 140
def truncate
  TRUNCATABLE_KEYS.each do |key|
    @payload[key] = @truncator.truncate(@payload[key])
  end

  new_max_size = @truncator.reduce_max_size
  if new_max_size == 0
    logger.error(
      "#{LOG_LABEL} truncation failed. File an issue at " \
      "https://github.com/airbrake/airbrake-ruby " \
      "and attach the following payload: #{@payload}",
    )
  end

  new_max_size
end