class Raven::Event

Constants

MAX_MESSAGE_SIZE_IN_BYTES

See Sentry server default limits at github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py

REQUIRED_OPTION_KEYS
SDK

Attributes

backtrace[RW]
breadcrumbs[RW]
checksum[RW]
configuration[RW]
context[RW]
environment[RW]
event_id[RW]
extra[RW]
fingerprint[RW]
id[RW]
level[R]
logger[RW]
modules[RW]
platform[RW]
release[RW]
runtime[RW]
sdk[RW]
server_name[RW]
server_os[RW]
tags[RW]
time_spent[R]
timestamp[R]
transaction[RW]
user[RW]

Public Class Methods

captureException(exc, options = {}, &block)
Alias for: from_exception
captureMessage(message, options = {})
Alias for: from_message
capture_exception(exc, options = {}, &block)
Alias for: from_exception
capture_message(message, options = {})
Alias for: from_message
from_exception(exc, options = {}) { |evt| ... } click to toggle source
# File lib/raven/event.rb, line 56
def self.from_exception(exc, options = {}, &block)
  exception_context = if exc.instance_variable_defined?(:@__raven_context)
                        exc.instance_variable_get(:@__raven_context)
                      elsif exc.respond_to?(:raven_context)
                        exc.raven_context
                      else
                        {}
                      end
  options = Raven::Utils::DeepMergeHash.deep_merge(exception_context, options)

  return unless options[:configuration].exception_class_allowed?(exc)

  new(options) do |evt|
    evt.add_exception_interface(exc)
    yield evt if block
  end
end
from_message(message, options = {}) click to toggle source
# File lib/raven/event.rb, line 74
def self.from_message(message, options = {})
  new(options) do |evt|
    evt.message = message, options[:message_params] || []
    if options[:backtrace]
      evt.interface(:stacktrace) do |int|
        int.frames = evt.stacktrace_interface_from(options[:backtrace])
      end
    end
  end
end
Also aliased as: captureMessage, capture_message
new(options) { |self| ... } click to toggle source
# File lib/raven/event.rb, line 23
def initialize(options)
  # Set some simple default values
  self.id            = SecureRandom.uuid.delete("-")
  self.timestamp     = Time.now.utc
  self.level         = :error
  self.logger        = :ruby
  self.platform      = :ruby
  self.sdk           = SDK

  # Set some attributes with empty hashes to allow merging
  @interfaces        = {}
  self.user          = {} # TODO: contexts
  self.extra         = {} # TODO: contexts
  self.server_os     = {} # TODO: contexts
  self.runtime       = {} # TODO: contexts
  self.tags          = {} # TODO: contexts

  unless REQUIRED_OPTION_KEYS.all? { |key| options.key?(key) }
    raise "you must provide configuration, context, and breadcrumbs when initializing a Raven::Event"
  end

  self.configuration = options[:configuration]
  self.context       = options[:context]
  self.breadcrumbs   = options[:breadcrumbs]

  # Allow attributes to be set on the event at initialization
  yield self if block_given?
  options.each_pair { |key, val| public_send("#{key}=", val) unless val.nil? }

  set_core_attributes_from_configuration
  set_core_attributes_from_context
end

Public Instance Methods

[](key) click to toggle source
# File lib/raven/event.rb, line 127
def [](key)
  interface(key)
end
[]=(key, value) click to toggle source
# File lib/raven/event.rb, line 131
def []=(key, value)
  interface(key, value)
end
add_exception_interface(exc) click to toggle source
# File lib/raven/event.rb, line 155
def add_exception_interface(exc)
  interface(:exception) do |exc_int|
    exceptions = Raven::Utils::ExceptionCauseChain.exception_to_array(exc).reverse
    backtraces = Set.new
    exc_int.values = exceptions.map do |e|
      SingleExceptionInterface.new do |int|
        int.type = e.class.to_s
        int.value = e.to_s
        int.module = e.class.to_s.split('::')[0...-1].join('::')

        int.stacktrace =
          if e.backtrace && !backtraces.include?(e.backtrace.object_id)
            backtraces << e.backtrace.object_id
            StacktraceInterface.new do |stacktrace|
              stacktrace.frames = stacktrace_interface_from(e.backtrace)
            end
          end
      end
    end
  end
end
interface(name, value = nil, &block) click to toggle source
# File lib/raven/event.rb, line 119
def interface(name, value = nil, &block)
  int = Interface.registered[name]
  raise(Error, "Unknown interface: #{name}") unless int

  @interfaces[int.sentry_alias] = int.new(value, &block) if value || block
  @interfaces[int.sentry_alias]
end
level=(new_level) click to toggle source
# File lib/raven/event.rb, line 115
def level=(new_level) # needed to meet the Sentry spec
  @level = new_level.to_s == "warn" ? :warning : new_level
