module Raven

Inspired by Rails' and Airbrake's backtrace parsers.

A much simpler source line cacher because linecache sucks at platform compat

frozen_string_literal: true

Some parts adapted from golang.org/src/pkg/json/decode.go and golang.org/src/pkg/utf8/utf8.go

frozen_string_literal: true

Constants

AVAILABLE_INTEGRATIONS
INTERFACES

TODO: a constant isn't appropriate here, refactor

VERSION

Attributes

client[W]

The client object is responsible for delivering formatted data to the Sentry server. Must respond to send. See Raven::Client.

configuration[W]

A Raven configuration object. Must act like a hash and return sensible values for all Raven configuration options. See Raven::Configuration.

Public Class Methods

annotate(exc, options = {})
Alias for: annotate_exception
annotateException(exc, options = {})
Alias for: annotate_exception
annotate_exception(exc, options = {}) click to toggle source

Provides extra context to the exception prior to it being handled by Raven. An exception can have multiple annotations, which are merged together.

The options (annotation) is treated the same as the “options“ parameter to “capture_exception“ or “Event.from_exception“, and can contain the same “:user“, “:tags“, etc. options as these methods.

These will be merged with the “options“ parameter to “Event.from_exception“ at the top of execution.

@example

begin
  raise "Hello"
rescue => exc
  Raven.annotate_exception(exc, :user => { 'id' => 1,
                           'email' => 'foo@example.com' })
end
# File lib/raven/base.rb, line 154
def annotate_exception(exc, options = {})
  notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {}
  notes.merge!(options)
  exc.instance_variable_set(:@__raven_context, notes)
  exc
end
Also aliased as: annotateException, annotate
capture(options = {}) { || ... } click to toggle source

Capture and process any exceptions from the given block, or globally if no block is given

@example

Raven.capture do
  MyApp.run
end
# File lib/raven/base.rb, line 95
def capture(options = {})
  if block_given?
    begin
      yield
    rescue Error
      raise # Don't capture Raven errors
    rescue Exception => e
      capture_exception(e, options)
      raise
    end
  else
    install_at_exit_hook(options)
  end
end
captureException(obj, options = {})

For cross-language compat

Alias for: capture_exception
captureMessage(obj, options = {})
Alias for: capture_message
capture_exception(obj, options = {})
Also aliased as: captureException
Alias for: capture_type
capture_message(obj, options = {})
Also aliased as: captureMessage
Alias for: capture_type
capture_type(obj, options = {}) { |evt| ... } click to toggle source
# File lib/raven/base.rb, line 110
def capture_type(obj, options = {})
  return false unless should_capture?(obj)
  message_or_exc = obj.is_a?(String) ? "message" : "exception"
  if (evt = Event.send("from_" + message_or_exc, obj, options))
    yield evt if block_given?
    if configuration.async?
      configuration.async.call(evt)
    else
      send_event(evt)
    end

    evt
  end
end
client() click to toggle source

The client object is responsible for delivering formatted data to the Sentry server.

# File lib/raven/base.rb, line 50
def client
  @client ||= Client.new(configuration)
end
configuration() click to toggle source

The configuration object. @see ::configure

# File lib/raven/base.rb, line 45
def configuration
  @configuration ||= Configuration.new
end
configure() { |configuration| ... } click to toggle source

Call this method to modify defaults in your initializers.

@example

Raven.configure do |config|
  config.server = 'http://...'
end
# File lib/raven/base.rb, line 71
def configure
  yield(configuration) if block_given?

  self.client = Client.new(configuration)
  report_status
  self.client
end
context() click to toggle source
# File lib/raven/base.rb, line 35
def context
  Context.current
end
extra_context(options = nil) click to toggle source

Bind extra context. Merges with existing context (if any).

Extra context shows up as Additional Data within Sentry, and is completely arbitrary.

@example

Raven.extra_context('my_custom_data' => 'value')
# File lib/raven/base.rb, line 189
def extra_context(options = nil)
  self.context.extra.merge!(options || {})
end
find_interface(name) click to toggle source
# File lib/raven/interfaces.rb, line 31
def self.find_interface(name)
  INTERFACES[name.to_s]
