airbrake 10.0.2 → 13.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/airbrake/capistrano/capistrano2.rb +1 -1
- data/lib/airbrake/capistrano/capistrano3.rb +1 -1
- data/lib/airbrake/delayed_job.rb +28 -30
- data/lib/airbrake/logger.rb +3 -1
- data/lib/airbrake/rack/context_filter.rb +10 -6
- data/lib/airbrake/rack/http_headers_filter.rb +4 -4
- data/lib/airbrake/rack/instrumentable.rb +9 -5
- data/lib/airbrake/rack/route_filter.rb +3 -1
- data/lib/airbrake/rack/user.rb +2 -0
- data/lib/airbrake/rack.rb +2 -0
- data/lib/airbrake/rails/action_cable.rb +19 -17
- data/lib/airbrake/rails/action_controller.rb +3 -0
- data/lib/airbrake/rails/action_controller_notify_subscriber.rb +2 -0
- data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +2 -0
- data/lib/airbrake/rails/action_controller_route_subscriber.rb +2 -0
- data/lib/airbrake/rails/active_job.rb +2 -2
- data/lib/airbrake/rails/active_record_subscriber.rb +2 -0
- data/lib/airbrake/rails/app.rb +22 -0
- data/lib/airbrake/rails/backtrace_cleaner.rb +11 -0
- data/lib/airbrake/rails/curb.rb +18 -23
- data/lib/airbrake/rails/event.rb +14 -2
- data/lib/airbrake/rails/excon_subscriber.rb +2 -0
- data/lib/airbrake/rails/http.rb +12 -8
- data/lib/airbrake/rails/http_client.rb +11 -7
- data/lib/airbrake/rails/railtie.rb +7 -99
- data/lib/airbrake/rails/railties/action_controller_tie.rb +90 -0
- data/lib/airbrake/rails/railties/active_record_tie.rb +74 -0
- data/lib/airbrake/rails/railties/middleware_tie.rb +62 -0
- data/lib/airbrake/rails/typhoeus.rb +10 -8
- data/lib/airbrake/rails.rb +6 -8
- data/lib/airbrake/rake/tasks.rb +10 -10
- data/lib/airbrake/rake.rb +47 -46
- data/lib/airbrake/resque.rb +26 -25
- data/lib/airbrake/shoryuken.rb +2 -4
- data/lib/airbrake/sidekiq/retryable_jobs_filter.rb +14 -8
- data/lib/airbrake/sidekiq.rb +5 -6
- data/lib/airbrake/sneakers.rb +28 -27
- data/lib/airbrake/version.rb +1 -1
- data/lib/generators/airbrake_generator.rb +3 -6
- data/lib/generators/airbrake_initializer.rb.erb +65 -65
- metadata +52 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f91f4d04951002ed983c872b4d6042c1cc4c01ae609d3969b4b7e9b344bdf12
|
4
|
+
data.tar.gz: 58ee6fd62567a65f7df5178f6d0d9e6bd9cd58e9debbf62d9d75fa741b20b6d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b464a25e936fafa269f35bb5c19ed6134ba65f4184f9d76e5f5a349370e1277dc71418393c21a8427dcecc572aabaa941a5ae41dbbfa1547fa280d1416fc630
|
7
|
+
data.tar.gz: a78fdeaba2521c51e47b4f9bbee5674b1d3228e25345e7d20cac5c3186c856c6c860a5daee82adc32f8001bce3b6422be50c31dbba32912f43dd535ba1dc965b
|
@@ -21,7 +21,7 @@ module Airbrake
|
|
21
21
|
RAILS_ENV=#{fetch(:rails_env, nil)} \
|
22
22
|
|
23
23
|
bundle exec rake airbrake:deploy \
|
24
|
-
USERNAME=#{Shellwords.shellescape(ENV
|
24
|
+
USERNAME=#{Shellwords.shellescape(ENV.fetch('USER', nil) || ENV.fetch('USERNAME', nil))} \
|
25
25
|
ENVIRONMENT=#{fetch(:airbrake_env, fetch(:rails_env, 'production'))} \
|
26
26
|
REVISION=#{current_revision.strip} \
|
27
27
|
REPOSITORY=#{repository} \
|
data/lib/airbrake/delayed_job.rb
CHANGED
@@ -7,41 +7,39 @@ module Delayed
|
|
7
7
|
class Airbrake < ::Delayed::Plugin
|
8
8
|
callbacks do |lifecycle|
|
9
9
|
lifecycle.around(:invoke_job) do |job, *args, &block|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
params = job.as_json
|
10
|
+
timing = ::Airbrake::Benchmark.measure do
|
11
|
+
# Forward the call to the next callback in the callback chain
|
12
|
+
block.call(job, *args)
|
13
|
+
end
|
14
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
15
|
+
params = job.as_json
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
# If DelayedJob is used through ActiveJob, it contains extra info.
|
18
|
+
if job.payload_object.respond_to?(:job_data)
|
19
|
+
params[:active_job] = job.payload_object.job_data
|
20
|
+
job_class = job.payload_object.job_data['job_class']
|
21
|
+
end
|
23
22
|
|
24
|
-
|
23
|
+
action = job_class || job.payload_object.class.name
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
::Airbrake.notify(exception, params) do |notice|
|
26
|
+
notice[:context][:component] = 'delayed_job'
|
27
|
+
notice[:context][:action] = action
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
::Airbrake.notify_queue(
|
31
|
+
queue: action,
|
32
|
+
error_count: 1,
|
33
|
+
timing: 0.01,
|
34
|
+
)
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
36
|
+
raise exception
|
37
|
+
else
|
38
|
+
::Airbrake.notify_queue(
|
39
|
+
queue: job_class || job.payload_object.class.name,
|
40
|
+
error_count: 0,
|
41
|
+
timing: timing,
|
42
|
+
)
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
data/lib/airbrake/logger.rb
CHANGED
@@ -9,7 +9,7 @@ module Airbrake
|
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# # Create a logger like you normally do and decorate it.
|
12
|
-
# logger = Airbrake::AirbrakeLogger.new(Logger.new(
|
12
|
+
# logger = Airbrake::AirbrakeLogger.new(Logger.new($stdout))
|
13
13
|
#
|
14
14
|
# # Just use the logger like you normally do.
|
15
15
|
# logger.fatal('oops')
|
@@ -24,6 +24,8 @@ module Airbrake
|
|
24
24
|
attr_reader :airbrake_level
|
25
25
|
|
26
26
|
def initialize(logger)
|
27
|
+
super
|
28
|
+
|
27
29
|
__setobj__(logger)
|
28
30
|
@airbrake_notifier = Airbrake
|
29
31
|
self.level = logger.level
|
@@ -20,14 +20,9 @@ module Airbrake
|
|
20
20
|
context = notice[:context]
|
21
21
|
|
22
22
|
context[:url] = request.url
|
23
|
-
context[:userAddr] =
|
24
|
-
if request.respond_to?(:remote_ip)
|
25
|
-
request.remote_ip
|
26
|
-
else
|
27
|
-
request.ip
|
28
|
-
end
|
29
23
|
context[:userAgent] = request.user_agent
|
30
24
|
|
25
|
+
add_ip(context, request)
|
31
26
|
add_framework_version(context)
|
32
27
|
|
33
28
|
controller = request.env['action_controller.instance']
|
@@ -60,6 +55,15 @@ module Airbrake
|
|
60
55
|
}
|
61
56
|
end
|
62
57
|
end
|
58
|
+
|
59
|
+
def add_ip(context, request)
|
60
|
+
context[:userAddr] =
|
61
|
+
if request.respond_to?(:remote_ip)
|
62
|
+
request.remote_ip
|
63
|
+
else
|
64
|
+
request.ip
|
65
|
+
end
|
66
|
+
end
|
63
67
|
end
|
64
68
|
end
|
65
69
|
end
|
@@ -8,10 +8,10 @@ module Airbrake
|
|
8
8
|
class HttpHeadersFilter
|
9
9
|
# @return [Array<String>] the prefixes of the majority of HTTP headers in
|
10
10
|
# Rack (some prefixes match the header names for simplicity)
|
11
|
-
HTTP_HEADER_PREFIXES = [
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
HTTP_HEADER_PREFIXES = %w[
|
12
|
+
HTTP_
|
13
|
+
CONTENT_TYPE
|
14
|
+
CONTENT_LENGTH
|
15
15
|
].freeze
|
16
16
|
|
17
17
|
# @return [Integer]
|
@@ -57,6 +57,7 @@ module Airbrake
|
|
57
57
|
klass.module_exec do
|
58
58
|
mod = __airbrake_capture_timing_module__
|
59
59
|
mod.module_exec do
|
60
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition
|
60
61
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
61
62
|
def #{method_name}(#{args})
|
62
63
|
Airbrake::Rack.capture_timing(#{label.to_s.inspect}) do
|
@@ -65,6 +66,7 @@ module Airbrake
|
|
65
66
|
end
|
66
67
|
#{visibility} :#{method_name}
|
67
68
|
RUBY
|
69
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
68
70
|
end
|
69
71
|
prepend mod
|
70
72
|
end
|
@@ -83,6 +85,7 @@ module Airbrake
|
|
83
85
|
klass.module_exec do
|
84
86
|
alias_method wrapped_method_name, method_name
|
85
87
|
remove_method method_name if needs_removal
|
88
|
+
# rubocop:disable Style/DocumentDynamicEvalDefinition
|
86
89
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
87
90
|
def #{method_name}(#{args})
|
88
91
|
Airbrake::Rack.capture_timing(#{label.to_s.inspect}) do
|
@@ -91,6 +94,7 @@ module Airbrake
|
|
91
94
|
end
|
92
95
|
#{visibility} :#{method_name}
|
93
96
|
RUBY
|
97
|
+
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -98,11 +102,11 @@ module Airbrake
|
|
98
102
|
def self.method_visibility(klass, method_name)
|
99
103
|
klass.module_exec do
|
100
104
|
if protected_method_defined?(method_name)
|
101
|
-
"protected"
|
105
|
+
"protected"
|
102
106
|
elsif private_method_defined?(method_name)
|
103
|
-
"private"
|
107
|
+
"private"
|
104
108
|
else
|
105
|
-
"public"
|
109
|
+
"public"
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
@@ -111,11 +115,11 @@ module Airbrake
|
|
111
115
|
# A method instead of a constant so it isn't accessible in the target.
|
112
116
|
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7")
|
113
117
|
def self.method_signature
|
114
|
-
"*args, **kw_args, &block"
|
118
|
+
"*args, **kw_args, &block"
|
115
119
|
end
|
116
120
|
else
|
117
121
|
def self.method_signature
|
118
|
-
"*args, &block"
|
122
|
+
"*args, &block"
|
119
123
|
end
|
120
124
|
end
|
121
125
|
|
@@ -28,12 +28,14 @@ module Airbrake
|
|
28
28
|
|
29
29
|
def rails_route(request)
|
30
30
|
return unless (route = Airbrake::Rails::App.recognize_route(request))
|
31
|
+
|
31
32
|
route.path
|
32
33
|
end
|
33
34
|
|
34
35
|
def sinatra_route(request)
|
35
36
|
return unless (route = request.env['sinatra.route'])
|
36
|
-
|
37
|
+
|
38
|
+
route.split.drop(1).join(' ')
|
37
39
|
end
|
38
40
|
|
39
41
|
def action_dispatch_request?(request)
|
data/lib/airbrake/rack/user.rb
CHANGED
@@ -28,6 +28,7 @@ module Airbrake
|
|
28
28
|
controller = rack_env['action_controller.instance']
|
29
29
|
return unless controller.respond_to?(:current_user, true)
|
30
30
|
return unless [-1, 0].include?(controller.method(:current_user).arity)
|
31
|
+
|
31
32
|
begin
|
32
33
|
controller.__send__(:current_user)
|
33
34
|
rescue Exception => _e # rubocop:disable Lint/RescueException
|
@@ -59,6 +60,7 @@ module Airbrake
|
|
59
60
|
# try methods with no arguments or with variable number of arguments,
|
60
61
|
# where none of them are required
|
61
62
|
return unless @user.method(key).arity.between?(-1, 0)
|
63
|
+
|
62
64
|
String(@user.__send__(key))
|
63
65
|
end
|
64
66
|
|
data/lib/airbrake/rack.rb
CHANGED
@@ -10,26 +10,28 @@ require 'airbrake/rails/action_cable/notify_callback'
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
module
|
14
|
-
module
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
module Airbrake
|
14
|
+
module ActionCable
|
15
|
+
module Channel
|
16
|
+
# @since v8.3.0
|
17
|
+
# @api private
|
18
|
+
# @see https://github.com/rails/rails/blob/master/actioncable/lib/action_cable/channel/base.rb
|
19
|
+
module Base
|
20
|
+
def perform_action(*args, &block)
|
21
|
+
super(*args, &block)
|
22
|
+
rescue Exception => ex # rubocop:disable Lint/RescueException
|
23
|
+
Airbrake.notify(ex) do |notice|
|
24
|
+
notice.stash[:action_cable_connection] = connection
|
25
|
+
notice[:context][:component] = self.class
|
26
|
+
notice[:context][:action] = args.first['action']
|
27
|
+
notice[:params].merge!(args.first)
|
28
|
+
end
|
20
29
|
|
21
|
-
|
22
|
-
perform_action_without_airbrake(*args, &block)
|
23
|
-
rescue Exception => ex # rubocop:disable Lint/RescueException
|
24
|
-
Airbrake.notify(ex) do |notice|
|
25
|
-
notice.stash[:action_cable_connection] = connection
|
26
|
-
notice[:context][:component] = self.class
|
27
|
-
notice[:context][:action] = args.first['action']
|
28
|
-
notice[:params].merge!(args.first)
|
30
|
+
raise ex
|
29
31
|
end
|
30
|
-
|
31
|
-
raise ex
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
ActionCable::Channel::Base.prepend(Airbrake::ActionCable::Channel::Base)
|
@@ -14,6 +14,7 @@ module Airbrake
|
|
14
14
|
# @see Airbrake#notify, #notify_airbrake_sync
|
15
15
|
def notify_airbrake(exception, params = {}, &block)
|
16
16
|
return unless (notice = build_notice(exception, params))
|
17
|
+
|
17
18
|
Airbrake.notify(notice, params, &block)
|
18
19
|
end
|
19
20
|
|
@@ -22,6 +23,7 @@ module Airbrake
|
|
22
23
|
# @see Airbrake#notify_sync, #notify_airbrake
|
23
24
|
def notify_airbrake_sync(exception, params = {}, &block)
|
24
25
|
return unless (notice = build_notice(exception, params))
|
26
|
+
|
25
27
|
Airbrake.notify_sync(notice, params, &block)
|
26
28
|
end
|
27
29
|
|
@@ -29,6 +31,7 @@ module Airbrake
|
|
29
31
|
# @return [Airbrake::Notice] the notice with information from the Rack env
|
30
32
|
def build_notice(exception, params = {})
|
31
33
|
return unless (notice = Airbrake.build_notice(exception, params))
|
34
|
+
|
32
35
|
notice.stash[:rack_request] = request
|
33
36
|
notice
|
34
37
|
end
|
@@ -11,6 +11,8 @@ module Airbrake
|
|
11
11
|
# @since v8.0.0
|
12
12
|
class ActionControllerRouteSubscriber
|
13
13
|
def call(*args)
|
14
|
+
return unless Airbrake::Config.instance.performance_stats
|
15
|
+
|
14
16
|
# We don't track routeless events.
|
15
17
|
return unless (routes = Airbrake::Rack::RequestStore[:routes])
|
16
18
|
|
@@ -22,14 +22,14 @@ module Airbrake
|
|
22
22
|
block.call
|
23
23
|
end
|
24
24
|
rescue StandardError => exception
|
25
|
-
Airbrake.
|
25
|
+
Airbrake.notify_queue(
|
26
26
|
queue: job.class.name,
|
27
27
|
error_count: 1,
|
28
28
|
timing: 0.01,
|
29
29
|
)
|
30
30
|
raise exception
|
31
31
|
else
|
32
|
-
Airbrake.
|
32
|
+
Airbrake.notify_queue(
|
33
33
|
queue: job.class.name,
|
34
34
|
error_count: 0,
|
35
35
|
timing: timing,
|
data/lib/airbrake/rails/app.rb
CHANGED
@@ -11,12 +11,19 @@ module Airbrake
|
|
11
11
|
|
12
12
|
# @param [] request
|
13
13
|
# @return [Airbrake::Rails::App::Route, nil]
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
14
15
|
def self.recognize_route(request)
|
15
16
|
# Duplicate `request` because `recognize` *can* strip the request's
|
16
17
|
# `path_info`, which results in broken engine links (when the engine has
|
17
18
|
# an isolated namespace).
|
18
19
|
request_copy = request.dup
|
19
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
|
+
|
20
27
|
# We must search every engine individually to find a concrete route. If
|
21
28
|
# we rely only on the `Rails.application.routes.router`, then the
|
22
29
|
# recognize call would return the root route, neglecting PATH_INFO
|
@@ -26,6 +33,20 @@ module Airbrake
|
|
26
33
|
# * `Marketing::Engine` recognizes it as `marketing#/pricing` (correct)
|
27
34
|
engines.each do |engine|
|
28
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
|
+
# Ideally, we should be using `route.glob?` but in Rails 7+ this
|
44
|
+
# call would fail with a `NoMethodError`. This is because in
|
45
|
+
# Rails 7+ the AST for the route is not kept in memory anymore.
|
46
|
+
#
|
47
|
+
# See: https://github.com/rails/rails/pull/43006#discussion_r783895766
|
48
|
+
next if route.path.spec.any?(ActionDispatch::Journey::Nodes::Star)
|
49
|
+
|
29
50
|
path =
|
30
51
|
if engine == ::Rails.application
|
31
52
|
route.path.spec.to_s
|
@@ -46,6 +67,7 @@ module Airbrake
|
|
46
67
|
|
47
68
|
nil
|
48
69
|
end
|
70
|
+
# rubocop:enable Metrics/AbcSize
|
49
71
|
|
50
72
|
def self.engines
|
51
73
|
@engines ||= [*::Rails::Engine.subclasses, ::Rails.application]
|
@@ -4,9 +4,20 @@ module Airbrake
|
|
4
4
|
module Rails
|
5
5
|
# BacktraceCleaner is a wrapper around Rails.backtrace_cleaner.
|
6
6
|
class BacktraceCleaner
|
7
|
+
# @return [Regexp]
|
8
|
+
AIRBRAKE_FRAME_PATTERN = %r{/airbrake/lib/airbrake/}.freeze
|
9
|
+
|
7
10
|
def self.clean(backtrace)
|
8
11
|
::Rails.backtrace_cleaner.clean(backtrace).first(1)
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
12
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
|
data/lib/airbrake/rails/curb.rb
CHANGED
@@ -1,37 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
11
|
end
|
12
|
-
end
|
13
|
-
|
14
|
-
alias perform_without_airbrake perform
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
def perform(&block)
|
14
|
+
Airbrake::Rack.capture_timing(:http) do
|
15
|
+
super(&block)
|
16
|
+
end
|
19
17
|
end
|
20
18
|
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module Curl
|
25
|
-
# Monkey-patch to measure request timing.
|
26
|
-
class Multi
|
27
|
-
class << self
|
28
|
-
alias http_without_airbrake http
|
29
19
|
|
20
|
+
# Allows measuring request timing.
|
21
|
+
module CurlMulti
|
30
22
|
def http(urls_with_config, multi_options = {}, &block)
|
31
23
|
Airbrake::Rack.capture_timing(:http) do
|
32
|
-
|
24
|
+
super(urls_with_config, multi_options, &block)
|
33
25
|
end
|
34
26
|
end
|
35
27
|
end
|
36
28
|
end
|
37
29
|
end
|
30
|
+
|
31
|
+
Curl::Easy.prepend(Airbrake::Rails::CurlEasy)
|
32
|
+
Curl::Multi.singleton_class.prepend(Airbrake::Rails::CurlMulti)
|
data/lib/airbrake/rails/event.rb
CHANGED
@@ -8,12 +8,16 @@ module Airbrake
|
|
8
8
|
# @api private
|
9
9
|
class Event
|
10
10
|
# @see https://github.com/rails/rails/issues/8987
|
11
|
-
HTML_RESPONSE_WILDCARD = "*/*"
|
11
|
+
HTML_RESPONSE_WILDCARD = "*/*"
|
12
|
+
|
13
|
+
# @return [Integer]
|
14
|
+
MILLISECOND = 1000
|
12
15
|
|
13
16
|
include Airbrake::Loggable
|
14
17
|
|
15
18
|
def initialize(*args)
|
16
19
|
@event = ActiveSupport::Notifications::Event.new(*args)
|
20
|
+
@rails_7_or_greater = ::Rails::VERSION::MAJOR >= 7
|
17
21
|
end
|
18
22
|
|
19
23
|
def method
|
@@ -42,7 +46,15 @@ module Airbrake
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def time
|
45
|
-
|
49
|
+
# On Rails 7+ `ActiveSupport::Notifications::Event#time` returns an
|
50
|
+
# instance of Float. It represents monotonic time in milliseconds.
|
51
|
+
# Airbrake Ruby expects that the provided time is in seconds. Hence,
|
52
|
+
# we need to convert it from milliseconds to seconds. In the
|
53
|
+
# versions below Rails 7, time is an instance of Time.
|
54
|
+
#
|
55
|
+
# Relevant commit:
|
56
|
+
# https://github.com/rails/rails/commit/81d0dc90becfe0b8e7f7f26beb66c25d84b8ec7f
|
57
|
+
@rails_7_or_greater ? @event.time / MILLISECOND : @event.time
|
46
58
|
end
|
47
59
|
|
48
60
|
def groups
|
data/lib/airbrake/rails/http.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module Airbrake
|
4
|
+
module Rails
|
5
|
+
# Monkey-patch to measure request timing.
|
6
|
+
# @api private
|
7
|
+
# @since v11.0.2
|
8
|
+
module HTTP
|
9
|
+
def perform(request, options)
|
10
|
+
Airbrake::Rack.capture_timing(:http) do
|
11
|
+
super(request, options)
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
17
|
+
|
18
|
+
HTTP::Client.prepend(Airbrake::Rails::HTTP)
|
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
15
|
+
|
16
|
+
HTTPClient.prepend(Airbrake::Rails::HTTPClient)
|