class Honeybadger::Plugin

Honeybadger::Plugin defines the API for registering plugins with Honeybadger. Each plugin has requirements which must be satisified before executing the plugin's execution block(s). This allows us to detect optional dependencies and load the plugin for each dependency only if it's present in the application.

See the plugins/ directory for examples of official plugins. If you're interested in developing a plugin for Honeybadger, see the Integration Guide: docs.honeybadger.io/ruby/gem-reference/integration.html

@example

require 'honeybadger/plugin'
require 'honeybadger/ruby'

module Honeybadger
  module Plugins
    # Register your plugin with an optional name. If the name (such as
    # "my_framework") is not provided, Honeybadger will try to infer the name
    # from the current file.
    Plugin.register 'my_framework' do
      requirement do
        # Check to see if the thing you're integrating with is loaded. Return true
        # if it is, or false if it isn't. An exception in this block is equivalent
        # to returning false. Multiple requirement blocks are supported.
        defined?(MyFramework)
      end

      execution do
        # Write your integration. This code will be executed only if all requirement
        # blocks return true. An exception in this block will disable the plugin.
        # Multiple execution blocks are supported.
        MyFramework.on_exception do |exception|
          Honeybadger.notify(exception)
        end
      end
    end
  end
end

Constants

CALLER_FILE

@api private

Attributes

executions[R]

@api private

name[R]

@api private

requirements[R]

@api private

Public Class Methods

instances() click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 52
def instances
  @@instances
end
load!(config) click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 77
def load!(config)
  instances.each_pair do |name, plugin|
    if config.load_plugin?(name)
      plugin.load!(config)
    else
      config.logger.debug(sprintf('skip plugin name=%s reason=disabled', name))
    end
  end
end
name_from_caller(caller) click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 88
def name_from_caller(caller)
  caller && caller[0].match(CALLER_FILE) or
    fail("Unable to determine name from caller: #{caller.inspect}")
  File.basename($1)[/[^\.]+/]
end
new(name) click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 115
def initialize(name)
  @name         = name
  @loaded       = false
  @requirements = []
  @executions   = []
end
register(name = nil, &block) click to toggle source

Register a new plugin with Honeybadger. See {#requirement} and {#execution}.

@example

Honeybadger::Plugin.register 'my_framework' do
  requirement { }
  execution { }
end

@param [String] name The optional name of the plugin. Should use snake_case. The name is inferred from the current file name if omitted.

@return nil

# File lib/honeybadger/plugin.rb, line 69
def register(name = nil, &block)
  name ||= name_from_caller(caller) or
    raise(ArgumentError, 'Plugin name is required, but was nil.')
  instances[key = name.to_sym] and fail("Already registered: #{name}")
  instances[key] = new(name).tap { |d| d.instance_eval(&block) }
end

Public Instance Methods

execution(&block) click to toggle source

Define an execution block. Execution blocks will be executed if all requirement blocks return true.

@example

Honeybadger::Plugin.register 'my_framework' do
  requirement { defined?(MyFramework) }

  execution do
    MyFramework.on_exception {|err| Honeybadger.notify(err) }
  end

  execution do
    # Honeybadger's configuration object is available inside
    # execution blocks. It should generally not be used outside of
    # internal plugins. See +Config+.
    MyFramework.use_middleware(MyMiddleware) if config[:'my_framework.use_middleware']
  end
end

@return nil

# File lib/honeybadger/plugin.rb, line 164
def execution(&block)
  @executions << block
end
load!(config) click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 177
def load!(config)
  if @loaded
    config.logger.debug(sprintf('skip plugin name=%s reason=loaded', name))
    return false
  elsif ok?(config)
    config.logger.debug(sprintf('load plugin name=%s', name))
    @executions.each {|e| Execution.new(config, &e).call }
    @loaded = true
  else
    config.logger.debug(sprintf('skip plugin name=%s reason=requirement', name))
  end

  @loaded
rescue => e
  config.logger.error(sprintf("plugin error name=%s class=%s message=%s\n\t%s", name, e.class, e.message.dump, Array(e.backtrace).join("\n\t")))
  @loaded = true
  false
end
loaded?() click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 197
def loaded?
  @loaded
end
ok?(config) click to toggle source

@api private

# File lib/honeybadger/plugin.rb, line 169
def ok?(config)
  @requirements.all? {|r| Execution.new(config, &r).call }
rescue => e
  config.logger.error(sprintf("plugin error name=%s class=%s message=%s\n\t%s", name, e.class, e.message.dump, Array(e.backtrace).join("\n\t")))
  false
end
requirement(&block) click to toggle source

Define a requirement. All requirement blocks must return true for the plugin to be executed.

@example

Honeybadger::Plugin.register 'my_framework' do
  requirement { defined?(MyFramework) }

  # Honeybadger's configuration object is available inside
  # requirement blocks. It should generally not be used outside of
  # internal plugins. See +Config+.
  requirement { config[:'my_framework.enabled'] }

  execution { }
end

@return nil

# File lib/honeybadger/plugin.rb, line 139
def requirement(&block)
  @requirements << block
end
reset!() click to toggle source

@private Used for testing only; don't normally call this. :)

# File lib/honeybadger/plugin.rb, line 203
def reset!
  @loaded = false
end