end
message() click to toggle source
# File lib/raven/event.rb, line 85
def message
  @interfaces[:logentry]&.unformatted_message
end
message=(args) click to toggle source
# File lib/raven/event.rb, line 89
def message=(args)
  if args.is_a?(Array)
    message, params = args[0], args[0..-1]
  else
    message = args
  end

  unless message.is_a?(String)
    configuration.logger.debug("You're passing a non-string message")
    message = message.to_s
  end

  interface(:message) do |int|
    int.message = message.byteslice(0...MAX_MESSAGE_SIZE_IN_BYTES) # Messages limited to 10kb
    int.params = params
  end
end
stacktrace_interface_from(backtrace) click to toggle source
# File lib/raven/event.rb, line 177
def stacktrace_interface_from(backtrace)
  Backtrace.parse(backtrace, { configuration: configuration }).lines.reverse.each_with_object([]) do |line, memo|
    frame = StacktraceInterface::Frame.new
    frame.abs_path = line.file if line.file
    frame.function = line.method if line.method
    frame.lineno = line.number
    frame.in_app = line.in_app
    frame.module = line.module_name if line.module_name

    if configuration[:context_lines] && frame.abs_path
      frame.pre_context, frame.context_line, frame.post_context = \
        configuration.linecache.get_file_context(frame.abs_path, frame.lineno, configuration[:context_lines])
    end

    memo << frame if frame.filename
  end
end
time_spent=(time) click to toggle source
# File lib/raven/event.rb, line 111
def time_spent=(time)
  @time_spent = time.is_a?(Float) ? (time * 1000).to_i : time
end
timestamp=(time) click to toggle source
# File lib/raven/event.rb, line 107
def timestamp=(time)
  @timestamp = time.is_a?(Time) ? time.strftime('%Y-%m-%dT%H:%M:%S') : time
end
to_hash() click to toggle source
# File lib/raven/event.rb, line 135
def to_hash
  data = [:checksum, :environment, :event_id, :extra, :fingerprint, :level,
          :logger, :message, :modules, :platform, :release, :sdk, :server_name,
          :tags, :time_spent, :timestamp, :transaction, :user].each_with_object({}) do |att, memo|
    memo[att] = public_send(att) if public_send(att)
  end

  data[:breadcrumbs] = @breadcrumbs.to_hash unless @breadcrumbs.empty?

  @interfaces.each_pair do |name, int_data|
    data[name.to_sym] = int_data.to_hash
  end
  data
end
to_json_compatible() click to toggle source
# File lib/raven/event.rb, line 150
def to_json_compatible
  cleaned_hash = async_json_processors.reduce(to_hash) { |a, e| e.process(a) }
  JSON.parse(JSON.generate(cleaned_hash))
end

Private Instance Methods

add_rack_context() click to toggle source
# File lib/raven/event.rb, line 224
def add_rack_context
  interface :http do |int|
    int.from_rack(context.rack_env)
  end
  context.user[:ip_address] = calculate_real_ip_from_rack

  if request_id = Utils::RequestId.read_from(context.rack_env)
    context.tags[:request_id] = request_id
  end
end
async_json_processors() click to toggle source
# File lib/raven/event.rb, line 246
def async_json_processors
  configuration.processors.map { |v| v.new(self) }
end
calculate_real_ip_from_rack() click to toggle source

When behind a proxy (or if the user is using a proxy), we can't use REMOTE_ADDR to determine the Event IP, and must use other headers instead.

# File lib/raven/event.rb, line 237
def calculate_real_ip_from_rack
  Utils::RealIp.new(
    :remote_addr => context.rack_env["REMOTE_ADDR"],
    :client_ip => context.rack_env["HTTP_CLIENT_IP"],
    :real_ip => context.rack_env["HTTP_X_REAL_IP"],
    :forwarded_for => context.rack_env["HTTP_X_FORWARDED_FOR"]
  ).calculate_ip
end
list_gem_specs() click to toggle source
# File lib/raven/event.rb, line 250
def list_gem_specs
  # Older versions of Rubygems don't support iterating over all specs
  Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
end
set_core_attributes_from_configuration() click to toggle source
# File lib/raven/event.rb, line 205
def set_core_attributes_from_configuration
  self.server_name ||= configuration.server_name
  self.release     ||= configuration.release
  self.modules       = list_gem_specs if configuration.send_modules
  self.environment ||= configuration.current_environment
end
set_core_attributes_from_context() click to toggle source
# File lib/raven/event.rb, line 212
def set_core_attributes_from_context
  self.transaction ||= context.transaction.last

  # If this is a Rack event, merge Rack context
  add_rack_context if !self[:http] && context.rack_env

  # Merge contexts
  self.user = context.user.merge(user) # TODO: contexts
  self.extra = context.extra.merge(extra) # TODO: contexts
  self.tags = configuration.tags.merge(context.tags).merge!(tags) # TODO: contexts
end