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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 81da57e8a5a47cfafd0a69d4d4c89e100301ba4c5e48418866ce584a95fe3632
|
4
|
+
data.tar.gz: c24d6f44c8eae4ad946471098620b16c6973d9272b0363f2420305b35374b7a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95b80ba3b1bf3771695c22fc28511a44347a4c8b841fc51d80f5abe14eb204147502f22599c2663a69f8b95986e1dd0cc7c026983957ecedb1761df4ab4311f5
|
7
|
+
data.tar.gz: 0dc035ee0b9b791eb13b2b7be401e46b5ab4fb5b906f5b180123b4bd9d4e3fd3a83439ffafe29e0371e39e71697575b0790992e5f240349b5113ad26a47b1dbf
|
data/lib/airbrake.rb
CHANGED
@@ -1,159 +1,32 @@
|
|
1
|
-
|
2
|
-
require 'net/http'
|
3
|
-
require 'net/https'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'airbrake/extensions/blank'
|
6
|
-
require 'airbrake/version'
|
7
|
-
require 'airbrake/configuration'
|
8
|
-
require 'airbrake/notice'
|
9
|
-
require 'airbrake/sender'
|
10
|
-
require 'airbrake/backtrace'
|
11
|
-
require 'airbrake/rack'
|
12
|
-
require 'airbrake/user_informer'
|
13
|
-
|
14
|
-
require 'airbrake/railtie' if defined?(Rails::Railtie)
|
15
|
-
|
16
|
-
module Airbrake
|
17
|
-
API_VERSION = "2.3"
|
18
|
-
LOG_PREFIX = "** [Airbrake] "
|
19
|
-
|
20
|
-
HEADERS = {
|
21
|
-
'Content-type' => 'text/xml',
|
22
|
-
'Accept' => 'text/xml, application/xml'
|
23
|
-
}
|
24
|
-
|
25
|
-
class << self
|
26
|
-
# The sender object is responsible for delivering formatted data to the Airbrake server.
|
27
|
-
# Must respond to #send_to_airbrake. See Airbrake::Sender.
|
28
|
-
attr_accessor :sender
|
29
|
-
|
30
|
-
# A Airbrake configuration object. Must act like a hash and return sensible
|
31
|
-
# values for all Airbrake configuration options. See Airbrake::Configuration.
|
32
|
-
attr_writer :configuration
|
33
|
-
|
34
|
-
# Tell the log that the Notifier is good to go
|
35
|
-
def report_ready
|
36
|
-
write_verbose_log("Notifier #{VERSION} ready to catch errors")
|
37
|
-
end
|
38
|
-
|
39
|
-
# Prints out the environment info to the log for debugging help
|
40
|
-
def report_environment_info
|
41
|
-
write_verbose_log("Environment Info: #{environment_info}")
|
42
|
-
end
|
43
|
-
|
44
|
-
# Prints out the response body from Airbrake for debugging help
|
45
|
-
def report_response_body(response)
|
46
|
-
write_verbose_log("Response from Airbrake: \n#{response}")
|
47
|
-
end
|
48
|
-
|
49
|
-
# Prints out the details about the notice that wasn't sent to server
|
50
|
-
def report_notice(notice)
|
51
|
-
write_verbose_log("Notice details: \n#{notice}")
|
52
|
-
end
|
1
|
+
# frozen_string_literal: true
|
53
2
|
|
54
|
-
|
55
|
-
|
56
|
-
info = "[Ruby: #{RUBY_VERSION}]"
|
57
|
-
info << " [#{configuration.framework}]" if configuration.framework
|
58
|
-
info << " [Env: #{configuration.environment_name}]" if configuration.environment_name
|
59
|
-
end
|
3
|
+
require 'shellwords'
|
4
|
+
require 'English'
|
60
5
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
6
|
+
# Core library that sends notices.
|
7
|
+
# See: https://github.com/airbrake/airbrake-ruby
|
8
|
+
require 'airbrake-ruby'
|
65
9
|
|
66
|
-
|
67
|
-
def logger
|
68
|
-
self.configuration.logger
|
69
|
-
end
|
70
|
-
|
71
|
-
# Call this method to modify defaults in your initializers.
|
72
|
-
#
|
73
|
-
# @example
|
74
|
-
# Airbrake.configure do |config|
|
75
|
-
# config.api_key = '1234567890abcdef'
|
76
|
-
# config.secure = false
|
77
|
-
# end
|
78
|
-
def configure(silent = false)
|
79
|
-
yield(configuration)
|
80
|
-
self.sender = Sender.new(configuration)
|
81
|
-
report_ready unless silent
|
82
|
-
self.sender
|
83
|
-
end
|
84
|
-
|
85
|
-
# The configuration object.
|
86
|
-
# @see Airbrake.configure
|
87
|
-
def configuration
|
88
|
-
@configuration ||= Configuration.new
|
89
|
-
end
|
90
|
-
|
91
|
-
# Sends an exception manually using this method, even when you are not in a controller.
|
92
|
-
#
|
93
|
-
# @param [Exception] exception The exception you want to notify Airbrake about.
|
94
|
-
# @param [Hash] opts Data that will be sent to Airbrake.
|
95
|
-
#
|
96
|
-
# @option opts [String] :api_key The API key for this project. The API key is a unique identifier that Airbrake uses for identification.
|
97
|
-
# @option opts [String] :error_message The error returned by the exception (or the message you want to log).
|
98
|
-
# @option opts [String] :backtrace A backtrace, usually obtained with +caller+.
|
99
|
-
# @option opts [String] :rack_env The Rack environment.
|
100
|
-
# @option opts [String] :session The contents of the user's session.
|
101
|
-
# @option opts [String] :environment_name The application environment name.
|
102
|
-
def notify(exception, opts = {})
|
103
|
-
send_notice(build_notice_for(exception, opts))
|
104
|
-
end
|
105
|
-
|
106
|
-
# Sends the notice unless it is one of the default ignored exceptions
|
107
|
-
# @see Airbrake.notify
|
108
|
-
def notify_or_ignore(exception, opts = {})
|
109
|
-
notice = build_notice_for(exception, opts)
|
110
|
-
send_notice(notice) unless notice.ignore?
|
111
|
-
end
|
112
|
-
|
113
|
-
def build_lookup_hash_for(exception, options = {})
|
114
|
-
notice = build_notice_for(exception, options)
|
115
|
-
|
116
|
-
result = {}
|
117
|
-
result[:action] = notice.action rescue nil
|
118
|
-
result[:component] = notice.component rescue nil
|
119
|
-
result[:error_class] = notice.error_class if notice.error_class
|
120
|
-
result[:environment_name] = 'production'
|
121
|
-
|
122
|
-
unless notice.backtrace.lines.empty?
|
123
|
-
result[:file] = notice.backtrace.lines.first.file
|
124
|
-
result[:line_number] = notice.backtrace.lines.first.number
|
125
|
-
end
|
10
|
+
require 'airbrake/version'
|
126
11
|
|
127
|
-
|
128
|
-
|
12
|
+
# Automatically load needed files for the environment the library is running in.
|
13
|
+
if defined?(Rack)
|
14
|
+
require 'airbrake/rack'
|
129
15
|
|
130
|
-
|
16
|
+
require 'airbrake/rails' if defined?(Rails)
|
17
|
+
end
|
131
18
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
19
|
+
require 'airbrake/rake' if defined?(Rake::Task)
|
20
|
+
require 'airbrake/resque' if defined?(Resque)
|
21
|
+
require 'airbrake/sidekiq' if defined?(Sidekiq)
|
22
|
+
require 'airbrake/shoryuken' if defined?(Shoryuken)
|
23
|
+
require 'airbrake/delayed_job' if defined?(Delayed)
|
24
|
+
require 'airbrake/sneakers' if defined?(Sneakers)
|
141
25
|
|
142
|
-
|
143
|
-
exception = unwrap_exception(exception)
|
144
|
-
opts = opts.merge(:exception => exception) if exception.is_a?(Exception)
|
145
|
-
opts = opts.merge(exception.to_hash) if exception.respond_to?(:to_hash)
|
146
|
-
Notice.new(configuration.merge(opts))
|
147
|
-
end
|
26
|
+
require 'airbrake/logger'
|
148
27
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
exception.continued_exception
|
154
|
-
else
|
155
|
-
exception
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
28
|
+
# Notify of unhandled exceptions, if there were any, but ignore SystemExit.
|
29
|
+
at_exit do
|
30
|
+
Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
|
31
|
+
Airbrake.close
|
159
32
|
end
|
data/lib/airbrake/capistrano.rb
CHANGED
@@ -1,44 +1,8 @@
|
|
1
|
-
#
|
2
|
-
require 'capistrano'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
after "deploy:migrations", "airbrake:deploy"
|
10
|
-
after "deploy:cold", "airbrake:deploy"
|
11
|
-
|
12
|
-
namespace :airbrake do
|
13
|
-
desc <<-DESC
|
14
|
-
Notify Airbrake of the deployment by running the notification on the REMOTE machine.
|
15
|
-
- Run remotely so we use remote API keys, environment, etc.
|
16
|
-
DESC
|
17
|
-
task :deploy, :except => { :no_release => true } do
|
18
|
-
rails_env = fetch(:rails_env, "production")
|
19
|
-
airbrake_env = fetch(:airbrake_env, fetch(:rails_env, "production"))
|
20
|
-
local_user = ENV['USER'] || ENV['USERNAME']
|
21
|
-
executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'rake')
|
22
|
-
directory = configuration.current_release
|
23
|
-
notify_command = "cd #{directory}; #{executable} RAILS_ENV=#{rails_env} airbrake:deploy TO=#{airbrake_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
|
24
|
-
notify_command << " DRY_RUN=true" if dry_run
|
25
|
-
notify_command << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
|
26
|
-
logger.info "Notifying Airbrake of Deploy (#{notify_command})"
|
27
|
-
if configuration.dry_run
|
28
|
-
logger.info "DRY RUN: Notification not actually run."
|
29
|
-
else
|
30
|
-
result = ""
|
31
|
-
run(notify_command, :once => true) { |ch, stream, data| result << data }
|
32
|
-
# TODO: Check if SSL is active on account via result content.
|
33
|
-
end
|
34
|
-
logger.info "Airbrake Notification Complete."
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
if Capistrano::Configuration.instance
|
43
|
-
Airbrake::Capistrano.load_into(Capistrano::Configuration.instance)
|
3
|
+
if defined?(Capistrano::VERSION) &&
|
4
|
+
Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
|
5
|
+
require 'airbrake/capistrano/capistrano3'
|
6
|
+
else
|
7
|
+
require 'airbrake/capistrano/capistrano2'
|
44
8
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Airbrake
|
4
|
+
# The Capistrano v2 integration.
|
5
|
+
module Capistrano
|
6
|
+
# rubocop:disable Metrics/AbcSize
|
7
|
+
def self.load_into(config)
|
8
|
+
config.load do
|
9
|
+
after 'deploy', 'airbrake:deploy'
|
10
|
+
after 'deploy:migrations', 'airbrake:deploy'
|
11
|
+
after 'deploy:cold', 'airbrake:deploy'
|
12
|
+
|
13
|
+
namespace :airbrake do
|
14
|
+
desc "Notify Airbrake of the deploy"
|
15
|
+
task :deploy, except: { no_release: true }, on_error: :continue do
|
16
|
+
run(
|
17
|
+
<<-CMD, once: true
|
18
|
+
cd #{config.release_path} && \
|
19
|
+
|
20
|
+
RACK_ENV=#{fetch(:rack_env, nil)} \
|
21
|
+
RAILS_ENV=#{fetch(:rails_env, nil)} \
|
22
|
+
|
23
|
+
bundle exec rake airbrake:deploy \
|
24
|
+
USERNAME=#{Shellwords.shellescape(ENV['USER'] || ENV['USERNAME'])} \
|
25
|
+
ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, 'production'))} \
|
26
|
+
REVISION=#{current_revision.strip} \
|
27
|
+
REPOSITORY=#{repository} \
|
28
|
+
VERSION=#{fetch(:app_version, nil)}
|
29
|
+
CMD
|
30
|
+
)
|
31
|
+
logger.info 'Notified Airbrake of the deploy'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# rubocop:enable Metrics/AbcSize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Airbrake::Capistrano.load_into(Capistrano::Configuration.instance)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :airbrake do
|
4
|
+
desc "Notify Airbrake of the deploy"
|
5
|
+
task :deploy do
|
6
|
+
role = roles(:all, select: :primary).first || roles(:all).first
|
7
|
+
on role do
|
8
|
+
within release_path do
|
9
|
+
with rails_env: fetch(:rails_env, fetch(:stage)) do
|
10
|
+
execute :bundle, :exec, :rake, <<-CMD
|
11
|
+
airbrake:deploy USERNAME=#{Shellwords.shellescape(local_user)} \
|
12
|
+
ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, fetch(:stage)))} \
|
13
|
+
REVISION=#{fetch(:current_revision)} \
|
14
|
+
REPOSITORY=#{fetch(:repo_url)} \
|
15
|
+
VERSION=#{fetch(:app_version)}
|
16
|
+
CMD
|
17
|
+
|
18
|
+
info 'Notified Airbrake of the deploy'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module Plugins
|
5
|
+
# Provides integration with Delayed Job.
|
6
|
+
# rubocop:disable Metrics/BlockLength
|
7
|
+
class Airbrake < ::Delayed::Plugin
|
8
|
+
callbacks do |lifecycle|
|
9
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
10
|
+
begin
|
11
|
+
timing = ::Airbrake::Benchmark.measure do
|
12
|
+
# Forward the call to the next callback in the callback chain
|
13
|
+
block.call(job, *args)
|
14
|
+
end
|
15
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
16
|
+
params = job.as_json
|
17
|
+
|
18
|
+
# If DelayedJob is used through ActiveJob, it contains extra info.
|
19
|
+
if job.payload_object.respond_to?(:job_data)
|
20
|
+
params[:active_job] = job.payload_object.job_data
|
21
|
+
job_class = job.payload_object.job_data['job_class']
|
22
|
+
end
|
23
|
+
|
24
|
+
action = job_class || job.payload_object.class.name
|
25
|
+
|
26
|
+
::Airbrake.notify(exception, params) do |notice|
|
27
|
+
notice[:context][:component] = 'delayed_job'
|
28
|
+
notice[:context][:action] = action
|
29
|
+
end
|
30
|
+
|
31
|
+
::Airbrake.notify_queue(
|
32
|
+
queue: action,
|
33
|
+
error_count: 1,
|
34
|
+
timing: 0.01,
|
35
|
+
)
|
36
|
+
|
37
|
+
raise exception
|
38
|
+
else
|
39
|
+
::Airbrake.notify_queue(
|
40
|
+
queue: job_class || job.payload_object.class.name,
|
41
|
+
error_count: 0,
|
42
|
+
timing: timing,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
# rubocop:enable Metrics/BlockLength
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if RUBY_ENGINE == 'jruby' && defined?(Delayed::Backend::ActiveRecord::Job)
|
53
|
+
# Workaround against JRuby bug:
|
54
|
+
# https://github.com/jruby/jruby/issues/3338
|
55
|
+
# rubocop:disable Style/ClassAndModuleChildren
|
56
|
+
class Delayed::Backend::ActiveRecord::Job
|
57
|
+
alias old_to_ary to_ary
|
58
|
+
|
59
|
+
def to_ary
|
60
|
+
old_to_ary || [self]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
# rubocop:enable Style/ClassAndModuleChildren
|
64
|
+
end
|
65
|
+
|
66
|
+
Delayed::Worker.plugins << Delayed::Plugins::Airbrake
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'delegate'
|
5
|
+
|
6
|
+
module Airbrake
|
7
|
+
# Decorator for +Logger+ from stdlib. Endows loggers the ability to both log
|
8
|
+
# and report errors to Airbrake.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # Create a logger like you normally do and decorate it.
|
12
|
+
# logger = Airbrake::AirbrakeLogger.new(Logger.new(STDOUT))
|
13
|
+
#
|
14
|
+
# # Just use the logger like you normally do.
|
15
|
+
# logger.fatal('oops')
|
16
|
+
class AirbrakeLogger < SimpleDelegator
|
17
|
+
# @example
|
18
|
+
# # Assign a custom Airbrake notifier
|
19
|
+
# logger.airbrake_notifier = Airbrake::NoticeNotifier.new
|
20
|
+
# @return [Airbrake::Notifier] notifier to be used to send notices
|
21
|
+
attr_accessor :airbrake_notifier
|
22
|
+
|
23
|
+
# @return [Integer]
|
24
|
+
attr_reader :airbrake_level
|
25
|
+
|
26
|
+
def initialize(logger)
|
27
|
+
__setobj__(logger)
|
28
|
+
@airbrake_notifier = Airbrake
|
29
|
+
self.level = logger.level
|
30
|
+
end
|
31
|
+
|
32
|
+
# @see Logger#warn
|
33
|
+
def warn(progname = nil, &block)
|
34
|
+
notify_airbrake(Logger::WARN, progname)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
# @see Logger#error
|
39
|
+
def error(progname = nil, &block)
|
40
|
+
notify_airbrake(Logger::ERROR, progname)
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
# @see Logger#fatal
|
45
|
+
def fatal(progname = nil, &block)
|
46
|
+
notify_airbrake(Logger::FATAL, progname)
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
# @see Logger#unknown
|
51
|
+
def unknown(progname = nil, &block)
|
52
|
+
notify_airbrake(Logger::UNKNOWN, progname)
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
# @see Logger#level=
|
57
|
+
def level=(value)
|
58
|
+
self.airbrake_level = value < Logger::WARN ? Logger::WARN : value
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets airbrake severity level. Does not permit values below `Logger::WARN`.
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# logger.airbrake_level = Logger::FATAL
|
66
|
+
# @return [void]
|
67
|
+
def airbrake_level=(level)
|
68
|
+
if level < Logger::WARN
|
69
|
+
raise "Airbrake severity level #{level} is not allowed. " \
|
70
|
+
"Minimum allowed level is #{Logger::WARN}"
|
71
|
+
end
|
72
|
+
@airbrake_level = level
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def notify_airbrake(severity, progname)
|
78
|
+
return if severity < @airbrake_level || !@airbrake_notifier
|
79
|
+
|
80
|
+
@airbrake_notifier.notify(progname) do |notice|
|
81
|
+
# Get rid of unwanted internal Logger frames. Examples:
|
82
|
+
# * /ruby-2.4.0/lib/ruby/2.4.0/logger.rb
|
83
|
+
# * /gems/activesupport-4.2.7.1/lib/active_support/logger.rb
|
84
|
+
backtrace = notice[:errors].first[:backtrace]
|
85
|
+
notice[:errors].first[:backtrace] =
|
86
|
+
backtrace.drop_while { |frame| frame[:file] =~ %r{/logger.rb\z} }
|
87
|
+
|
88
|
+
notice[:context][:component] = 'log'
|
89
|
+
notice[:context][:severity] = normalize_severity(severity)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def normalize_severity(severity)
|
94
|
+
(case severity
|
95
|
+
when Logger::WARN then 'warning'
|
96
|
+
when Logger::ERROR, Logger::UNKNOWN then 'error'
|
97
|
+
when Logger::FATAL then 'critical'
|
98
|
+
else
|
99
|
+
raise "Unknown airbrake severity: #{severity}"
|
100
|
+
end).freeze
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|