airbrake 3.1.6 → 11.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/lib/airbrake.rb +23 -150
  3. data/lib/airbrake/capistrano.rb +6 -42
  4. data/lib/airbrake/capistrano/capistrano2.rb +40 -0
  5. data/lib/airbrake/capistrano/capistrano3.rb +23 -0
  6. data/lib/airbrake/delayed_job.rb +66 -0
  7. data/lib/airbrake/logger.rb +103 -0
  8. data/lib/airbrake/rack.rb +30 -45
  9. data/lib/airbrake/rack/context_filter.rb +65 -0
  10. data/lib/airbrake/rack/http_headers_filter.rb +44 -0
  11. data/lib/airbrake/rack/http_params_filter.rb +27 -0
  12. data/lib/airbrake/rack/instrumentable.rb +136 -0
  13. data/lib/airbrake/rack/middleware.rb +102 -0
  14. data/lib/airbrake/rack/request_body_filter.rb +33 -0
  15. data/lib/airbrake/rack/request_store.rb +34 -0
  16. data/lib/airbrake/rack/route_filter.rb +51 -0
  17. data/lib/airbrake/rack/session_filter.rb +25 -0
  18. data/lib/airbrake/rack/user.rb +74 -0
  19. data/lib/airbrake/rack/user_filter.rb +25 -0
  20. data/lib/airbrake/rails.rb +25 -31
  21. data/lib/airbrake/rails/action_cable.rb +35 -0
  22. data/lib/airbrake/rails/action_cable/notify_callback.rb +22 -0
  23. data/lib/airbrake/rails/action_controller.rb +40 -0
  24. data/lib/airbrake/rails/action_controller_notify_subscriber.rb +32 -0
  25. data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +51 -0
  26. data/lib/airbrake/rails/action_controller_route_subscriber.rb +33 -0
  27. data/lib/airbrake/rails/active_job.rb +50 -0
  28. data/lib/airbrake/rails/active_record.rb +36 -0
  29. data/lib/airbrake/rails/active_record_subscriber.rb +46 -0
  30. data/lib/airbrake/rails/app.rb +78 -0
  31. data/lib/airbrake/rails/backtrace_cleaner.rb +23 -0
  32. data/lib/airbrake/rails/curb.rb +32 -0
  33. data/lib/airbrake/rails/event.rb +81 -0
  34. data/lib/airbrake/rails/excon_subscriber.rb +25 -0
  35. data/lib/airbrake/rails/http.rb +14 -0
  36. data/lib/airbrake/rails/http_client.rb +16 -0
  37. data/lib/airbrake/rails/net_http.rb +18 -0
  38. data/lib/airbrake/rails/railtie.rb +151 -0
  39. data/lib/airbrake/rails/typhoeus.rb +16 -0
  40. data/lib/airbrake/rake.rb +65 -0
  41. data/lib/airbrake/rake/tasks.rb +112 -0
  42. data/lib/airbrake/resque.rb +61 -0
  43. data/lib/airbrake/shoryuken.rb +54 -0
  44. data/lib/airbrake/sidekiq.rb +55 -0
  45. data/lib/airbrake/sidekiq/retryable_jobs_filter.rb +53 -0
  46. data/lib/airbrake/sneakers.rb +72 -0
  47. data/lib/airbrake/version.rb +5 -1
  48. data/lib/generators/airbrake_generator.rb +25 -0
  49. data/lib/generators/airbrake_initializer.rb.erb +80 -0
  50. metadata +206 -259
  51. data/CHANGELOG +0 -944
  52. data/Gemfile +0 -3
  53. data/Guardfile +0 -6
  54. data/INSTALL +0 -20
  55. data/MIT-LICENSE +0 -22
  56. data/README.md +0 -556
  57. data/README_FOR_HEROKU_ADDON.md +0 -94
  58. data/Rakefile +0 -223
  59. data/SUPPORTED_RAILS_VERSIONS +0 -38
  60. data/TESTING.md +0 -41
  61. data/airbrake.gemspec +0 -40
  62. data/bin/airbrake +0 -12
  63. data/features/metal.feature +0 -18
  64. data/features/rack.feature +0 -60
  65. data/features/rails.feature +0 -272
  66. data/features/rails_with_js_notifier.feature +0 -97
  67. data/features/rake.feature +0 -27
  68. data/features/sinatra.feature +0 -29
  69. data/features/step_definitions/file_steps.rb +0 -10
  70. data/features/step_definitions/metal_steps.rb +0 -23
  71. data/features/step_definitions/rack_steps.rb +0 -23
  72. data/features/step_definitions/rails_application_steps.rb +0 -478
  73. data/features/step_definitions/rake_steps.rb +0 -17
  74. data/features/support/airbrake_shim.rb.template +0 -16
  75. data/features/support/env.rb +0 -18
  76. data/features/support/matchers.rb +0 -35
  77. data/features/support/rails.rb +0 -201
  78. data/features/support/rake/Rakefile +0 -68
  79. data/features/support/terminal.rb +0 -107
  80. data/features/user_informer.feature +0 -63
  81. data/generators/airbrake/airbrake_generator.rb +0 -94
  82. data/generators/airbrake/lib/insert_commands.rb +0 -34
  83. data/generators/airbrake/lib/rake_commands.rb +0 -24
  84. data/generators/airbrake/templates/airbrake_tasks.rake +0 -25
  85. data/generators/airbrake/templates/capistrano_hook.rb +0 -6
  86. data/generators/airbrake/templates/initializer.rb +0 -6
  87. data/install.rb +0 -1
  88. data/lib/airbrake/backtrace.rb +0 -108
  89. data/lib/airbrake/cli/client.rb +0 -68
  90. data/lib/airbrake/cli/options.rb +0 -41
  91. data/lib/airbrake/cli/printer.rb +0 -30
  92. data/lib/airbrake/cli/project.rb +0 -17
  93. data/lib/airbrake/cli/project_factory.rb +0 -36
  94. data/lib/airbrake/cli/runner.rb +0 -48
  95. data/lib/airbrake/cli/validator.rb +0 -8
  96. data/lib/airbrake/configuration.rb +0 -311
  97. data/lib/airbrake/extensions/blank.rb +0 -73
  98. data/lib/airbrake/notice.rb +0 -390
  99. data/lib/airbrake/rails/action_controller_catcher.rb +0 -30
  100. data/lib/airbrake/rails/controller_methods.rb +0 -87
  101. data/lib/airbrake/rails/error_lookup.rb +0 -33
  102. data/lib/airbrake/rails/javascript_notifier.rb +0 -47
  103. data/lib/airbrake/rails/middleware/exceptions_catcher.rb +0 -33
  104. data/lib/airbrake/rails3_tasks.rb +0 -98
  105. data/lib/airbrake/railtie.rb +0 -48
  106. data/lib/airbrake/rake_handler.rb +0 -71
  107. data/lib/airbrake/sender.rb +0 -128
  108. data/lib/airbrake/shared_tasks.rb +0 -47
  109. data/lib/airbrake/tasks.rb +0 -83
  110. data/lib/airbrake/user_informer.rb +0 -27
  111. data/lib/airbrake_tasks.rb +0 -64
  112. data/lib/rails/generators/airbrake/airbrake_generator.rb +0 -100
  113. data/lib/templates/javascript_notifier.erb +0 -15
  114. data/lib/templates/rescue.erb +0 -91
  115. data/rails/init.rb +0 -1
  116. data/resources/README.md +0 -34
  117. data/resources/ca-bundle.crt +0 -3376
  118. data/script/integration_test.rb +0 -38
  119. data/test/airbrake_2_3.xsd +0 -88
  120. data/test/airbrake_tasks_test.rb +0 -170
  121. data/test/backtrace_test.rb +0 -162
  122. data/test/capistrano_test.rb +0 -34
  123. data/test/catcher_test.rb +0 -333
  124. data/test/configuration_test.rb +0 -233
  125. data/test/helper.rb +0 -263
  126. data/test/javascript_notifier_test.rb +0 -51
  127. data/test/logger_test.rb +0 -79
  128. data/test/notice_test.rb +0 -490
  129. data/test/notifier_test.rb +0 -276
  130. data/test/rack_test.rb +0 -58
  131. data/test/rails_initializer_test.rb +0 -36
  132. data/test/recursion_test.rb +0 -10
  133. data/test/sender_test.rb +0 -288
  134. data/test/user_informer_test.rb +0 -29
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'airbrake/rails/event'
4
+
5
+ module Airbrake
6
+ module Rails
7
+ # @since v8.3.0
8
+ class ActionControllerPerformanceBreakdownSubscriber
9
+ def call(*args)
10
+ return unless Airbrake::Config.instance.performance_stats
11
+
12
+ routes = Airbrake::Rack::RequestStore[:routes]
13
+ return if !routes || routes.none?
14
+
15
+ event = Airbrake::Rails::Event.new(*args)
16
+ stash = build_stash
17
+
18
+ routes.each do |route, params|
19
+ groups = event.groups.merge(params[:groups])
20
+ next if groups.none?
21
+
22
+ breakdown_info = {
23
+ method: event.method,
24
+ route: route,
25
+ response_type: event.response_type,
26
+ groups: groups,
27
+ timing: event.duration,
28
+ time: event.time,
29
+ }
30
+
31
+ Airbrake.notify_performance_breakdown(breakdown_info, stash)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def build_stash
38
+ stash = {}
39
+ request = Airbrake::Rack::RequestStore[:request]
40
+ return stash unless request
41
+
42
+ stash[:request] = request
43
+ if (user = Airbrake::Rack::User.extract(request.env))
44
+ stash.merge!(user.as_json)
45
+ end
46
+
47
+ stash
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'airbrake/rails/event'
4
+ require 'airbrake/rails/app'
5
+
6
+ module Airbrake
7
+ module Rails
8
+ # ActionControllerRouteSubscriber sends route stat information, including
9
+ # performance data.
10
+ #
11
+ # @since v8.0.0
12
+ class ActionControllerRouteSubscriber
13
+ def call(*args)
14
+ return unless Airbrake::Config.instance.performance_stats
15
+
16
+ # We don't track routeless events.
17
+ return unless (routes = Airbrake::Rack::RequestStore[:routes])
18
+
19
+ event = Airbrake::Rails::Event.new(*args)
20
+ route = Airbrake::Rails::App.recognize_route(
21
+ Airbrake::Rack::RequestStore[:request],
22
+ )
23
+ return unless route
24
+
25
+ routes[route.path] = {
26
+ method: event.method,
27
+ response_type: event.response_type,
28
+ groups: {},
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # Enables support for exceptions occurring in ActiveJob jobs.
6
+ module ActiveJob
7
+ extend ActiveSupport::Concern
8
+
9
+ def self.notify_airbrake(exception, job)
10
+ notice = Airbrake.build_notice(exception)
11
+ notice[:context][:component] = 'active_job'
12
+ notice[:context][:action] = job.class.name
13
+ notice[:params].merge!(job.serialize)
14
+
15
+ Airbrake.notify(notice)
16
+
17
+ raise exception
18
+ end
19
+
20
+ def self.perform(job, block)
21
+ timing = Airbrake::Benchmark.measure do
22
+ block.call
23
+ end
24
+ rescue StandardError => exception
25
+ Airbrake.notify_queue(
26
+ queue: job.class.name,
27
+ error_count: 1,
28
+ timing: 0.01,
29
+ )
30
+ raise exception
31
+ else
32
+ Airbrake.notify_queue(
33
+ queue: job.class.name,
34
+ error_count: 0,
35
+ timing: timing,
36
+ )
37
+ end
38
+
39
+ included do
40
+ rescue_from(Exception) do |exception|
41
+ Airbrake::Rails::ActiveJob.notify_airbrake(exception, self)
42
+ end
43
+
44
+ around_perform do |job, block|
45
+ Airbrake::Rails::ActiveJob.perform(job, block)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # Rails <4.2 has a bug with regard to swallowing exceptions in the
6
+ # +after_commit+ and the +after_rollback+ hooks: it doesn't bubble up
7
+ # exceptions from there.
8
+ #
9
+ # This module makes it possible to report exceptions occurring there.
10
+ #
11
+ # @see https://github.com/rails/rails/pull/14488 Detailed description of the
12
+ # bug and the fix
13
+ # @see https://goo.gl/348lor Rails 4.2+ implementation (fixed)
14
+ # @see https://goo.gl/ddFNg7 Rails <4.2 implementation (bugged)
15
+ module ActiveRecord
16
+ # Patches default +run_callbacks+ with our version, which is capable of
17
+ # notifying about exceptions.
18
+ #
19
+ # rubocop:disable Lint/RescueException
20
+ def run_callbacks(kind, *args, &block)
21
+ # Let the post process handle the exception if it's not a bugged hook.
22
+ return super unless %i[commit rollback].include?(kind)
23
+
24
+ # Handle the exception ourselves. The 'ex' exception won't be
25
+ # propagated, therefore we must notify it here.
26
+ begin
27
+ super
28
+ rescue Exception => ex
29
+ Airbrake.notify(ex)
30
+ raise ex
31
+ end
32
+ end
33
+ # rubocop:enable Lint/RescueException
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'airbrake/rails/event'
4
+ require 'airbrake/rails/backtrace_cleaner'
5
+
6
+ module Airbrake
7
+ module Rails
8
+ # ActiveRecordSubscriber sends SQL information, including performance data.
9
+ #
10
+ # @since v8.1.0
11
+ class ActiveRecordSubscriber
12
+ def call(*args)
13
+ return unless Airbrake::Config.instance.query_stats
14
+
15
+ routes = Airbrake::Rack::RequestStore[:routes]
16
+ return if !routes || routes.none?
17
+
18
+ event = Airbrake::Rails::Event.new(*args)
19
+ frame = last_caller
20
+
21
+ routes.each do |route, params|
22
+ Airbrake.notify_query(
23
+ route: route,
24
+ method: params[:method],
25
+ query: event.sql,
26
+ func: frame[:function],
27
+ file: frame[:file],
28
+ line: frame[:line],
29
+ timing: event.duration,
30
+ time: event.time,
31
+ )
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def last_caller
38
+ exception = StandardError.new
39
+ exception.set_backtrace(
40
+ Airbrake::Rails::BacktraceCleaner.clean(Kernel.caller),
41
+ )
42
+ Airbrake::Backtrace.parse(exception).first || {}
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # App is a wrapper around Rails.application.
6
+ #
7
+ # @since v9.0.3
8
+ # @api private
9
+ class App
10
+ Route = Struct.new(:path)
11
+
12
+ # @param [] request
13
+ # @return [Airbrake::Rails::App::Route, nil]
14
+ # rubocop:disable Metrics/AbcSize
15
+ def self.recognize_route(request)
16
+ # Duplicate `request` because `recognize` *can* strip the request's
17
+ # `path_info`, which results in broken engine links (when the engine has
18
+ # an isolated namespace).
19
+ request_copy = request.dup
20
+
21
+ # Save original script name because `router.recognize(request)` mutates
22
+ # it. It's a Rails bug. More info in:
23
+ # * https://github.com/airbrake/airbrake/issues/1072
24
+ # * https://github.com/rails/rails/issues/31152
25
+ original_script_name = request.env['SCRIPT_NAME']
26
+
27
+ # We must search every engine individually to find a concrete route. If
28
+ # we rely only on the `Rails.application.routes.router`, then the
29
+ # recognize call would return the root route, neglecting PATH_INFO
30
+ # completely. For example:
31
+ # * a request is made to `marketing#pricing`
32
+ # * `Rails.application` recognizes it as `marketing#/` (incorrect)
33
+ # * `Marketing::Engine` recognizes it as `marketing#/pricing` (correct)
34
+ engines.each do |engine|
35
+ engine.routes.router.recognize(request_copy) do |route, _params|
36
+ # Restore original script name. Remove this code when/if the Rails
37
+ # bug is fixed: https://github.com/airbrake/airbrake/issues/1072
38
+ request.env['SCRIPT_NAME'] = original_script_name
39
+
40
+ # Skip "catch-all" routes such as:
41
+ # get '*path => 'pages#about'
42
+ #
43
+ # @todo The `glob?` method was added in Rails v4.2.0.beta1. We
44
+ # should remove the `respond_to?` check once we drop old Rails
45
+ # versions support.
46
+ #
47
+ # https://github.com/rails/rails/commit/5460591f0226a9d248b7b4f89186bd5553e7768f
48
+ next if route.respond_to?(:glob?) && route.glob?
49
+
50
+ path =
51
+ if engine == ::Rails.application
52
+ route.path.spec.to_s
53
+ else
54
+ "#{engine.engine_name}##{route.path.spec}"
55
+ end
56
+
57
+ # Rails can recognize multiple routes for the given request. For
58
+ # example, if we visit /users/2/edit, then Rails sees these routes:
59
+ # * "/users/:id/edit(.:format)"
60
+ # * "/"
61
+ #
62
+ # We return the first route as, what it seems, the most optimal
63
+ # approach.
64
+ return Route.new(path)
65
+ end
66
+ end
67
+
68
+ nil
69
+ end
70
+ # rubocop:enable Metrics/AbcSize
71
+
72
+ def self.engines
73
+ @engines ||= [*::Rails::Engine.subclasses, ::Rails.application]
74
+ end
75
+ private_class_method :engines
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # BacktraceCleaner is a wrapper around Rails.backtrace_cleaner.
6
+ class BacktraceCleaner
7
+ # @return [Regexp]
8
+ AIRBRAKE_FRAME_PATTERN = %r{/airbrake/lib/airbrake/}.freeze
9
+
10
+ def self.clean(backtrace)
11
+ ::Rails.backtrace_cleaner.clean(backtrace).first(1)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ if defined?(Rails)
18
+ # Silence own frames to let the cleaner proceed to the next line (and probably
19
+ # find the correct call-site coming from the app code rather this library).
20
+ Rails.backtrace_cleaner.add_silencer do |line|
21
+ line =~ Airbrake::Rails::BacktraceCleaner::AIRBRAKE_FRAME_PATTERN
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # Allows measuring request timing.
6
+ module CurlEasy
7
+ def http(verb)
8
+ Airbrake::Rack.capture_timing(:http) do
9
+ super(verb)
10
+ end
11
+ end
12
+
13
+ def perform(&block)
14
+ Airbrake::Rack.capture_timing(:http) do
15
+ super(&block)
16
+ end
17
+ end
18
+ end
19
+
20
+ # Allows measuring request timing.
21
+ module CurlMulti
22
+ def http(urls_with_config, multi_options = {}, &block)
23
+ Airbrake::Rack.capture_timing(:http) do
24
+ super(urls_with_config, multi_options, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Curl::Easy.prepend(Airbrake::Rails::CurlEasy)
32
+ Curl::Multi.singleton_class.prepend(Airbrake::Rails::CurlMulti)
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Airbrake
4
+ module Rails
5
+ # Event is a wrapper around ActiveSupport::Notifications::Event.
6
+ #
7
+ # @since v9.0.3
8
+ # @api private
9
+ class Event
10
+ # @see https://github.com/rails/rails/issues/8987
11
+ HTML_RESPONSE_WILDCARD = "*/*"
12
+
13
+ include Airbrake::Loggable
14
+
15
+ def initialize(*args)
16
+ @event = ActiveSupport::Notifications::Event.new(*args)
17
+ end
18
+
19
+ def method
20
+ @event.payload[:method]
21
+ end
22
+
23
+ def response_type
24
+ response_type = @event.payload[:format]
25
+ response_type == HTML_RESPONSE_WILDCARD ? :html : response_type
26
+ end
27
+
28
+ def params
29
+ @event.payload[:params]
30
+ end
31
+
32
+ def sql
33
+ @event.payload[:sql]
34
+ end
35
+
36
+ def db_runtime
37
+ @db_runtime ||= @event.payload[:db_runtime] || 0
38
+ end
39
+
40
+ def view_runtime
41
+ @view_runtime ||= @event.payload[:view_runtime] || 0
42
+ end
43
+
44
+ def time
45
+ @event.time
46
+ end
47
+
48
+ def groups
49
+ groups = {}
50
+ groups[:db] = db_runtime if db_runtime > 0
51
+ groups[:view] = view_runtime if view_runtime > 0
52
+ groups
53
+ end
54
+
55
+ def status_code
56
+ return @event.payload[:status] if @event.payload[:status]
57
+
58
+ if @event.payload[:exception]
59
+ status = ActionDispatch::ExceptionWrapper.status_code_for_exception(
60
+ @event.payload[:exception].first,
61
+ )
62
+ status = 500 if status == 0
63
+
64
+ return status
65
+ end
66
+
67
+ # The ActiveSupport event doesn't have status only in two cases:
68
+ # - an exception was thrown
69
+ # - unauthorized access
70
+ # We have already handled the exception so what's left is unauthorized
71
+ # access. There's no way to know for sure it's unauthorized access, so
72
+ # we are rather optimistic here.
73
+ 401
74
+ end
75
+
76
+ def duration
77
+ @event.duration
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'airbrake/rails/event'
4
+
5
+ module Airbrake
6
+ module Rails
7
+ # @api private
8
+ # @since v9.2.0
9
+ class Excon
10
+ def call(*args)
11
+ return unless Airbrake::Config.instance.performance_stats
12
+
13
+ routes = Airbrake::Rack::RequestStore[:routes]
14
+ return if !routes || routes.none?
15
+
16
+ event = Airbrake::Rails::Event.new(*args)
17
+
18
+ routes.each do |_route_path, params|
19
+ params[:groups][:http] ||= 0
20
+ params[:groups][:http] += event.duration
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end