airbrake 9.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/airbrake.rb +30 -0
- data/lib/airbrake/capistrano.rb +6 -0
- data/lib/airbrake/capistrano/capistrano2.rb +38 -0
- data/lib/airbrake/capistrano/capistrano3.rb +21 -0
- data/lib/airbrake/delayed_job.rb +48 -0
- data/lib/airbrake/logger.rb +101 -0
- data/lib/airbrake/rack.rb +35 -0
- data/lib/airbrake/rack/context_filter.rb +58 -0
- data/lib/airbrake/rack/http_headers_filter.rb +42 -0
- data/lib/airbrake/rack/http_params_filter.rb +25 -0
- data/lib/airbrake/rack/instrumentable.rb +28 -0
- data/lib/airbrake/rack/middleware.rb +100 -0
- data/lib/airbrake/rack/request_body_filter.rb +31 -0
- data/lib/airbrake/rack/request_store.rb +32 -0
- data/lib/airbrake/rack/route_filter.rb +53 -0
- data/lib/airbrake/rack/session_filter.rb +23 -0
- data/lib/airbrake/rack/user.rb +70 -0
- data/lib/airbrake/rack/user_filter.rb +23 -0
- data/lib/airbrake/rails.rb +32 -0
- data/lib/airbrake/rails/action_cable.rb +33 -0
- data/lib/airbrake/rails/action_cable/notify_callback.rb +20 -0
- data/lib/airbrake/rails/action_controller.rb +35 -0
- data/lib/airbrake/rails/action_controller_notify_subscriber.rb +28 -0
- data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +46 -0
- data/lib/airbrake/rails/action_controller_route_subscriber.rb +46 -0
- data/lib/airbrake/rails/active_job.rb +33 -0
- data/lib/airbrake/rails/active_record.rb +34 -0
- data/lib/airbrake/rails/active_record_subscriber.rb +42 -0
- data/lib/airbrake/rails/app.rb +43 -0
- data/lib/airbrake/rails/backtrace_cleaner.rb +10 -0
- data/lib/airbrake/rails/curb.rb +35 -0
- data/lib/airbrake/rails/event.rb +83 -0
- data/lib/airbrake/rails/excon_subscriber.rb +21 -0
- data/lib/airbrake/rails/http.rb +12 -0
- data/lib/airbrake/rails/http_client.rb +10 -0
- data/lib/airbrake/rails/net_http.rb +10 -0
- data/lib/airbrake/rails/railtie.rb +141 -0
- data/lib/airbrake/rails/typhoeus.rb +12 -0
- data/lib/airbrake/rake.rb +63 -0
- data/lib/airbrake/rake/tasks.rb +110 -0
- data/lib/airbrake/resque.rb +29 -0
- data/lib/airbrake/shoryuken.rb +40 -0
- data/lib/airbrake/sidekiq.rb +47 -0
- data/lib/airbrake/sidekiq/retryable_jobs_filter.rb +51 -0
- data/lib/airbrake/sneakers.rb +34 -0
- data/lib/airbrake/version.rb +5 -0
- data/lib/generators/airbrake_generator.rb +23 -0
- data/lib/generators/airbrake_initializer.rb.erb +78 -0
- metadata +416 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
# Monkey-patch to measure request timing.
|
2
|
+
class HTTPClient
|
3
|
+
alias do_get_without_airbrake do_get_block
|
4
|
+
|
5
|
+
def do_get_block(request, proxy, connection, &block)
|
6
|
+
Airbrake::Rack.capture_timing(:http) do
|
7
|
+
do_get_without_airbrake(request, proxy, connection, &block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Monkey-patch Net::HTTP to benchmark it.
|
2
|
+
Net::HTTP.class_eval do
|
3
|
+
alias_method :request_without_airbrake, :request
|
4
|
+
|
5
|
+
def request(request, *args, &block)
|
6
|
+
Airbrake::Rack.capture_timing(:http) do
|
7
|
+
request_without_airbrake(request, *args, &block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Airbrake
|
2
|
+
module Rails
|
3
|
+
# This railtie works for any Rails application that supports railties (Rails
|
4
|
+
# 3.2+ apps). It makes Airbrake Ruby work with Rails and report errors
|
5
|
+
# occurring in the application automatically.
|
6
|
+
class Railtie < ::Rails::Railtie
|
7
|
+
initializer('airbrake.middleware') do |app|
|
8
|
+
# Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is
|
9
|
+
# responsible for logging exceptions and showing a debugging page in
|
10
|
+
# case the request is local. We want to insert our middleware after
|
11
|
+
# DebugExceptions, so we don't notify Airbrake about local requests.
|
12
|
+
|
13
|
+
if ::Rails.version.to_i >= 5
|
14
|
+
# Avoid the warning about deprecated strings.
|
15
|
+
# Insert after DebugExceptions, since ConnectionManagement doesn't
|
16
|
+
# exist in Rails 5 anymore.
|
17
|
+
app.config.middleware.insert_after(
|
18
|
+
ActionDispatch::DebugExceptions,
|
19
|
+
Airbrake::Rack::Middleware
|
20
|
+
)
|
21
|
+
elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement)
|
22
|
+
# Insert after ConnectionManagement to avoid DB connection leakage:
|
23
|
+
# https://github.com/airbrake/airbrake/pull/568
|
24
|
+
app.config.middleware.insert_after(
|
25
|
+
::ActiveRecord::ConnectionAdapters::ConnectionManagement,
|
26
|
+
'Airbrake::Rack::Middleware'
|
27
|
+
)
|
28
|
+
else
|
29
|
+
# Insert after DebugExceptions for apps without ActiveRecord.
|
30
|
+
app.config.middleware.insert_after(
|
31
|
+
ActionDispatch::DebugExceptions,
|
32
|
+
'Airbrake::Rack::Middleware'
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rake_tasks do
|
38
|
+
# Report exceptions occurring in Rake tasks.
|
39
|
+
require 'airbrake/rake'
|
40
|
+
|
41
|
+
# Defines tasks such as `airbrake:test` & `airbrake:deploy`.
|
42
|
+
require 'airbrake/rake/tasks'
|
43
|
+
end
|
44
|
+
|
45
|
+
# rubocop:disable Metrics/BlockLength
|
46
|
+
initializer('airbrake.action_controller') do
|
47
|
+
ActiveSupport.on_load(:action_controller, run_once: true) do
|
48
|
+
# Patches ActionController with methods that allow us to retrieve
|
49
|
+
# interesting request data. Appends that information to notices.
|
50
|
+
require 'airbrake/rails/action_controller'
|
51
|
+
include Airbrake::Rails::ActionController
|
52
|
+
|
53
|
+
if Airbrake::Config.instance.performance_stats
|
54
|
+
# Cache route information for the duration of the request.
|
55
|
+
require 'airbrake/rails/action_controller_route_subscriber'
|
56
|
+
ActiveSupport::Notifications.subscribe(
|
57
|
+
'start_processing.action_controller',
|
58
|
+
Airbrake::Rails::ActionControllerRouteSubscriber.new
|
59
|
+
)
|
60
|
+
|
61
|
+
# Send route stats.
|
62
|
+
require 'airbrake/rails/action_controller_notify_subscriber'
|
63
|
+
ActiveSupport::Notifications.subscribe(
|
64
|
+
'process_action.action_controller',
|
65
|
+
Airbrake::Rails::ActionControllerNotifySubscriber.new
|
66
|
+
)
|
67
|
+
|
68
|
+
# Send performance breakdown: where a request spends its time.
|
69
|
+
require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
|
70
|
+
ActiveSupport::Notifications.subscribe(
|
71
|
+
'process_action.action_controller',
|
72
|
+
Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new
|
73
|
+
)
|
74
|
+
|
75
|
+
require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP)
|
76
|
+
|
77
|
+
if defined?(Curl) && defined?(Curl::CURB_VERSION)
|
78
|
+
require 'airbrake/rails/curb'
|
79
|
+
end
|
80
|
+
|
81
|
+
require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client)
|
82
|
+
require 'airbrake/rails/http_client' if defined?(HTTPClient)
|
83
|
+
require 'airbrake/rails/typhoeus' if defined?(Typhoeus)
|
84
|
+
|
85
|
+
if defined?(Excon)
|
86
|
+
require 'airbrake/rails/excon_subscriber'
|
87
|
+
ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new)
|
88
|
+
::Excon.defaults[:instrumentor] = ActiveSupport::Notifications
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
# rubocop:enable Metrics/BlockLength
|
94
|
+
|
95
|
+
initializer('airbrake.active_record') do
|
96
|
+
ActiveSupport.on_load(:active_record, run_once: true) do
|
97
|
+
# Reports exceptions occurring in some bugged ActiveRecord callbacks.
|
98
|
+
# Applicable only to the versions of Rails lower than 4.2.
|
99
|
+
require 'airbrake/rails/active_record'
|
100
|
+
include Airbrake::Rails::ActiveRecord
|
101
|
+
|
102
|
+
if defined?(ActiveRecord) && Airbrake::Config.instance.query_stats
|
103
|
+
# Send SQL queries.
|
104
|
+
require 'airbrake/rails/active_record_subscriber'
|
105
|
+
ActiveSupport::Notifications.subscribe(
|
106
|
+
'sql.active_record', Airbrake::Rails::ActiveRecordSubscriber.new
|
107
|
+
)
|
108
|
+
|
109
|
+
# Filter out parameters from SQL body.
|
110
|
+
Airbrake.add_performance_filter(
|
111
|
+
Airbrake::Filters::SqlFilter.new(
|
112
|
+
::ActiveRecord::Base.connection_config[:adapter]
|
113
|
+
)
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
initializer('airbrake.active_job') do
|
120
|
+
ActiveSupport.on_load(:active_job, run_once: true) do
|
121
|
+
# Reports exceptions occurring in ActiveJob jobs.
|
122
|
+
require 'airbrake/rails/active_job'
|
123
|
+
include Airbrake::Rails::ActiveJob
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
initializer('airbrake.action_cable') do
|
128
|
+
ActiveSupport.on_load(:action_cable, run_once: true) do
|
129
|
+
# Reports exceptions occurring in ActionCable connections.
|
130
|
+
require 'airbrake/rails/action_cable'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
runner do
|
135
|
+
at_exit do
|
136
|
+
Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# This is not bulletproof, but if this file is executed before a task
|
2
|
+
# definition, we can grab tasks descriptions and locations.
|
3
|
+
# See: https://goo.gl/ksn6PE
|
4
|
+
Rake::TaskManager.record_task_metadata = true
|
5
|
+
|
6
|
+
module Rake
|
7
|
+
# Redefine +Rake::Task#execute+, so it can report errors to Airbrake.
|
8
|
+
class Task
|
9
|
+
# Store the original method to use it later.
|
10
|
+
alias execute_without_airbrake execute
|
11
|
+
|
12
|
+
# A wrapper around the original +#execute+, that catches all errors and
|
13
|
+
# notifies Airbrake.
|
14
|
+
#
|
15
|
+
# rubocop:disable Lint/RescueException
|
16
|
+
def execute(args = nil)
|
17
|
+
execute_without_airbrake(args)
|
18
|
+
rescue Exception => ex
|
19
|
+
notify_airbrake(ex, args)
|
20
|
+
raise ex
|
21
|
+
end
|
22
|
+
# rubocop:enable Lint/RescueException
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def notify_airbrake(exception, args)
|
27
|
+
notice = Airbrake.build_notice(exception)
|
28
|
+
notice[:context][:component] = 'rake'
|
29
|
+
notice[:context][:action] = name
|
30
|
+
notice[:params].merge!(
|
31
|
+
rake_task: task_info,
|
32
|
+
execute_args: args,
|
33
|
+
argv: ARGV.join(' ')
|
34
|
+
)
|
35
|
+
|
36
|
+
Airbrake.notify_sync(notice)
|
37
|
+
end
|
38
|
+
|
39
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
40
|
+
def task_info
|
41
|
+
info = {}
|
42
|
+
|
43
|
+
info[:name] = name
|
44
|
+
info[:timestamp] = timestamp.to_s
|
45
|
+
info[:investigation] = investigation
|
46
|
+
|
47
|
+
info[:full_comment] = full_comment if full_comment
|
48
|
+
info[:arg_names] = arg_names if arg_names.any?
|
49
|
+
info[:arg_description] = arg_description if arg_description
|
50
|
+
info[:locations] = locations if locations.any?
|
51
|
+
info[:sources] = sources if sources.any?
|
52
|
+
|
53
|
+
if prerequisite_tasks.any?
|
54
|
+
info[:prerequisite_tasks] = prerequisite_tasks.map do |p|
|
55
|
+
p.__send__(:task_info)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
info
|
60
|
+
end
|
61
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'airbrake-ruby'
|
2
|
+
|
3
|
+
namespace :airbrake do
|
4
|
+
desc 'Verify your gem installation by sending a test exception'
|
5
|
+
task test: (:environment if defined?(Rails)) do
|
6
|
+
raise Airbrake::Error, 'airbrake-ruby is not configured' unless Airbrake.configured?
|
7
|
+
|
8
|
+
require 'pp'
|
9
|
+
|
10
|
+
response = Airbrake.notify_sync('Exception from the test Rake task')
|
11
|
+
if response['error']
|
12
|
+
puts "Error: #{response['error']}"
|
13
|
+
elsif response.nil? || response['code']
|
14
|
+
puts <<-ERROR.gsub(/^\s+\|/, '')
|
15
|
+
|#{response['type']}: #{response['message']} (#{response['code']})
|
16
|
+
|
|
17
|
+
|Possible problems:
|
18
|
+
| 1. Project id/key is incorrect
|
19
|
+
| 2. Custom filters ignore the exception we try to send
|
20
|
+
| 3. Environment this task runs in is ignored (see `ignored_environments`)
|
21
|
+
|
|
22
|
+
|If nothing works, please file an issue at: https://github.com/airbrake/airbrake/issues
|
23
|
+
ERROR
|
24
|
+
elsif response['url']
|
25
|
+
puts <<-SUCCESS.gsub(/^\s+\|/, '')
|
26
|
+
|A test exception was sent to Airbrake.
|
27
|
+
|Find it here: #{response['url']}
|
28
|
+
SUCCESS
|
29
|
+
else
|
30
|
+
puts <<-ERROR.gsub(/^\s+\|/, '')
|
31
|
+
|Unexpected error occurred. Response from Airbrake:
|
32
|
+
|#{response}
|
33
|
+
ERROR
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Notify Airbrake of a new deploy'
|
38
|
+
task :deploy do
|
39
|
+
if defined?(Rails)
|
40
|
+
initializer = Rails.root.join('config', 'initializers', 'airbrake.rb')
|
41
|
+
|
42
|
+
# Avoid loading the environment to speed up the deploy task and try guess
|
43
|
+
# the initializer file location.
|
44
|
+
if initializer.exist? && !Airbrake.configured?
|
45
|
+
load(initializer)
|
46
|
+
else
|
47
|
+
Rake::Task[:environment].invoke
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
raise Airbrake::Error, 'airbrake-ruby is not configured' unless Airbrake.configured?
|
52
|
+
|
53
|
+
deploy_params = {
|
54
|
+
environment: ENV['ENVIRONMENT'],
|
55
|
+
username: ENV['USERNAME'],
|
56
|
+
revision: ENV['REVISION'],
|
57
|
+
repository: ENV['REPOSITORY'],
|
58
|
+
version: ENV['VERSION']
|
59
|
+
}
|
60
|
+
promise = Airbrake.notify_deploy(deploy_params)
|
61
|
+
promise.then do
|
62
|
+
puts "The #{deploy_params[:environment]} environment was deployed."
|
63
|
+
end
|
64
|
+
promise.rescue { |error| abort(error) }
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Install a Heroku deploy hook to notify Airbrake of deploys'
|
68
|
+
task :install_heroku_deploy_hook do
|
69
|
+
app = ENV['HEROKU_APP']
|
70
|
+
|
71
|
+
config = Bundler.with_clean_env do
|
72
|
+
`heroku config --shell#{ " --app #{app}" if app }`
|
73
|
+
end
|
74
|
+
|
75
|
+
heroku_env = config.each_line.with_object({}) do |line, h|
|
76
|
+
h.merge!(Hash[*line.rstrip.split("\n").flat_map { |v| v.split('=', 2) }])
|
77
|
+
end
|
78
|
+
|
79
|
+
id = heroku_env['AIRBRAKE_PROJECT_ID']
|
80
|
+
key = heroku_env['AIRBRAKE_API_KEY']
|
81
|
+
|
82
|
+
exit!(1) if [id, key].any?(&:nil?)
|
83
|
+
|
84
|
+
unless (env = heroku_env['RAILS_ENV'])
|
85
|
+
env = 'production'
|
86
|
+
puts "Airbrake couldn't identify your app's environment, so the '#{env}'" \
|
87
|
+
" environment will be used."
|
88
|
+
end
|
89
|
+
|
90
|
+
unless (repo = ENV['REPOSITORY_URL'])
|
91
|
+
repo = `git remote get-url origin 2>/dev/null`.chomp
|
92
|
+
if repo.empty?
|
93
|
+
puts "Airbrake couldn't identify your app's repository."
|
94
|
+
else
|
95
|
+
puts "Airbrake couldn't identify your app's repository, so the " \
|
96
|
+
"'origin' remote url '#{repo}' will be used."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
url = "https://airbrake.io/api/v3/projects/#{id}/heroku-deploys?key=#{key}"
|
101
|
+
url << "&environment=#{env}"
|
102
|
+
url << "&repository=#{repo}" unless repo.empty?
|
103
|
+
|
104
|
+
command = %(heroku addons:create deployhooks:http --url="#{url}")
|
105
|
+
command << " --app #{app}" if app
|
106
|
+
|
107
|
+
puts "$ #{command}"
|
108
|
+
Bundler.with_clean_env { puts `#{command}` }
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Resque
|
2
|
+
module Failure
|
3
|
+
# Provides Resque integration with Airbrake.
|
4
|
+
#
|
5
|
+
# @since v5.0.0
|
6
|
+
# @see https://github.com/resque/resque/wiki/Failure-Backends
|
7
|
+
class Airbrake < Base
|
8
|
+
def save
|
9
|
+
::Airbrake.notify_sync(exception, payload) do |notice|
|
10
|
+
notice[:context][:component] = 'resque'
|
11
|
+
notice[:context][:action] = action(payload)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# @return [String] job's name. When ActiveJob is present, retrieve
|
18
|
+
# job_class. When used directly, use worker's name
|
19
|
+
def action(payload)
|
20
|
+
active_job_args = payload['args'].first if payload['args']
|
21
|
+
if active_job_args.is_a?(Hash) && active_job_args['job_class']
|
22
|
+
active_job_args['job_class']
|
23
|
+
else
|
24
|
+
payload['class'].to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Airbrake
|
2
|
+
module Shoryuken
|
3
|
+
# Provides integration with Shoryuken.
|
4
|
+
class ErrorHandler
|
5
|
+
# rubocop:disable Lint/RescueException
|
6
|
+
def call(worker, queue, _sqs_msg, body)
|
7
|
+
yield
|
8
|
+
rescue Exception => exception
|
9
|
+
notify_airbrake(exception, worker, queue, body)
|
10
|
+
|
11
|
+
raise exception
|
12
|
+
end
|
13
|
+
# rubocop:enable Lint/RescueException
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def notify_airbrake(exception, worker, queue, body)
|
18
|
+
Airbrake.notify(exception, notice_context(queue, body)) do |notice|
|
19
|
+
notice[:context][:component] = 'shoryuken'
|
20
|
+
notice[:context][:action] = worker.class.to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def notice_context(queue, body)
|
25
|
+
{
|
26
|
+
queue: queue,
|
27
|
+
body: body.is_a?(Array) ? { batch: body } : { body: body }
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if defined?(::Shoryuken)
|
35
|
+
Shoryuken.configure_server do |config|
|
36
|
+
config.server_middleware do |chain|
|
37
|
+
chain.add Airbrake::Shoryuken::ErrorHandler
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'airbrake/sidekiq/retryable_jobs_filter'
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
module Sidekiq
|
5
|
+
# Provides integration with Sidekiq v2+.
|
6
|
+
class ErrorHandler
|
7
|
+
# rubocop:disable Lint/RescueException
|
8
|
+
def call(_worker, context, _queue)
|
9
|
+
yield
|
10
|
+
rescue Exception => exception
|
11
|
+
notify_airbrake(exception, context)
|
12
|
+
raise exception
|
13
|
+
end
|
14
|
+
# rubocop:enable Lint/RescueException
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def notify_airbrake(exception, context)
|
19
|
+
Airbrake.notify(exception, context) do |notice|
|
20
|
+
notice[:context][:component] = 'sidekiq'
|
21
|
+
notice[:context][:action] = action(context)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String] job's name. When ActiveJob is present, retrieve
|
26
|
+
# job_class. When used directly, use worker's name
|
27
|
+
def action(context)
|
28
|
+
klass = context['class'] || context[:job] && context[:job]['class']
|
29
|
+
return klass unless context[:job] && context[:job]['args'].first.is_a?(Hash)
|
30
|
+
return klass unless (job_class = context[:job]['args'].first['job_class'])
|
31
|
+
job_class
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if Sidekiq::VERSION < '3'
|
38
|
+
Sidekiq.configure_server do |config|
|
39
|
+
config.server_middleware do |chain|
|
40
|
+
chain.add(Airbrake::Sidekiq::ErrorHandler)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
Sidekiq.configure_server do |config|
|
45
|
+
config.error_handlers << Airbrake::Sidekiq::ErrorHandler.new.method(:notify_airbrake)
|
46
|
+
end
|
47
|
+
end
|