airbrake 9.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/lib/airbrake.rb +30 -0
  3. data/lib/airbrake/capistrano.rb +6 -0
  4. data/lib/airbrake/capistrano/capistrano2.rb +38 -0
  5. data/lib/airbrake/capistrano/capistrano3.rb +21 -0
  6. data/lib/airbrake/delayed_job.rb +48 -0
  7. data/lib/airbrake/logger.rb +101 -0
  8. data/lib/airbrake/rack.rb +35 -0
  9. data/lib/airbrake/rack/context_filter.rb +58 -0
  10. data/lib/airbrake/rack/http_headers_filter.rb +42 -0
  11. data/lib/airbrake/rack/http_params_filter.rb +25 -0
  12. data/lib/airbrake/rack/instrumentable.rb +28 -0
  13. data/lib/airbrake/rack/middleware.rb +100 -0
  14. data/lib/airbrake/rack/request_body_filter.rb +31 -0
  15. data/lib/airbrake/rack/request_store.rb +32 -0
  16. data/lib/airbrake/rack/route_filter.rb +53 -0
  17. data/lib/airbrake/rack/session_filter.rb +23 -0
  18. data/lib/airbrake/rack/user.rb +70 -0
  19. data/lib/airbrake/rack/user_filter.rb +23 -0
  20. data/lib/airbrake/rails.rb +32 -0
  21. data/lib/airbrake/rails/action_cable.rb +33 -0
  22. data/lib/airbrake/rails/action_cable/notify_callback.rb +20 -0
  23. data/lib/airbrake/rails/action_controller.rb +35 -0
  24. data/lib/airbrake/rails/action_controller_notify_subscriber.rb +28 -0
  25. data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +46 -0
  26. data/lib/airbrake/rails/action_controller_route_subscriber.rb +46 -0
  27. data/lib/airbrake/rails/active_job.rb +33 -0
  28. data/lib/airbrake/rails/active_record.rb +34 -0
  29. data/lib/airbrake/rails/active_record_subscriber.rb +42 -0
  30. data/lib/airbrake/rails/app.rb +43 -0
  31. data/lib/airbrake/rails/backtrace_cleaner.rb +10 -0
  32. data/lib/airbrake/rails/curb.rb +35 -0
  33. data/lib/airbrake/rails/event.rb +83 -0
  34. data/lib/airbrake/rails/excon_subscriber.rb +21 -0
  35. data/lib/airbrake/rails/http.rb +12 -0
  36. data/lib/airbrake/rails/http_client.rb +10 -0
  37. data/lib/airbrake/rails/net_http.rb +10 -0
  38. data/lib/airbrake/rails/railtie.rb +141 -0
  39. data/lib/airbrake/rails/typhoeus.rb +12 -0
  40. data/lib/airbrake/rake.rb +63 -0
  41. data/lib/airbrake/rake/tasks.rb +110 -0
  42. data/lib/airbrake/resque.rb +29 -0
  43. data/lib/airbrake/shoryuken.rb +40 -0
  44. data/lib/airbrake/sidekiq.rb +47 -0
  45. data/lib/airbrake/sidekiq/retryable_jobs_filter.rb +51 -0
  46. data/lib/airbrake/sneakers.rb +34 -0
  47. data/lib/airbrake/version.rb +5 -0
  48. data/lib/generators/airbrake_generator.rb +23 -0
  49. data/lib/generators/airbrake_initializer.rb.erb +78 -0
  50. metadata +416 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e3451e5b75e5f477d87dc437e48bc95bee4783bd
