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,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
|