end
inject() click to toggle source

Injects various integrations. Default behavior: inject all available integrations

# File lib/raven/base.rb, line 201
def inject
  inject_only(*Raven::AVAILABLE_INTEGRATIONS)
end
inject_only(*only_integrations) click to toggle source
# File lib/raven/base.rb, line 210
def inject_only(*only_integrations)
  only_integrations = only_integrations.map(&:to_s)
  integrations_to_load = Raven::AVAILABLE_INTEGRATIONS & only_integrations
  not_found_integrations = only_integrations - integrations_to_load
  if not_found_integrations.any?
    self.logger.warn "Integrations do not exist: #{not_found_integrations.join ', '}"
  end
  integrations_to_load &= Gem.loaded_specs.keys
  # TODO(dcramer): integrations should have some additional checks baked-in
  # or we should break them out into their own repos. Specifically both the
  # rails and delayed_job checks are not always valid (i.e. Rails 2.3) and
  # https://github.com/getsentry/raven-ruby/issues/180
  integrations_to_load.each do |integration|
    load_integration(integration)
  end
end
inject_without(*exclude_integrations) click to toggle source
# File lib/raven/base.rb, line 205
def inject_without(*exclude_integrations)
  include_integrations = Raven::AVAILABLE_INTEGRATIONS - exclude_integrations.map(&:to_s)
  inject_only(*include_integrations)
end
load_integration(integration) click to toggle source
# File lib/raven/base.rb, line 227
def load_integration(integration)
  require "raven/integrations/#{integration}"
rescue Exception => error
  self.logger.warn "Unable to load raven/integrations/#{integration}: #{error}"
end
logger() click to toggle source
# File lib/raven/base.rb, line 39
def logger
  @logger ||= Logger.new
end
rack_context(env) click to toggle source
# File lib/raven/base.rb, line 193
def rack_context(env)
  if env.empty?
    env = nil
  end
  self.context.rack_env = env
end
register_interface(mapping) click to toggle source
# File lib/raven/interfaces.rb, line 24
def self.register_interface(mapping)
  mapping.each_pair do |key, klass|
    INTERFACES[key.to_s] = klass
    INTERFACES[klass.name] = klass
  end
end
report_ready()
Alias for: report_status
report_status() click to toggle source

Tell the log that the client is good to go

# File lib/raven/base.rb, line 55
def report_status
  return if client.configuration.silence_ready
  if client.configuration.send_in_current_environment?
    logger.info "Raven #{VERSION} ready to catch errors"
  else
    logger.info "Raven #{VERSION} configured not to send errors."
  end
end
Also aliased as: report_ready
send_event(event) click to toggle source

Send an event to the configured Sentry server

@example

evt = Raven::Event.new(:message => "An error")
Raven.send_event(evt)
# File lib/raven/base.rb, line 84
def send_event(event)
  client.send_event(event)
end
should_capture?(message_or_exc) click to toggle source
# File lib/raven/base.rb, line 127
def should_capture?(message_or_exc)
  if configuration.should_capture
    configuration.should_capture.call(*[message_or_exc])
  else
    true
  end
end
tags_context(options = nil) click to toggle source

Bind tags context. Merges with existing context (if any).

Tags are key / value pairs which generally represent things like application version, environment, role, and server names.

@example

Raven.tags_context('my_custom_tag' => 'tag_value')
# File lib/raven/base.rb, line 179
def tags_context(options = nil)
  self.context.tags.merge!(options || {})
end
user_context(options = nil) click to toggle source

Bind user context. Merges with existing context (if any).

It is recommending that you send at least the “id“ and “email“ values. All other values are arbitrary.

@example

Raven.user_context('id' => 1, 'email' => 'foo@example.com')
# File lib/raven/base.rb, line 168
def user_context(options = nil)
  self.context.user = options || {}
end

Private Class Methods

install_at_exit_hook(options) click to toggle source
# File lib/raven/base.rb, line 241
def install_at_exit_hook(options)
  at_exit do
    if $!
      logger.debug "Caught a post-mortem exception: #{$!.inspect}"
      capture_exception($!, options)
    end
  end
end