4
+ data.tar.gz: c13ff23bd4a54accb6ba3b9eadd70fa283836f7e
5
+ SHA512:
6
+ metadata.gz: 92c00e765d4c72494d5c8c3046df7c6ba28a8a10168c1ca06131838c8ca6225ee461694d61c2cf8ef9a9189cf102eee31b2aec6ad5a8621223ebbf04011ef861
7
+ data.tar.gz: eefbe3fdb7e7a9157a5426114fdfe030a8f05cfa8602827bd7efe8d5279f9fc7ee4d8f900d6e94766d78ccdade11359a09edf196bf8ae439f595110ad00eed72
@@ -0,0 +1,30 @@
1
+ require 'shellwords'
2
+ require 'English'
3
+
4
+ # Core library that sends notices.
5
+ # See: https://github.com/airbrake/airbrake-ruby
6
+ require 'airbrake-ruby'
7
+
8
+ require 'airbrake/version'
9
+
10
+ # Automatically load needed files for the environment the library is running in.
11
+ if defined?(Rack)
12
+ require 'airbrake/rack'
13
+
14
+ require 'airbrake/rails' if defined?(Rails)
15
+ end
16
+
17
+ require 'airbrake/rake' if defined?(Rake::Task)
18
+ require 'airbrake/resque' if defined?(Resque)
19
+ require 'airbrake/sidekiq' if defined?(Sidekiq)
20
+ require 'airbrake/shoryuken' if defined?(Shoryuken)
21
+ require 'airbrake/delayed_job' if defined?(Delayed)
22
+ require 'airbrake/sneakers' if defined?(Sneakers)
23
+
24
+ require 'airbrake/logger'
25
+
26
+ # Notify of unhandled exceptions, if there were any, but ignore SystemExit.
27
+ at_exit do
28
+ Airbrake.notify_sync($ERROR_INFO) if $ERROR_INFO
29
+ Airbrake.close
30
+ end
@@ -0,0 +1,6 @@
1
+ if defined?(Capistrano::VERSION) &&
2
+ Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
3
+ require 'airbrake/capistrano/capistrano3'
4
+ else
5
+ require 'airbrake/capistrano/capistrano2'
6
+ end
@@ -0,0 +1,38 @@
1
+ module Airbrake
2
+ # The Capistrano v2 integration.
3
+ module Capistrano
4
+ # rubocop:disable Metrics/AbcSize
5
+ def self.load_into(config)
6
+ config.load do
7
+ after 'deploy', 'airbrake:deploy'
8
+ after 'deploy:migrations', 'airbrake:deploy'
9
+ after 'deploy:cold', 'airbrake:deploy'
10
+
11
+ namespace :airbrake do
12
+ desc "Notify Airbrake of the deploy"
13
+ task :deploy, except: { no_release: true }, on_error: :continue do
14
+ run(
15
+ <<-CMD, once: true
16
+ cd #{config.release_path} && \
17
+
18
+ RACK_ENV=#{fetch(:rack_env, nil)} \
19
+ RAILS_ENV=#{fetch(:rails_env, nil)} \
20
+
21
+ bundle exec rake airbrake:deploy \
22
+ USERNAME=#{Shellwords.shellescape(ENV['USER'] || ENV['USERNAME'])} \
23
+ ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, 'production'))} \
24
+ REVISION=#{current_revision.strip} \
25
+ REPOSITORY=#{repository} \
26
+ VERSION=#{fetch(:app_version, nil)}
27
+ CMD
28
+ )
29
+ logger.info 'Notified Airbrake of the deploy'
30
+ end
31
+ end
32
+ end
33
+ end
34
+ # rubocop:enable Metrics/AbcSize
35
+ end
36
+ end
37
+
38
+ Airbrake::Capistrano.load_into(Capistrano::Configuration.instance)
@@ -0,0 +1,21 @@
1
+ namespace :airbrake do
2
+ desc "Notify Airbrake of the deploy"
3
+ task :deploy do
4
+ role = roles(:all, select: :primary).first || roles(:all).first
5
+ on role do
6
+ within release_path do
7
+ with rails_env: fetch(:rails_env, fetch(:stage)) do
8
+ execute :bundle, :exec, :rake, <<-CMD
9
+ airbrake:deploy USERNAME=#{Shellwords.shellescape(local_user)} \
10
+ ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, fetch(:stage)))} \
11
+ REVISION=#{fetch(:current_revision)} \
12
+ REPOSITORY=#{fetch(:repo_url)} \
13
+ VERSION=#{fetch(:app_version)}
14
+ CMD
15
+
16
+ info 'Notified Airbrake of the deploy'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ module Delayed
2
+ module Plugins
3
+ # Provides integration with Delayed Job.
4
+ # rubocop:disable Lint/RescueException
5
+ class Airbrake < ::Delayed::Plugin
6
+ callbacks do |lifecycle|
7
+ lifecycle.around(:invoke_job) do |job, *args, &block|
8
+ begin
9
+ # Forward the call to the next callback in the callback chain
10
+ block.call(job, *args)
11
+ rescue Exception => exception
12
+ params = job.as_json
13
+
14
+ # If DelayedJob is used through ActiveJob, it contains extra info.
15
+ if job.payload_object.respond_to?(:job_data)
16
+ params[:active_job] = job.payload_object.job_data
17
+ job_class = job.payload_object.job_data['job_class']
18
+ end
19
+
20
+ ::Airbrake.notify(exception, params) do |notice|
21
+ notice[:context][:component] = 'delayed_job'
22
+ notice[:context][:action] = job_class || job.payload_object.class.name
23
+ end
24
+
25
+ raise exception
26
+ end
27
+ end
28
+ end
29
+ end
30
+ # rubocop:enable Lint/RescueException
31
+ end
32
+ end
33
+
34
+ if RUBY_ENGINE == 'jruby' && defined?(Delayed::Backend::ActiveRecord::Job)
35
+ # Workaround against JRuby bug:
36
+ # https://github.com/jruby/jruby/issues/3338
37
+ # rubocop:disable Style/ClassAndModuleChildren
38
+ class Delayed::Backend::ActiveRecord::Job
39
+ alias old_to_ary to_ary
40
+
41
+ def to_ary
42
+ old_to_ary || [self]
43
+ end
44
+ end
45
+ # rubocop:enable Style/ClassAndModuleChildren
46
+ end
47
+
48
+ Delayed::Worker.plugins << Delayed::Plugins::Airbrake
@@ -0,0 +1,101 @@
1
+ require 'logger'
2
+ require 'delegate'
3
+
4
+ module Airbrake
5
+ # Decorator for +Logger+ from stdlib. Endows loggers the ability to both log
6
+ # and report errors to Airbrake.
7
+ #
8
+ # @example
9
+ # # Create a logger like you normally do and decorate it.
10
+ # logger = Airbrake::AirbrakeLogger.new(Logger.new(STDOUT))
11
+ #
12
+ # # Just use the logger like you normally do.
13
+ # logger.fatal('oops')
14
+ class AirbrakeLogger < SimpleDelegator
15
+ # @example
16
+ # # Assign a custom Airbrake notifier
17
+ # logger.airbrake_notifier = Airbrake::NoticeNotifier.new
18
+ # @return [Airbrake::Notifier] notifier to be used to send notices
19
+ attr_accessor :airbrake_notifier
20
+
21
+ # @return [Integer]
22
+ attr_reader :airbrake_level
23
+
24
+ def initialize(logger)
25
+ __setobj__(logger)
26
+ @airbrake_notifier = Airbrake
27
+ self.level = logger.level
28
+ end
29
+
30
+ # @see Logger#warn
31
+ def warn(progname = nil, &block)
32
+ notify_airbrake(Logger::WARN, progname)
33
+ super
34
+ end
35
+
36
+ # @see Logger#error
37
+ def error(progname = nil, &block)
38
+ notify_airbrake(Logger::ERROR, progname)
39
+ super
40
+ end
41
+
42
+ # @see Logger#fatal
43
+ def fatal(progname = nil, &block)
44
+ notify_airbrake(Logger::FATAL, progname)
45
+ super
46
+ end
47
+
48
+ # @see Logger#unknown
49
+ def unknown(progname = nil, &block)
50
+ notify_airbrake(Logger::UNKNOWN, progname)
51
+ super
52
+ end
53
+
54
+ # @see Logger#level=
55
+ def level=(value)
56
+ self.airbrake_level = value < Logger::WARN ? Logger::WARN : value
57
+ super
58
+ end
59
+
60
+ # Sets airbrake severity level. Does not permit values below `Logger::WARN`.
61
+ #
62
+ # @example
63
+ # logger.airbrake_level = Logger::FATAL
64
+ # @return [void]
65
+ def airbrake_level=(level)
66
+ if level < Logger::WARN
67
+ raise "Airbrake severity level #{level} is not allowed. " \
68
+ "Minimum allowed level is #{Logger::WARN}"
69
+ end
70
+ @airbrake_level = level
71
+ end
72
+
73
+ private
74
+
75
+ def notify_airbrake(severity, progname)
76
+ return if severity < @airbrake_level || !@airbrake_notifier
77
+
78
+ @airbrake_notifier.notify(progname) do |notice|
79
+ # Get rid of unwanted internal Logger frames. Examples:
80
+ # * /ruby-2.4.0/lib/ruby/2.4.0/logger.rb
81
+ # * /gems/activesupport-4.2.7.1/lib/active_support/logger.rb
82
+ backtrace = notice[:errors].first[:backtrace]
83
+ notice[:errors].first[:backtrace] =
84
+ backtrace.drop_while { |frame| frame[:file] =~ %r{/logger.rb\z} }
85
+
86
+ notice[:context][:component] = 'log'
87
+ notice[:context][:severity] = normalize_severity(severity)
88
+ end
89
+ end
90
+
91
+ def normalize_severity(severity)
92
+ (case severity
93
+ when Logger::WARN then 'warning'
94
+ when Logger::ERROR, Logger::UNKNOWN then 'error'
95
+ when Logger::FATAL then 'critical'
96
+ else
97
+ raise "Unknown airbrake severity: #{severity}"
98
+ end).freeze
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,35 @@
1
+ require 'airbrake/rack/user'
2
+ require 'airbrake/rack/user_filter'
3
+ require 'airbrake/rack/context_filter'
4
+ require 'airbrake/rack/session_filter'
5
+ require 'airbrake/rack/http_params_filter'
6
+ require 'airbrake/rack/http_headers_filter'
7
+ require 'airbrake/rack/request_body_filter'
8
+ require 'airbrake/rack/route_filter'
9
+ require 'airbrake/rack/middleware'
10
+ require 'airbrake/rack/request_store'
11
+ require 'airbrake/rack/instrumentable'
12
+
13
+ module Airbrake
14
+ # Rack is a namespace for all Rack-related code.
15
+ module Rack
16
+ # @since v9.2.0
17
+ # @api public
18
+ def self.capture_timing(label)
19
+ routes = Airbrake::Rack::RequestStore[:routes]
20
+ if !routes || routes.none?
21
+ result = yield
22
+ else
23
+ timed_trace = Airbrake::TimedTrace.span(label) do
24
+ result = yield
25
+ end
26
+
27
+ routes.each do |_route_path, params|
28
+ params[:groups].merge!(timed_trace.spans)
29
+ end
30
+ end
31
+
32
+ result
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ module Airbrake
2
+ module Rack
3
+ # Adds context (URL, User-Agent, framework version, controller and more).
4
+ #
5
+ # @since v5.7.0
6
+ class ContextFilter
7
+ # @return [Integer]
8
+ attr_reader :weight
9
+
10
+ def initialize
11
+ @weight = 99
12
+ end
13
+
14
+ # @see Airbrake::FilterChain#refine
15
+ def call(notice)
16
+ return unless (request = notice.stash[:rack_request])
17
+
18
+ context = notice[:context]
19
+
20
+ context[:url] = request.url
21
+ context[:userAddr] = request.ip
22
+ context[:userAgent] = request.user_agent
23
+
24
+ add_framework_version(context)
25
+
26
+ controller = request.env['action_controller.instance']
27
+ return unless controller
28
+
29
+ context[:component] = controller.controller_name
30
+ context[:action] = controller.action_name
31
+ end
32
+
33
+ private
34
+
35
+ def add_framework_version(context)
36
+ if context.key?(:versions)
37
+ context[:versions].merge!(framework_version)
38
+ else
39
+ context[:versions] = framework_version
40
+ end
41
+ end
42
+
43
+ def framework_version
44
+ @framework_version ||=
45
+ if defined?(::Rails) && ::Rails.respond_to?(:version)
46
+ { 'rails' => ::Rails.version }
47
+ elsif defined?(::Sinatra)
48
+ { 'sinatra' => Sinatra::VERSION }
49
+ else
50
+ {
51
+ 'rack_version' => ::Rack.version,
52
+ 'rack_release' => ::Rack.release
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,42 @@
1
+ module Airbrake
2
+ module Rack
3
+ # Adds HTTP request parameters.
4
+ #
5
+ # @since v5.7.0
6
+ class HttpHeadersFilter
7
+ # @return [Array<String>] the prefixes of the majority of HTTP headers in
8
+ # Rack (some prefixes match the header names for simplicity)
9
+ HTTP_HEADER_PREFIXES = [
10
+ 'HTTP_'.freeze,
11
+ 'CONTENT_TYPE'.freeze,
12
+ 'CONTENT_LENGTH'.freeze
13
+ ].freeze
14
+
15
+ # @return [Integer]
16
+ attr_reader :weight
17
+
18
+ def initialize
19
+ @weight = 98
20
+ end
21
+
22
+ # @see Airbrake::FilterChain#refine
23
+ def call(notice)
24
+ return unless (request = notice.stash[:rack_request])
25
+
26
+ http_headers = request.env.map.with_object({}) do |(key, value), headers|
27
+ if HTTP_HEADER_PREFIXES.any? { |prefix| key.to_s.start_with?(prefix) }
28
+ headers[key] = value
29
+ end
30
+
31
+ headers
32
+ end
33
+
34
+ notice[:context].merge!(
35
+ httpMethod: request.request_method,
36
+ referer: request.referer,
37
+ headers: http_headers
38
+ )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ module Airbrake
2
+ module Rack
3
+ # Adds HTTP request parameters.
4
+ #
5
+ # @since v5.7.0
6
+ class HttpParamsFilter
7
+ # @return [Integer]
8
+ attr_reader :weight
9
+
10
+ def initialize
11
+ @weight = 97
12
+ end
13
+
14
+ # @see Airbrake::FilterChain#refine
15
+ def call(notice)
16
+ return unless (request = notice.stash[:rack_request])
17
+
18
+ notice[:params].merge!(request.params)
19
+
20
+ rails_params = request.env['action_dispatch.request.parameters']
21
+ notice[:params].merge!(rails_params) if rails_params
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module Airbrake
2
+ module Rack
3
+ # Instrumentable holds methods that simplify instrumenting Rack apps.
4
+ # @example
5
+ # class UsersController
6
+ # extend Airbrake::Rack::Instrumentable
7
+ #
8
+ # def index
9
+ # # ...
10
+ # end
11
+ # airbrake_capture_timing :index
12
+ # end
13
+ #
14
+ # @api public
15
+ # @since v9.2.0
16
+ module Instrumentable
17
+ def airbrake_capture_timing(method_name, label: method_name.to_s)
18
+ alias_method "#{method_name}_without_airbrake", method_name
19
+
20
+ define_method(method_name) do |*args|
21
+ Airbrake::Rack.capture_timing(label) do
22
+ __send__("#{method_name}_without_airbrake", *args)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end