Class: Honeybadger::Agent

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Logging::Helper
Defined in:
lib/honeybadger/agent.rb

Overview

The Honeybadger agent contains all the methods for interacting with the Honeybadger service. It can be used to send notifications to multiple projects in large apps. The global agent instance (Agent.instance) should always be accessed through the Honeybadger singleton.

Context

Context is global by default, meaning agents created via Honeybadger::Agent.new will share context (added via Honeybadger.context or #context) with other agents. This also includes the Rack environment when using the Rack::ErrorNotifier middleware. To localize context for a custom agent, use the local_context: true option when initializing.

Examples:


# Standard usage:
OtherBadger = Honeybadger::Agent.new

# With local context:
OtherBadger = Honeybadger::Agent.new(local_context: true)

OtherBadger.configure do |config|
  config.api_key = 'project api key'
end

begin
  # Risky operation
rescue => e
  OtherBadger.notify(e)
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Agent

Returns a new instance of Agent


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/honeybadger/agent.rb', line 59

def initialize(opts = {})
  if opts.kind_of?(Config)
    @config = opts
    opts = {}
  end

  @context = opts.delete(:context)
  if opts.delete(:local_context)
    @context ||= ContextManager.new
    @breadcrumbs = Breadcrumbs::Collector.new(config)
  end

  @config ||= Config.new(opts)

  init_worker
end

Instance Attribute Details

#configObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


331
332
333
# File 'lib/honeybadger/agent.rb', line 331

def config
  @config
end

#workerObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


402
403
404
# File 'lib/honeybadger/agent.rb', line 402

def worker
  @worker
end

Class Method Details

.instanceObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


50
51
52
# File 'lib/honeybadger/agent.rb', line 50

def self.instance
  @instance
end

.instance=(instance) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


55
56
57
# File 'lib/honeybadger/agent.rb', line 55

def self.instance=(instance)
  @instance = instance
end

Instance Method Details

#add_breadcrumb(message, metadata: {}, category: "custom") ⇒ Object

Appends a breadcrumb to the trace. Use this when you want to add some custom data to your breadcrumb trace in effort to help debugging. If a notice is reported to Honeybadger, all breadcrumbs within the execution path will be appended to the notice. You will be able to view the breadcrumb trace in the Honeybadger interface to see what events led up to the notice.

Examples:

Honeybadger.add_breadcrumb("Email Sent", metadata: { user: user.id, message: message })

Parameters:

  • message (String)

    The message you want to send with the breadcrumb

  • params (Hash)

    extra options for breadcrumb building

Returns:

  • self


273
274
275
276
277
278
279
280
281
282
283
# File 'lib/honeybadger/agent.rb', line 273

def add_breadcrumb(message, metadata: {}, category: "custom")
  params = Util::Sanitizer.new(max_depth: 2).sanitize({
    category: category,
    message: message,
    metadata: 
  })

  breadcrumbs.add!(Breadcrumbs::Breadcrumb.new(params))

  self
end

#backendObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

See Also:


412
# File 'lib/honeybadger/agent.rb', line 412

def_delegators :config, :backend

#backtrace_filter {|line| ... } ⇒ Object

DEPRECATED: Callback to filter backtrace lines. One use for this is to make additional [PROJECT_ROOT] or [GEM_ROOT] substitutions, which are used by Honeybadger when grouping errors and displaying application traces.

Examples:

Honeybadger.backtrace_filter do |line|
  line.gsub(/^\/my\/unknown\/bundle\/path/, "[GEM_ROOT]")
end

Yield Parameters:

  • line (String)

    The backtrace line to modify.

Yield Returns:

  • (String)

    The new (modified) backtrace line.


391
# File 'lib/honeybadger/agent.rb', line 391

def_delegator :config, :backtrace_filter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Direct access to the Breadcrumbs::Collector instance


247
248
249
250
251
# File 'lib/honeybadger/agent.rb', line 247

def breadcrumbs
  return @breadcrumbs if @breadcrumbs

  Thread.current[:__hb_breadcrumbs] ||= Breadcrumbs::Collector.new(config)
end

#check_in(id) ⇒ Boolean

Perform a synchronous check_in.

Examples:

Honeybadger.check_in('1MqIo1')

Parameters:

  • id (String)

    The unique check in id (e.g. '1MqIo1') or the check in url.

Returns:

  • (Boolean)

    true if the check in was successful and false otherwise.


179
180
181
182
183
184
# File 'lib/honeybadger/agent.rb', line 179

def check_in(id)
  # this is to allow check ins even if a url is passed
  check_in_id = id.to_s.strip.gsub(/\/$/, '').split('/').last
  response = backend.check_in(check_in_id)
  response.success?
end

#clear!Object

Clear all transaction scoped data.


229
230
231
232
# File 'lib/honeybadger/agent.rb', line 229

def clear!
  context_manager.clear!
  breadcrumbs.clear!
end

#configure {|Config::Ruby| ... } ⇒ Object

Configure the Honeybadger agent via Ruby.

Examples:

Honeybadger.configure do |config|
  config.api_key = 'project api key'
  config.exceptions.ignore += [CustomError]
end

Yields:


343
# File 'lib/honeybadger/agent.rb', line 343

def_delegator :config, :configure

#context(context = nil) ⇒ self

Save global context for the current request.

Examples:

Honeybadger.context({my_data: 'my value'})

# Inside a Rails controller:
before_action do
  Honeybadger.context({user_id: current_user.id})
end

# Explicit conversion
class User < ActiveRecord::Base
  def to_honeybadger_context
    { user_id: id, user_email: email }
  end
end

user = User.first
Honeybadger.context(user)

# Clearing global context:
Honeybadger.context.clear!

Parameters:

  • context (Hash) (defaults to: nil)

    A Hash of data which will be sent to Honeybadger when an error occurs. If the object responds to #to_honeybadger_context, the return value of that method will be used (explicit conversion). Can include any key/value, but a few keys have a special meaning in Honeybadger.

Options Hash (context):

  • :user_id (String)

    The user ID used by Honeybadger to aggregate user data across occurrences on the error page (optional).

  • :user_email (String)

    The user email address (optional).

  • :tags (String)

    The comma-separated list of tags. When present, tags will be applied to errors with this context (optional).

Returns:

  • (self)

    so that method calls can be chained.


223
224
225
226
# File 'lib/honeybadger/agent.rb', line 223

def context(context = nil)
  context_manager.set_context(context) unless context.nil?
  self
end

#exception_filterObject

DEPRECATED: Callback to ignore exceptions.

See public API documentation for Notice for available attributes.

Examples:

# Ignoring based on error message:
Honeybadger.exception_filter do |notice|
  notice.error_message =~ /sensitive data/
end

# Ignore an entire class of exceptions:
Honeybadger.exception_filter do |notice|
  notice.exception.class < MyError
end

Yield Returns:

  • (Boolean)

    true (to ignore) or false (to send).


362
# File 'lib/honeybadger/agent.rb', line 362

def_delegator :config, :exception_filter

#exception_fingerprintObject

DEPRECATED: Callback to add a custom grouping strategy for exceptions. The return value is hashed and sent to Honeybadger. Errors with the same fingerprint will be grouped.

See public API documentation for Notice for available attributes.

Examples:

Honeybadger.exception_fingerprint do |notice|
  [notice.error_class, notice.component, notice.backtrace.to_s].join(':')
end

Yield Returns:

  • (#to_s)

    The fingerprint of the error.


377
# File 'lib/honeybadger/agent.rb', line 377

def_delegator :config, :exception_fingerprint

#flush { ... } ⇒ Object, Boolean

Flushes all data from workers before returning. This is most useful in tests when using the test backend, where normally the asynchronous nature of this library could create race conditions.

Examples:

# Without a block:
it "sends a notification to Honeybadger" do
  expect {
    Honeybadger.notify(StandardError.new('test backend'))
    Honeybadger.flush
  }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(0)
end

# With a block:
it "sends a notification to Honeybadger" do
  expect {
    Honeybadger.flush do
      49.times do
        Honeybadger.notify(StandardError.new('test backend'))
      end
    end
  }.to change(Honeybadger::Backend::Test.notifications[:notices], :size).by(49)
end

Yields:

  • An optional block to execute (exceptions will propagate after data is flushed).

Returns:

  • (Object, Boolean)

    value of block if block is given, otherwise true on success or false if Honeybadger isn't running.


314
315
316
317
318
319
# File 'lib/honeybadger/agent.rb', line 314

def flush
  return true unless block_given?
  yield
ensure
  worker.flush
end

#get_contextHash?

Get global context for the current request.

Examples:

Honeybadger.context({my_data: 'my value'})
Honeybadger.get_context # => {my_data: 'my value'}

Returns:

  • (Hash, nil)

241
242
243
# File 'lib/honeybadger/agent.rb', line 241

def get_context
  context_manager.get_context
end

#init!(...) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

See Also:


407
# File 'lib/honeybadger/agent.rb', line 407

def_delegators :config, :init!

#notify(exception_or_opts, opts = {}) ⇒ String, false

Sends an exception to Honeybadger. Does not report ignored exceptions by default.

Examples:

# With an exception:
begin
  fail 'oops'
rescue => exception
  Honeybadger.notify(exception, context: {
    my_data: 'value'
  }) # => '-1dfb92ae-9b01-42e9-9c13-31205b70744a'
end

# Custom notification:
Honeybadger.notify('Something went wrong.', {
  error_class: 'MyClass',
  context: {my_data: 'value'}
}) # => '06220c5a-b471-41e5-baeb-de247da45a56'

Parameters:

  • exception_or_opts (Exception, Hash, Object)

    An Exception object, or a Hash of options which is used to build the notice. All other types of objects will be converted to a String and used as the :error_message.

  • opts (Hash) (defaults to: {})

    The options Hash when the first argument is an Exception.

Options Hash (opts):

  • :error_message (String)

    The error message.

  • :error_class (String) — default: 'Notice'

    The class name of the error.

  • :backtrace (Array)

    The backtrace of the error (optional).

  • :fingerprint (String)

    The grouping fingerprint of the exception (optional).

  • :force (Boolean) — default: false

    Always report the exception when true, even when ignored (optional).

  • :tags (String)

    The comma-separated list of tags (optional).

  • :context (Hash)

    The context to associate with the exception (optional).

  • :controller (String)

    The controller name (such as a Rails controller) (optional).

  • :action (String)

    The action name (such as a Rails controller action) (optional).

  • :parameters (Hash)

    The HTTP request paramaters (optional).

  • :session (Hash)

    The HTTP request session (optional).

  • :url (String)

    The HTTP request URL (optional).

  • :cause (Exception)

    The cause for this error (optional).

Returns:

  • (String)

    UUID reference to the notice within Honeybadger.

  • (false)

    when ignored.


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/honeybadger/agent.rb', line 116

def notify(exception_or_opts, opts = {})
  if exception_or_opts.is_a?(Exception)
    opts[:exception] = exception_or_opts
  elsif exception_or_opts.respond_to?(:to_hash)
    opts.merge!(exception_or_opts.to_hash)
  else
    opts[:error_message] = exception_or_opts.to_s
  end

  validate_notify_opts!(opts)

  add_breadcrumb(
    "Honeybadger Notice",
    metadata: opts,
    category: "notice"
  ) if config[:'breadcrumbs.enabled']

  opts[:rack_env] ||= context_manager.get_rack_env
  opts[:global_context] ||= context_manager.get_context
  opts[:breadcrumbs] ||= breadcrumbs.dup

  notice = Notice.new(config, opts)

  config.before_notify_hooks.each do |hook|
    break if notice.halted?
    with_error_handling { hook.call(notice) }
  end

  unless notice.api_key =~ NOT_BLANK
    error { sprintf('Unable to send error report: API key is missing. id=%s', notice.id) }
    return false
  end

  if !opts[:force] && notice.ignore?
    debug { sprintf('ignore notice feature=notices id=%s', notice.id) }
    return false
  end

  if notice.halted?
    debug { 'halted notice feature=notices' }
    return false
  end

  info { sprintf('Reporting error id=%s', notice.id) }

  if opts[:sync]
    send_now(notice)
  else
    push(notice)
  end

  notice.id
end

#stop(force = false) ⇒ Object

Stops the Honeybadger service.

Examples:

Honeybadger.stop # => nil

325
326
327
328
# File 'lib/honeybadger/agent.rb', line 325

def stop(force = false)
  worker.shutdown(force)
  true
end

#with_rack_env(rack_env, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


394
395
396
397
398
399
# File 'lib/honeybadger/agent.rb', line 394

def with_rack_env(rack_env, &block)
  context_manager.set_rack_env(rack_env)
  yield
ensure
  context_manager.set_rack_env(nil)
end