airbrake 3.1.6 → 11.0.0
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 +23 -150
- data/lib/airbrake/capistrano.rb +6 -42
- data/lib/airbrake/capistrano/capistrano2.rb +40 -0
- data/lib/airbrake/capistrano/capistrano3.rb +23 -0
- data/lib/airbrake/delayed_job.rb +66 -0
- data/lib/airbrake/logger.rb +103 -0
- data/lib/airbrake/rack.rb +30 -45
- data/lib/airbrake/rack/context_filter.rb +65 -0
- data/lib/airbrake/rack/http_headers_filter.rb +44 -0
- data/lib/airbrake/rack/http_params_filter.rb +27 -0
- data/lib/airbrake/rack/instrumentable.rb +136 -0
- data/lib/airbrake/rack/middleware.rb +102 -0
- data/lib/airbrake/rack/request_body_filter.rb +33 -0
- data/lib/airbrake/rack/request_store.rb +34 -0
- data/lib/airbrake/rack/route_filter.rb +51 -0
- data/lib/airbrake/rack/session_filter.rb +25 -0
- data/lib/airbrake/rack/user.rb +74 -0
- data/lib/airbrake/rack/user_filter.rb +25 -0
- data/lib/airbrake/rails.rb +25 -31
- data/lib/airbrake/rails/action_cable.rb +35 -0
- data/lib/airbrake/rails/action_cable/notify_callback.rb +22 -0
- data/lib/airbrake/rails/action_controller.rb +40 -0
- data/lib/airbrake/rails/action_controller_notify_subscriber.rb +32 -0
- data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +51 -0
- data/lib/airbrake/rails/action_controller_route_subscriber.rb +33 -0
- data/lib/airbrake/rails/active_job.rb +50 -0
- data/lib/airbrake/rails/active_record.rb +36 -0
- data/lib/airbrake/rails/active_record_subscriber.rb +46 -0
- data/lib/airbrake/rails/app.rb +78 -0
- data/lib/airbrake/rails/backtrace_cleaner.rb +23 -0
- data/lib/airbrake/rails/curb.rb +32 -0
- data/lib/airbrake/rails/event.rb +81 -0
- data/lib/airbrake/rails/excon_subscriber.rb +25 -0
- data/lib/airbrake/rails/http.rb +14 -0
- data/lib/airbrake/rails/http_client.rb +16 -0
- data/lib/airbrake/rails/net_http.rb +18 -0
- data/lib/airbrake/rails/railtie.rb +151 -0
- data/lib/airbrake/rails/typhoeus.rb +16 -0
- data/lib/airbrake/rake.rb +65 -0
- data/lib/airbrake/rake/tasks.rb +112 -0
- data/lib/airbrake/resque.rb +61 -0
- data/lib/airbrake/shoryuken.rb +54 -0
- data/lib/airbrake/sidekiq.rb +55 -0
- data/lib/airbrake/sidekiq/retryable_jobs_filter.rb +53 -0
- data/lib/airbrake/sneakers.rb +72 -0
- data/lib/airbrake/version.rb +5 -1
- data/lib/generators/airbrake_generator.rb +25 -0
- data/lib/generators/airbrake_initializer.rb.erb +80 -0
- metadata +206 -259
- data/CHANGELOG +0 -944
- data/Gemfile +0 -3
- data/Guardfile +0 -6
- data/INSTALL +0 -20
- data/MIT-LICENSE +0 -22
- data/README.md +0 -556
- data/README_FOR_HEROKU_ADDON.md +0 -94
- data/Rakefile +0 -223
- data/SUPPORTED_RAILS_VERSIONS +0 -38
- data/TESTING.md +0 -41
- data/airbrake.gemspec +0 -40
- data/bin/airbrake +0 -12
- data/features/metal.feature +0 -18
- data/features/rack.feature +0 -60
- data/features/rails.feature +0 -272
- data/features/rails_with_js_notifier.feature +0 -97
- data/features/rake.feature +0 -27
- data/features/sinatra.feature +0 -29
- data/features/step_definitions/file_steps.rb +0 -10
- data/features/step_definitions/metal_steps.rb +0 -23
- data/features/step_definitions/rack_steps.rb +0 -23
- data/features/step_definitions/rails_application_steps.rb +0 -478
- data/features/step_definitions/rake_steps.rb +0 -17
- data/features/support/airbrake_shim.rb.template +0 -16
- data/features/support/env.rb +0 -18
- data/features/support/matchers.rb +0 -35
- data/features/support/rails.rb +0 -201
- data/features/support/rake/Rakefile +0 -68
- data/features/support/terminal.rb +0 -107
- data/features/user_informer.feature +0 -63
- data/generators/airbrake/airbrake_generator.rb +0 -94
- data/generators/airbrake/lib/insert_commands.rb +0 -34
- data/generators/airbrake/lib/rake_commands.rb +0 -24
- data/generators/airbrake/templates/airbrake_tasks.rake +0 -25
- data/generators/airbrake/templates/capistrano_hook.rb +0 -6
- data/generators/airbrake/templates/initializer.rb +0 -6
- data/install.rb +0 -1
- data/lib/airbrake/backtrace.rb +0 -108
- data/lib/airbrake/cli/client.rb +0 -68
- data/lib/airbrake/cli/options.rb +0 -41
- data/lib/airbrake/cli/printer.rb +0 -30
- data/lib/airbrake/cli/project.rb +0 -17
- data/lib/airbrake/cli/project_factory.rb +0 -36
- data/lib/airbrake/cli/runner.rb +0 -48
- data/lib/airbrake/cli/validator.rb +0 -8
- data/lib/airbrake/configuration.rb +0 -311
- data/lib/airbrake/extensions/blank.rb +0 -73
- data/lib/airbrake/notice.rb +0 -390
- data/lib/airbrake/rails/action_controller_catcher.rb +0 -30
- data/lib/airbrake/rails/controller_methods.rb +0 -87
- data/lib/airbrake/rails/error_lookup.rb +0 -33
- data/lib/airbrake/rails/javascript_notifier.rb +0 -47
- data/lib/airbrake/rails/middleware/exceptions_catcher.rb +0 -33
- data/lib/airbrake/rails3_tasks.rb +0 -98
- data/lib/airbrake/railtie.rb +0 -48
- data/lib/airbrake/rake_handler.rb +0 -71
- data/lib/airbrake/sender.rb +0 -128
- data/lib/airbrake/shared_tasks.rb +0 -47
- data/lib/airbrake/tasks.rb +0 -83
- data/lib/airbrake/user_informer.rb +0 -27
- data/lib/airbrake_tasks.rb +0 -64
- data/lib/rails/generators/airbrake/airbrake_generator.rb +0 -100
- data/lib/templates/javascript_notifier.erb +0 -15
- data/lib/templates/rescue.erb +0 -91
- data/rails/init.rb +0 -1
- data/resources/README.md +0 -34
- data/resources/ca-bundle.crt +0 -3376
- data/script/integration_test.rb +0 -38
- data/test/airbrake_2_3.xsd +0 -88
- data/test/airbrake_tasks_test.rb +0 -170
- data/test/backtrace_test.rb +0 -162
- data/test/capistrano_test.rb +0 -34
- data/test/catcher_test.rb +0 -333
- data/test/configuration_test.rb +0 -233
- data/test/helper.rb +0 -263
- data/test/javascript_notifier_test.rb +0 -51
- data/test/logger_test.rb +0 -79
- data/test/notice_test.rb +0 -490
- data/test/notifier_test.rb +0 -276
- data/test/rack_test.rb +0 -58
- data/test/rails_initializer_test.rb +0 -36
- data/test/recursion_test.rb +0 -10
- data/test/sender_test.rb +0 -288
- data/test/user_informer_test.rb +0 -29
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTP
|
4
|
+
# Monkey-patch to measure request timing.
|
5
|
+
class Client
|
6
|
+
alias perform_without_airbrake perform
|
7
|
+
|
8
|
+
def perform(request, options)
|
9
|
+
Airbrake::Rack.capture_timing(:http) do
|
10
|
+
perform_without_airbrake(request, options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
module Rails
|
5
|
+
# Allows measuring request timing.
|
6
|
+
module HTTPClient
|
7
|
+
def do_get_block(request, proxy, connection, &block)
|
8
|
+
Airbrake::Rack.capture_timing(:http) do
|
9
|
+
super(request, proxy, connection, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
HTTPClient.prepend(Airbrake::Rails::HTTPClient)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
module Rails
|
5
|
+
# Monkey-patch Net::HTTP to benchmark it.
|
6
|
+
# @api private
|
7
|
+
# @since v10.0.2
|
8
|
+
module NetHttp
|
9
|
+
def request(request, *args, &block)
|
10
|
+
Airbrake::Rack.capture_timing(:http) do
|
11
|
+
super(request, *args, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Net::HTTP.prepend(Airbrake::Rails::NetHttp)
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
module Rails
|
5
|
+
# This railtie works for any Rails application that supports railties (Rails
|
6
|
+
# 3.2+ apps). It makes Airbrake Ruby work with Rails and report errors
|
7
|
+
# occurring in the application automatically.
|
8
|
+
#
|
9
|
+
# rubocop:disable Metrics/BlockLength
|
10
|
+
class Railtie < ::Rails::Railtie
|
11
|
+
initializer('airbrake.middleware') do |app|
|
12
|
+
# Since Rails 3.2 the ActionDispatch::DebugExceptions middleware is
|
13
|
+
# responsible for logging exceptions and showing a debugging page in
|
14
|
+
# case the request is local. We want to insert our middleware after
|
15
|
+
# DebugExceptions, so we don't notify Airbrake about local requests.
|
16
|
+
|
17
|
+
if ::Rails.version.to_i >= 5
|
18
|
+
# Avoid the warning about deprecated strings.
|
19
|
+
# Insert after DebugExceptions, since ConnectionManagement doesn't
|
20
|
+
# exist in Rails 5 anymore.
|
21
|
+
app.config.middleware.insert_after(
|
22
|
+
ActionDispatch::DebugExceptions,
|
23
|
+
Airbrake::Rack::Middleware,
|
24
|
+
)
|
25
|
+
elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement)
|
26
|
+
# Insert after ConnectionManagement to avoid DB connection leakage:
|
27
|
+
# https://github.com/airbrake/airbrake/pull/568
|
28
|
+
app.config.middleware.insert_after(
|
29
|
+
::ActiveRecord::ConnectionAdapters::ConnectionManagement,
|
30
|
+
'Airbrake::Rack::Middleware',
|
31
|
+
)
|
32
|
+
else
|
33
|
+
# Insert after DebugExceptions for apps without ActiveRecord.
|
34
|
+
app.config.middleware.insert_after(
|
35
|
+
ActionDispatch::DebugExceptions,
|
36
|
+
'Airbrake::Rack::Middleware',
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
rake_tasks do
|
42
|
+
# Report exceptions occurring in Rake tasks.
|
43
|
+
require 'airbrake/rake'
|
44
|
+
|
45
|
+
# Defines tasks such as `airbrake:test` & `airbrake:deploy`.
|
46
|
+
require 'airbrake/rake/tasks'
|
47
|
+
end
|
48
|
+
|
49
|
+
initializer('airbrake.action_controller') do
|
50
|
+
ActiveSupport.on_load(:action_controller, run_once: true) do
|
51
|
+
# Patches ActionController with methods that allow us to retrieve
|
52
|
+
# interesting request data. Appends that information to notices.
|
53
|
+
require 'airbrake/rails/action_controller'
|
54
|
+
include Airbrake::Rails::ActionController
|
55
|
+
|
56
|
+
# Cache route information for the duration of the request.
|
57
|
+
require 'airbrake/rails/action_controller_route_subscriber'
|
58
|
+
ActiveSupport::Notifications.subscribe(
|
59
|
+
'start_processing.action_controller',
|
60
|
+
Airbrake::Rails::ActionControllerRouteSubscriber.new,
|
61
|
+
)
|
62
|
+
|
63
|
+
# Send route stats.
|
64
|
+
require 'airbrake/rails/action_controller_notify_subscriber'
|
65
|
+
ActiveSupport::Notifications.subscribe(
|
66
|
+
'process_action.action_controller',
|
67
|
+
Airbrake::Rails::ActionControllerNotifySubscriber.new,
|
68
|
+
)
|
69
|
+
|
70
|
+
# Send performance breakdown: where a request spends its time.
|
71
|
+
require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
|
72
|
+
ActiveSupport::Notifications.subscribe(
|
73
|
+
'process_action.action_controller',
|
74
|
+
Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new,
|
75
|
+
)
|
76
|
+
|
77
|
+
require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP)
|
78
|
+
require 'airbrake/rails/curb' if defined?(Curl) && defined?(Curl::CURB_VERSION)
|
79
|
+
require 'airbrake/rails/http' if defined?(HTTP) && defined?(HTTP::Client)
|
80
|
+
require 'airbrake/rails/http_client' if defined?(HTTPClient)
|
81
|
+
require 'airbrake/rails/typhoeus' if defined?(Typhoeus)
|
82
|
+
|
83
|
+
if defined?(Excon)
|
84
|
+
require 'airbrake/rails/excon_subscriber'
|
85
|
+
ActiveSupport::Notifications.subscribe(/excon/, Airbrake::Rails::Excon.new)
|
86
|
+
::Excon.defaults[:instrumentor] = ActiveSupport::Notifications
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
initializer('airbrake.active_record') do
|
92
|
+
ActiveSupport.on_load(:active_record, run_once: true) do
|
93
|
+
# Reports exceptions occurring in some bugged ActiveRecord callbacks.
|
94
|
+
# Applicable only to the versions of Rails lower than 4.2.
|
95
|
+
if defined?(::Rails) &&
|
96
|
+
Gem::Version.new(::Rails.version) <= Gem::Version.new('4.2')
|
97
|
+
require 'airbrake/rails/active_record'
|
98
|
+
include Airbrake::Rails::ActiveRecord
|
99
|
+
end
|
100
|
+
|
101
|
+
if defined?(ActiveRecord)
|
102
|
+
# Send SQL queries.
|
103
|
+
require 'airbrake/rails/active_record_subscriber'
|
104
|
+
ActiveSupport::Notifications.subscribe(
|
105
|
+
'sql.active_record', Airbrake::Rails::ActiveRecordSubscriber.new
|
106
|
+
)
|
107
|
+
|
108
|
+
# Filter out parameters from SQL body.
|
109
|
+
if ::ActiveRecord::Base.respond_to?(:connection_db_config)
|
110
|
+
# Rails 6.1+ deprecates "connection_config" in favor of
|
111
|
+
# "connection_db_config", so we need an updated call.
|
112
|
+
Airbrake.add_performance_filter(
|
113
|
+
Airbrake::Filters::SqlFilter.new(
|
114
|
+
::ActiveRecord::Base.connection_db_config.configuration_hash[:adapter],
|
115
|
+
),
|
116
|
+
)
|
117
|
+
else
|
118
|
+
Airbrake.add_performance_filter(
|
119
|
+
Airbrake::Filters::SqlFilter.new(
|
120
|
+
::ActiveRecord::Base.connection_config[:adapter],
|
121
|
+
),
|
122
|
+
)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
initializer('airbrake.active_job') do
|
129
|
+
ActiveSupport.on_load(:active_job, run_once: true) do
|
130
|
+
# Reports exceptions occurring in ActiveJob jobs.
|
131
|
+
require 'airbrake/rails/active_job'
|
132
|
+
include Airbrake::Rails::ActiveJob
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
initializer('airbrake.action_cable') do
|
137
|
+
ActiveSupport.on_load(:action_cable, run_once: true) do
|
138
|
+
# Reports exceptions occurring in ActionCable connections.
|
139
|
+
require 'airbrake/rails/action_cable'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
runner do
|
144
|
+
at_exit do
|
145
|
+
Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
# rubocop:enable Metrics/BlockLength
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
module Rails
|
5
|
+
# Allow measuring request timing.
|
6
|
+
module TyphoeusRequest
|
7
|
+
def run
|
8
|
+
Airbrake::Rack.capture_timing(:http) do
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Typhoeus::Request.prepend(Airbrake::Rails::TyphoeusRequest)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This is not bulletproof, but if this file is executed before a task
|
4
|
+
# definition, we can grab tasks descriptions and locations.
|
5
|
+
# See: https://goo.gl/ksn6PE
|
6
|
+
Rake::TaskManager.record_task_metadata = true
|
7
|
+
|
8
|
+
module Rake
|
9
|
+
# Redefine +Rake::Task#execute+, so it can report errors to Airbrake.
|
10
|
+
class Task
|
11
|
+
# Store the original method to use it later.
|
12
|
+
alias execute_without_airbrake execute
|
13
|
+
|
14
|
+
# A wrapper around the original +#execute+, that catches all errors and
|
15
|
+
# notifies Airbrake.
|
16
|
+
#
|
17
|
+
# rubocop:disable Lint/RescueException
|
18
|
+
def execute(args = nil)
|
19
|
+
execute_without_airbrake(args)
|
20
|
+
rescue Exception => ex
|
21
|
+
notify_airbrake(ex, args)
|
22
|
+
raise ex
|
23
|
+
end
|
24
|
+
# rubocop:enable Lint/RescueException
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def notify_airbrake(exception, args)
|
29
|
+
notice = Airbrake.build_notice(exception)
|
30
|
+
notice[:context][:component] = 'rake'
|
31
|
+
notice[:context][:action] = name
|
32
|
+
notice[:params].merge!(
|
33
|
+
rake_task: task_info,
|
34
|
+
execute_args: args,
|
35
|
+
argv: ARGV.join(' '),
|
36
|
+
)
|
37
|
+
|
38
|
+
Airbrake.notify_sync(notice)
|
39
|
+
end
|
40
|
+
|
41
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
42
|
+
def task_info
|
43
|
+
info = {}
|
44
|
+
|
45
|
+
info[:name] = name
|
46
|
+
info[:timestamp] = timestamp.to_s
|
47
|
+
info[:investigation] = investigation
|
48
|
+
|
49
|
+
info[:full_comment] = full_comment if full_comment
|
50
|
+
info[:arg_names] = arg_names if arg_names.any?
|
51
|
+
info[:arg_description] = arg_description if arg_description
|
52
|
+
info[:locations] = locations if locations.any?
|
53
|
+
info[:sources] = sources if sources.any?
|
54
|
+
|
55
|
+
if prerequisite_tasks.any?
|
56
|
+
info[:prerequisite_tasks] = prerequisite_tasks.map do |p|
|
57
|
+
p.__send__(:task_info)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
info
|
62
|
+
end
|
63
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'airbrake-ruby'
|
4
|
+
|
5
|
+
namespace :airbrake do
|
6
|
+
desc 'Verify your gem installation by sending a test exception'
|
7
|
+
task test: (:environment if defined?(Rails)) do
|
8
|
+
raise Airbrake::Error, 'airbrake-ruby is not configured' unless Airbrake.configured?
|
9
|
+
|
10
|
+
require 'pp'
|
11
|
+
|
12
|
+
response = Airbrake.notify_sync('Exception from the test Rake task')
|
13
|
+
if response['error']
|
14
|
+
puts "Error: #{response['error']}"
|
15
|
+
elsif response.nil? || response['code']
|
16
|
+
puts <<-ERROR.gsub(/^\s+\|/, '')
|
17
|
+
|#{response['type']}: #{response['message']} (#{response['code']})
|
18
|
+
|
|
19
|
+
|Possible problems:
|
20
|
+
| 1. Project id/key is incorrect
|
21
|
+
| 2. Custom filters ignore the exception we try to send
|
22
|
+
| 3. Environment this task runs in is ignored (see `ignored_environments`)
|
23
|
+
|
|
24
|
+
|If nothing works, please file an issue at: https://github.com/airbrake/airbrake/issues
|
25
|
+
ERROR
|
26
|
+
elsif response['url']
|
27
|
+
puts <<-SUCCESS.gsub(/^\s+\|/, '')
|
28
|
+
|A test exception was sent to Airbrake.
|
29
|
+
|Find it here: #{response['url']}
|
30
|
+
SUCCESS
|
31
|
+
else
|
32
|
+
puts <<-ERROR.gsub(/^\s+\|/, '')
|
33
|
+
|Unexpected error occurred. Response from Airbrake:
|
34
|
+
|#{response}
|
35
|
+
ERROR
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Notify Airbrake of a new deploy'
|
40
|
+
task :deploy do
|
41
|
+
if defined?(Rails)
|
42
|
+
initializer = Rails.root.join('config', 'initializers', 'airbrake.rb')
|
43
|
+
|
44
|
+
# Avoid loading the environment to speed up the deploy task and try guess
|
45
|
+
# the initializer file location.
|
46
|
+
if initializer.exist? && !Airbrake.configured?
|
47
|
+
load(initializer)
|
48
|
+
else
|
49
|
+
Rake::Task[:environment].invoke
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
raise Airbrake::Error, 'airbrake-ruby is not configured' unless Airbrake.configured?
|
54
|
+
|
55
|
+
deploy_params = {
|
56
|
+
environment: ENV['ENVIRONMENT'],
|
57
|
+
username: ENV['USERNAME'],
|
58
|
+
revision: ENV['REVISION'],
|
59
|
+
repository: ENV['REPOSITORY'],
|
60
|
+
version: ENV['VERSION'],
|
61
|
+
}
|
62
|
+
promise = Airbrake.notify_deploy(deploy_params)
|
63
|
+
promise.then do
|
64
|
+
puts "The #{deploy_params[:environment]} environment was deployed."
|
65
|
+
end
|
66
|
+
promise.rescue { |error| abort(error) }
|
67
|
+
end
|
68
|
+
|
69
|
+
desc 'Install a Heroku deploy hook to notify Airbrake of deploys'
|
70
|
+
task :install_heroku_deploy_hook do
|
71
|
+
app = ENV['HEROKU_APP']
|
72
|
+
|
73
|
+
config = Bundler.with_clean_env do
|
74
|
+
`heroku config --shell#{" --app #{app}" if app}`
|
75
|
+
end
|
76
|
+
|
77
|
+
heroku_env = config.each_line.with_object({}) do |line, h|
|
78
|
+
h.merge!(Hash[*line.rstrip.split("\n").flat_map { |v| v.split('=', 2) }])
|
79
|
+
end
|
80
|
+
|
81
|
+
id = heroku_env['AIRBRAKE_PROJECT_ID']
|
82
|
+
key = heroku_env['AIRBRAKE_API_KEY']
|
83
|
+
|
84
|
+
exit!(1) if [id, key].any?(&:nil?)
|
85
|
+
|
86
|
+
unless (env = heroku_env['RAILS_ENV'])
|
87
|
+
env = 'production'
|
88
|
+
puts "Airbrake couldn't identify your app's environment, so the '#{env}'" \
|
89
|
+
" environment will be used."
|
90
|
+
end
|
91
|
+
|
92
|
+
unless (repo = ENV['REPOSITORY_URL'])
|
93
|
+
repo = `git remote get-url origin 2>/dev/null`.chomp
|
94
|
+
if repo.empty?
|
95
|
+
puts "Airbrake couldn't identify your app's repository."
|
96
|
+
else
|
97
|
+
puts "Airbrake couldn't identify your app's repository, so the " \
|
98
|
+
"'origin' remote url '#{repo}' will be used."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
url = ["https://airbrake.io/api/v3/projects/#{id}/heroku-deploys?key=#{key}"]
|
103
|
+
url << "&environment=#{env}"
|
104
|
+
url << "&repository=#{repo}" unless repo.empty?
|
105
|
+
|
106
|
+
command = [%(heroku addons:create deployhooks:http --url="#{url.join}")]
|
107
|
+
command << " --app #{app}" if app
|
108
|
+
|
109
|
+
puts "$ #{command.join}"
|
110
|
+
Bundler.with_clean_env { puts `#{command}` }
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Resque
|
4
|
+
module Failure
|
5
|
+
# Provides Resque integration with Airbrake.
|
6
|
+
#
|
7
|
+
# @since v5.0.0
|
8
|
+
# @see https://github.com/resque/resque/wiki/Failure-Backends
|
9
|
+
class Airbrake < Base
|
10
|
+
def save
|
11
|
+
::Airbrake.notify_sync(exception, payload) do |notice|
|
12
|
+
notice[:context][:component] = 'resque'
|
13
|
+
notice[:context][:action] = action(payload)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# @return [String] job's name. When ActiveJob is present, retrieve
|
20
|
+
# job_class. When used directly, use worker's name
|
21
|
+
def action(payload)
|
22
|
+
active_job_args = payload['args'].first if payload['args']
|
23
|
+
if active_job_args.is_a?(Hash) && active_job_args['job_class']
|
24
|
+
active_job_args['job_class']
|
25
|
+
else
|
26
|
+
payload['class'].to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module Resque
|
34
|
+
# Measures elapsed time of a job and notifies Airbrake of the execution
|
35
|
+
# status.
|
36
|
+
#
|
37
|
+
# @since v9.6.0
|
38
|
+
class Job
|
39
|
+
# Store the original method to use it later.
|
40
|
+
alias perform_without_airbrake perform
|
41
|
+
|
42
|
+
def perform
|
43
|
+
timing = Airbrake::Benchmark.measure do
|
44
|
+
perform_without_airbrake
|
45
|
+
end
|
46
|
+
rescue StandardError => exception
|
47
|
+
Airbrake.notify_queue_sync(
|
48
|
+
queue: payload['class'],
|
49
|
+
error_count: 1,
|
50
|
+
timing: 0.01,
|
51
|
+
)
|
52
|
+
raise exception
|
53
|
+
else
|
54
|
+
Airbrake.notify_queue_sync(
|
55
|
+
queue: payload['class'],
|
56
|
+
error_count: 0,
|
57
|
+
timing: timing,
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|