honeybadger 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +13 -0
- data/Gemfile.lock +114 -0
- data/Guardfile +5 -0
- data/MIT-LICENSE +22 -0
- data/README.md +271 -0
- data/Rakefile +261 -0
- data/SUPPORTED_RAILS_VERSIONS +26 -0
- data/TESTING.md +33 -0
- data/features/metal.feature +18 -0
- data/features/rack.feature +56 -0
- data/features/rails.feature +211 -0
- data/features/rake.feature +27 -0
- data/features/sinatra.feature +29 -0
- data/features/step_definitions/file_steps.rb +10 -0
- data/features/step_definitions/metal_steps.rb +23 -0
- data/features/step_definitions/rack_steps.rb +23 -0
- data/features/step_definitions/rails_application_steps.rb +394 -0
- data/features/step_definitions/rake_steps.rb +17 -0
- data/features/support/env.rb +17 -0
- data/features/support/honeybadger_shim.rb.template +8 -0
- data/features/support/rails.rb +201 -0
- data/features/support/rake/Rakefile +68 -0
- data/features/support/terminal.rb +107 -0
- data/generators/honeybadger/honeybadger_generator.rb +94 -0
- data/generators/honeybadger/lib/insert_commands.rb +34 -0
- data/generators/honeybadger/lib/rake_commands.rb +24 -0
- data/generators/honeybadger/templates/capistrano_hook.rb +6 -0
- data/generators/honeybadger/templates/honeybadger_tasks.rake +25 -0
- data/generators/honeybadger/templates/initializer.rb +6 -0
- data/honeybadger.gemspec +109 -0
- data/lib/honeybadger.rb +162 -0
- data/lib/honeybadger/backtrace.rb +123 -0
- data/lib/honeybadger/capistrano.rb +43 -0
- data/lib/honeybadger/configuration.rb +273 -0
- data/lib/honeybadger/notice.rb +314 -0
- data/lib/honeybadger/rack.rb +55 -0
- data/lib/honeybadger/rails.rb +34 -0
- data/lib/honeybadger/rails/action_controller_catcher.rb +30 -0
- data/lib/honeybadger/rails/controller_methods.rb +69 -0
- data/lib/honeybadger/rails/middleware/exceptions_catcher.rb +29 -0
- data/lib/honeybadger/rails3_tasks.rb +84 -0
- data/lib/honeybadger/railtie.rb +45 -0
- data/lib/honeybadger/rake_handler.rb +65 -0
- data/lib/honeybadger/sender.rb +120 -0
- data/lib/honeybadger/shared_tasks.rb +36 -0
- data/lib/honeybadger/tasks.rb +82 -0
- data/lib/honeybadger_tasks.rb +65 -0
- data/lib/rails/generators/honeybadger/honeybadger_generator.rb +99 -0
- data/rails/init.rb +1 -0
- data/resources/README.md +34 -0
- data/resources/ca-bundle.crt +3376 -0
- data/script/integration_test.rb +38 -0
- data/test/test_helper.rb +143 -0
- data/test/unit/backtrace_test.rb +180 -0
- data/test/unit/capistrano_test.rb +34 -0
- data/test/unit/configuration_test.rb +201 -0
- data/test/unit/honeybadger_tasks_test.rb +163 -0
- data/test/unit/logger_test.rb +72 -0
- data/test/unit/notice_test.rb +406 -0
- data/test/unit/notifier_test.rb +245 -0
- data/test/unit/rack_test.rb +56 -0
- data/test/unit/rails/action_controller_catcher_test.rb +300 -0
- data/test/unit/rails_test.rb +35 -0
- data/test/unit/sender_test.rb +257 -0
- metadata +315 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
# Middleware for Rack applications. Any errors raised by the upstream
|
3
|
+
# application will be delivered to Honeybadger and re-raised.
|
4
|
+
#
|
5
|
+
# Synopsis:
|
6
|
+
#
|
7
|
+
# require 'rack'
|
8
|
+
# require 'honeybadger'
|
9
|
+
#
|
10
|
+
# Honeybadger.configure do |config|
|
11
|
+
# config.api_key = 'my_api_key'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# app = Rack::Builder.app do
|
15
|
+
# run lambda { |env| raise "Rack down" }
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# use Honeybadger::Rack
|
19
|
+
# run app
|
20
|
+
#
|
21
|
+
# Use a standard Honeybadger.configure call to configure your api key.
|
22
|
+
class Rack
|
23
|
+
def initialize(app)
|
24
|
+
@app = app
|
25
|
+
Honeybadger.configuration.logger ||= Logger.new STDOUT
|
26
|
+
end
|
27
|
+
|
28
|
+
def ignored_user_agent?(env)
|
29
|
+
true if Honeybadger.
|
30
|
+
configuration.
|
31
|
+
ignore_user_agent.
|
32
|
+
flatten.
|
33
|
+
any? { |ua| ua === env['HTTP_USER_AGENT'] }
|
34
|
+
end
|
35
|
+
|
36
|
+
def notify_honeybadger(exception,env)
|
37
|
+
Honeybadger.notify_or_ignore(exception,:rack_env => env) unless ignored_user_agent?(env)
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(env)
|
41
|
+
begin
|
42
|
+
response = @app.call(env)
|
43
|
+
rescue Exception => raised
|
44
|
+
env['honeybadger.error_id'] = notify_honeybadger(raised,env)
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
|
48
|
+
if env['rack.exception']
|
49
|
+
env['honeybadger.error_id'] = notify_honeybadger(env['rack.exception'],env)
|
50
|
+
end
|
51
|
+
|
52
|
+
response
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'honeybadger'
|
2
|
+
require 'honeybadger/rails/controller_methods'
|
3
|
+
require 'honeybadger/rails/action_controller_catcher'
|
4
|
+
|
5
|
+
module Honeybadger
|
6
|
+
module Rails
|
7
|
+
def self.initialize
|
8
|
+
if defined?(ActionController::Base)
|
9
|
+
ActionController::Base.send(:include, Honeybadger::Rails::ActionControllerCatcher)
|
10
|
+
ActionController::Base.send(:include, Honeybadger::Rails::ControllerMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
rails_logger = if defined?(::Rails.logger)
|
14
|
+
::Rails.logger
|
15
|
+
elsif defined?(RAILS_DEFAULT_LOGGER)
|
16
|
+
RAILS_DEFAULT_LOGGER
|
17
|
+
end
|
18
|
+
|
19
|
+
if defined?(::Rails.configuration) && ::Rails.configuration.respond_to?(:middleware)
|
20
|
+
::Rails.configuration.middleware.insert_after 'ActionController::Failsafe',
|
21
|
+
Honeybadger::Rack
|
22
|
+
end
|
23
|
+
|
24
|
+
Honeybadger.configure(true) do |config|
|
25
|
+
config.logger = rails_logger
|
26
|
+
config.environment_name = defined?(::Rails.env) && ::Rails.env || defined?(RAILS_ENV) && RAILS_ENV
|
27
|
+
config.project_root = defined?(::Rails.root) && ::Rails.root || defined?(RAILS_ROOT) && RAILS_ROOT
|
28
|
+
config.framework = defined?(::Rails.version) && "Rails: #{::Rails.version}" || defined?(::Rails::VERSION::STRING) && "Rails: #{::Rails::VERSION::STRING}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Honeybadger::Rails.initialize
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
module Rails
|
3
|
+
module ActionControllerCatcher
|
4
|
+
|
5
|
+
# Sets up an alias chain to catch exceptions when Rails does
|
6
|
+
def self.included(base) #:nodoc:
|
7
|
+
base.send(:alias_method, :rescue_action_in_public_without_honeybadger, :rescue_action_in_public)
|
8
|
+
base.send(:alias_method, :rescue_action_in_public, :rescue_action_in_public_with_honeybadger)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Overrides the rescue_action method in ActionController::Base, but does not inhibit
|
14
|
+
# any custom processing that is defined with Rails 2's exception helpers.
|
15
|
+
def rescue_action_in_public_with_honeybadger(exception)
|
16
|
+
unless honeybadger_ignore_user_agent?
|
17
|
+
error_id = Honeybadger.notify_or_ignore(exception, honeybadger_request_data)
|
18
|
+
request.env['honeybadger.error_id'] = error_id
|
19
|
+
end
|
20
|
+
rescue_action_in_public_without_honeybadger(exception)
|
21
|
+
end
|
22
|
+
|
23
|
+
def honeybadger_ignore_user_agent? #:nodoc:
|
24
|
+
# Rails 1.2.6 doesn't have request.user_agent, so check for it here
|
25
|
+
user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
|
26
|
+
Honeybadger.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
module Rails
|
3
|
+
module ControllerMethods
|
4
|
+
def honeybadger_request_data
|
5
|
+
{ :parameters => honeybadger_filter_if_filtering(params.to_hash),
|
6
|
+
:session_data => honeybadger_filter_if_filtering(honeybadger_session_data),
|
7
|
+
:controller => params[:controller],
|
8
|
+
:action => params[:action],
|
9
|
+
:url => honeybadger_request_url,
|
10
|
+
:cgi_data => honeybadger_filter_if_filtering(request.env) }
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
# This method should be used for sending manual notifications while you are still
|
16
|
+
# inside the controller. Otherwise it works like Honeybadger.notify.
|
17
|
+
def notify_honeybadger(hash_or_exception)
|
18
|
+
unless honeybadger_local_request?
|
19
|
+
Honeybadger.notify(hash_or_exception, honeybadger_request_data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def honeybadger_local_request?
|
24
|
+
if defined?(::Rails.application.config)
|
25
|
+
::Rails.application.config.consider_all_requests_local || (request.local? && (!request.env["HTTP_X_FORWARDED_FOR"]))
|
26
|
+
else
|
27
|
+
consider_all_requests_local || (local_request? && (!request.env["HTTP_X_FORWARDED_FOR"]))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def honeybadger_ignore_user_agent? #:nodoc:
|
32
|
+
# Rails 1.2.6 doesn't have request.user_agent, so check for it here
|
33
|
+
user_agent = request.respond_to?(:user_agent) ? request.user_agent : request.env["HTTP_USER_AGENT"]
|
34
|
+
Honeybadger.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
|
35
|
+
end
|
36
|
+
|
37
|
+
def honeybadger_filter_if_filtering(hash)
|
38
|
+
return hash if ! hash.is_a?(Hash)
|
39
|
+
|
40
|
+
if respond_to?(:filter_parameters) # Rails 2
|
41
|
+
filter_parameters(hash)
|
42
|
+
elsif defined?(ActionDispatch::Http::ParameterFilter) # Rails 3
|
43
|
+
ActionDispatch::Http::ParameterFilter.new(::Rails.application.config.filter_parameters).filter(hash)
|
44
|
+
else
|
45
|
+
hash
|
46
|
+
end rescue hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def honeybadger_session_data
|
50
|
+
if session.respond_to?(:to_hash)
|
51
|
+
session.to_hash
|
52
|
+
else
|
53
|
+
session.data
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def honeybadger_request_url
|
58
|
+
url = "#{request.protocol}#{request.host}"
|
59
|
+
|
60
|
+
unless [80, 443].include?(request.port)
|
61
|
+
url << ":#{request.port}"
|
62
|
+
end
|
63
|
+
|
64
|
+
url << request.fullpath
|
65
|
+
url
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
module Rails
|
3
|
+
module Middleware
|
4
|
+
module ExceptionsCatcher
|
5
|
+
def self.included(base)
|
6
|
+
base.send(:alias_method_chain,:render_exception,:honeybadger)
|
7
|
+
end
|
8
|
+
|
9
|
+
def skip_user_agent?(env)
|
10
|
+
user_agent = env["HTTP_USER_AGENT"]
|
11
|
+
::Honeybadger.configuration.ignore_user_agent.flatten.any? { |ua| ua === user_agent }
|
12
|
+
rescue
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_exception_with_honeybadger(env,exception)
|
17
|
+
controller = env['action_controller.instance']
|
18
|
+
env['honeybadger.error_id'] = Honeybadger.
|
19
|
+
notify_or_ignore(exception,
|
20
|
+
(controller.try(:honeybadger_request_data) || {:rack_env => env})) unless skip_user_agent?(env)
|
21
|
+
if defined?(controller.rescue_action_in_public_without_honeybadger)
|
22
|
+
controller.rescue_action_in_public_without_honeybadger(exception)
|
23
|
+
end
|
24
|
+
render_exception_without_honeybadger(env,exception)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'honeybadger'
|
2
|
+
require File.join(File.dirname(__FILE__), 'shared_tasks')
|
3
|
+
|
4
|
+
namespace :honeybadger do
|
5
|
+
desc "Verify your gem installation by sending a test exception to the honeybadger service"
|
6
|
+
task :test => [:environment] do
|
7
|
+
Rails.logger = defined?(ActiveSupport::TaggedLogging) ?
|
8
|
+
ActiveSupport::TaggedLogging.new(Logger.new(STDOUT)) :
|
9
|
+
Logger.new(STDOUT)
|
10
|
+
|
11
|
+
Rails.logger.level = Logger::DEBUG
|
12
|
+
Honeybadger.configure(true) do |config|
|
13
|
+
config.logger = Rails.logger
|
14
|
+
end
|
15
|
+
|
16
|
+
require './app/controllers/application_controller'
|
17
|
+
|
18
|
+
class HoneybadgerTestingException < RuntimeError; end
|
19
|
+
|
20
|
+
unless Honeybadger.configuration.api_key
|
21
|
+
puts "Honeybadger needs an API key configured! Check the README to see how to add it."
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
Honeybadger.configuration.development_environments = []
|
26
|
+
|
27
|
+
puts "Configuration:"
|
28
|
+
Honeybadger.configuration.to_hash.each do |key, value|
|
29
|
+
puts sprintf("%25s: %s", key.to_s, value.inspect.slice(0, 55))
|
30
|
+
end
|
31
|
+
|
32
|
+
unless defined?(ApplicationController)
|
33
|
+
puts "No ApplicationController found"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
puts 'Setting up the Controller.'
|
38
|
+
class ApplicationController
|
39
|
+
# This is to bypass any filters that may prevent access to the action.
|
40
|
+
prepend_before_filter :test_honeybadger
|
41
|
+
def test_honeybadger
|
42
|
+
puts "Raising '#{exception_class.name}' to simulate application failure."
|
43
|
+
raise exception_class.new, 'Testing honeybadger via "rake honeybadger:test". If you can see this, it works.'
|
44
|
+
end
|
45
|
+
|
46
|
+
# def rescue_action(exception)
|
47
|
+
# rescue_action_in_public exception
|
48
|
+
# end
|
49
|
+
|
50
|
+
# Ensure we actually have an action to go to.
|
51
|
+
def verify; end
|
52
|
+
|
53
|
+
# def consider_all_requests_local
|
54
|
+
# false
|
55
|
+
# end
|
56
|
+
|
57
|
+
# def local_request?
|
58
|
+
# false
|
59
|
+
# end
|
60
|
+
|
61
|
+
def exception_class
|
62
|
+
exception_name = ENV['EXCEPTION'] || "HoneybadgerTestingException"
|
63
|
+
Object.const_get(exception_name)
|
64
|
+
rescue
|
65
|
+
Object.const_set(exception_name, Class.new(Exception))
|
66
|
+
end
|
67
|
+
|
68
|
+
def logger
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
class HoneybadgerVerificationController < ApplicationController; end
|
73
|
+
|
74
|
+
Rails.application.routes_reloader.execute_if_updated
|
75
|
+
Rails.application.routes.draw do
|
76
|
+
match 'verify' => 'application#verify', :as => 'verify'
|
77
|
+
end
|
78
|
+
|
79
|
+
puts 'Processing request.'
|
80
|
+
env = Rack::MockRequest.env_for("/verify")
|
81
|
+
|
82
|
+
Rails.application.call(env)
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'honeybadger'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Honeybadger
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
rake_tasks do
|
7
|
+
require 'honeybadger/rake_handler'
|
8
|
+
require "honeybadger/rails3_tasks"
|
9
|
+
end
|
10
|
+
|
11
|
+
initializer "honeybadger.use_rack_middleware" do |app|
|
12
|
+
app.config.middleware.insert 0, "Honeybadger::Rack"
|
13
|
+
end
|
14
|
+
|
15
|
+
config.after_initialize do
|
16
|
+
Honeybadger.configure(true) do |config|
|
17
|
+
config.logger ||= ::Rails.logger
|
18
|
+
config.environment_name ||= ::Rails.env
|
19
|
+
config.project_root ||= ::Rails.root
|
20
|
+
config.framework = "Rails: #{::Rails::VERSION::STRING}"
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveSupport.on_load(:action_controller) do
|
24
|
+
# Lazily load action_controller methods
|
25
|
+
#
|
26
|
+
require 'honeybadger/rails/controller_methods'
|
27
|
+
|
28
|
+
include Honeybadger::Rails::ControllerMethods
|
29
|
+
end
|
30
|
+
|
31
|
+
if defined?(::ActionDispatch::DebugExceptions)
|
32
|
+
# We should catch the exceptions in ActionDispatch::DebugExceptions in Rails 3.2.x.
|
33
|
+
#
|
34
|
+
require 'honeybadger/rails/middleware/exceptions_catcher'
|
35
|
+
::ActionDispatch::DebugExceptions.send(:include,Honeybadger::Rails::Middleware::ExceptionsCatcher)
|
36
|
+
elsif defined?(::ActionDispatch::ShowExceptions)
|
37
|
+
# ActionDispatch::DebugExceptions is not defined in Rails 3.0.x and 3.1.x so
|
38
|
+
# catch the exceptions in ShowExceptions.
|
39
|
+
#
|
40
|
+
require 'honeybadger/rails/middleware/exceptions_catcher'
|
41
|
+
::ActionDispatch::ShowExceptions.send(:include,Honeybadger::Rails::Middleware::ExceptionsCatcher)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Patch Rake::Application to handle errors with Honeybadger
|
2
|
+
module Honeybadger::RakeHandler
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
include Rake087Methods unless defined?(Rake::VERSION) && Rake::VERSION >= '0.9.0'
|
6
|
+
alias_method :display_error_message_without_honeybadger, :display_error_message
|
7
|
+
alias_method :display_error_message, :display_error_message_with_honeybadger
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def display_error_message_with_honeybadger(ex)
|
12
|
+
if Honeybadger.sender && Honeybadger.configuration &&
|
13
|
+
(Honeybadger.configuration.rescue_rake_exceptions ||
|
14
|
+
(Honeybadger.configuration.rescue_rake_exceptions===nil && !self.tty_output?))
|
15
|
+
|
16
|
+
Honeybadger.notify_or_ignore(ex, :component => reconstruct_command_line, :cgi_data => ENV)
|
17
|
+
end
|
18
|
+
|
19
|
+
display_error_message_without_honeybadger(ex)
|
20
|
+
end
|
21
|
+
|
22
|
+
def reconstruct_command_line
|
23
|
+
"rake #{ARGV.join( ' ' )}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# This module brings Rake 0.8.7 error handling to 0.9.0 standards
|
27
|
+
module Rake087Methods
|
28
|
+
# Method taken from Rake 0.9.0 source
|
29
|
+
#
|
30
|
+
# Provide standard exception handling for the given block.
|
31
|
+
def standard_exception_handling
|
32
|
+
begin
|
33
|
+
yield
|
34
|
+
rescue SystemExit => ex
|
35
|
+
# Exit silently with current status
|
36
|
+
raise
|
37
|
+
rescue OptionParser::InvalidOption => ex
|
38
|
+
$stderr.puts ex.message
|
39
|
+
exit(false)
|
40
|
+
rescue Exception => ex
|
41
|
+
# Exit with error message
|
42
|
+
display_error_message(ex)
|
43
|
+
exit(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Method extracted from Rake 0.8.7 source
|
48
|
+
def display_error_message(ex)
|
49
|
+
$stderr.puts "#{name} aborted!"
|
50
|
+
$stderr.puts ex.message
|
51
|
+
if options.trace
|
52
|
+
$stderr.puts ex.backtrace.join("\n")
|
53
|
+
else
|
54
|
+
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
55
|
+
$stderr.puts "(See full trace by running task with --trace)"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Rake.application.instance_eval do
|
62
|
+
class << self
|
63
|
+
include Honeybadger::RakeHandler
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Honeybadger
|
2
|
+
class Sender
|
3
|
+
NOTICES_URI = '/v1/notices/'.freeze
|
4
|
+
HTTP_ERRORS = [Timeout::Error,
|
5
|
+
Errno::EINVAL,
|
6
|
+
Errno::ECONNRESET,
|
7
|
+
EOFError,
|
8
|
+
Net::HTTPBadResponse,
|
9
|
+
Net::HTTPHeaderSyntaxError,
|
10
|
+
Net::ProtocolError,
|
11
|
+
Errno::ECONNREFUSED].freeze
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
[ :api_key,
|
15
|
+
:proxy_host,
|
16
|
+
:proxy_port,
|
17
|
+
:proxy_user,
|
18
|
+
:proxy_pass,
|
19
|
+
:protocol,
|
20
|
+
:host,
|
21
|
+
:port,
|
22
|
+
:secure,
|
23
|
+
:use_system_ssl_cert_chain,
|
24
|
+
:http_open_timeout,
|
25
|
+
:http_read_timeout
|
26
|
+
].each do |option|
|
27
|
+
instance_variable_set("@#{option}", options[option])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: Sends the notice data off to Honeybadger for processing.
|
32
|
+
#
|
33
|
+
# data - The JSON notice to be sent off
|
34
|
+
#
|
35
|
+
# Returns nothing
|
36
|
+
def send_to_honeybadger(data)
|
37
|
+
http = setup_http_connection
|
38
|
+
headers = HEADERS
|
39
|
+
|
40
|
+
headers.merge!({ 'X-API-Key' => api_key}) if api_key.present?
|
41
|
+
|
42
|
+
response = begin
|
43
|
+
http.post(url.path, data, headers)
|
44
|
+
rescue *HTTP_ERRORS => e
|
45
|
+
log(:error, "Unable to contact the Honeybadger server. HTTP Error=#{e}")
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
case response
|
50
|
+
when Net::HTTPSuccess then
|
51
|
+
log(:info, "Success: #{response.class}", response)
|
52
|
+
else
|
53
|
+
log(:error, "Failure: #{response.class}", response)
|
54
|
+
end
|
55
|
+
|
56
|
+
if response && response.respond_to?(:body)
|
57
|
+
notice = JSON.parse(response.body)
|
58
|
+
error_id = notice['id']
|
59
|
+
end
|
60
|
+
rescue => e
|
61
|
+
log(:error, "[Honeybadger::Sender#send_to_honeybadger] Cannot send notification. Error: #{e.class} - #{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}")
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
attr_reader :api_key,
|
66
|
+
:proxy_host,
|
67
|
+
:proxy_port,
|
68
|
+
:proxy_user,
|
69
|
+
:proxy_pass,
|
70
|
+
:protocol,
|
71
|
+
:host,
|
72
|
+
:port,
|
73
|
+
:secure,
|
74
|
+
:use_system_ssl_cert_chain,
|
75
|
+
:http_open_timeout,
|
76
|
+
:http_read_timeout
|
77
|
+
|
78
|
+
alias_method :secure?, :secure
|
79
|
+
alias_method :use_system_ssl_cert_chain?, :use_system_ssl_cert_chain
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def url
|
84
|
+
URI.parse("#{protocol}://#{host}:#{port}").merge(NOTICES_URI)
|
85
|
+
end
|
86
|
+
|
87
|
+
def log(level, message, response = nil)
|
88
|
+
logger.send(level, LOG_PREFIX + message) if logger
|
89
|
+
Honeybadger.report_environment_info
|
90
|
+
Honeybadger.report_response_body(response.body) if response && response.respond_to?(:body)
|
91
|
+
end
|
92
|
+
|
93
|
+
def logger
|
94
|
+
Honeybadger.logger
|
95
|
+
end
|
96
|
+
|
97
|
+
def setup_http_connection
|
98
|
+
http =
|
99
|
+
Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass).
|
100
|
+
new(url.host, url.port)
|
101
|
+
|
102
|
+
http.read_timeout = http_read_timeout
|
103
|
+
http.open_timeout = http_open_timeout
|
104
|
+
|
105
|
+
if secure?
|
106
|
+
http.use_ssl = true
|
107
|
+
|
108
|
+
http.ca_file = Honeybadger.configuration.ca_bundle_path
|
109
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
110
|
+
else
|
111
|
+
http.use_ssl = false
|
112
|
+
end
|
113
|
+
|
114
|
+
http
|
115
|
+
rescue => e
|
116
|
+
log(:error, "[Honeybadger::Sender#setup_http_connection] Failure initializing the HTTP connection.\nError: #{e.class} - #{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}")
|
117
|
+
raise e
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|