airbrake 9.5.5 → 10.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90f7f39f6012a7e8383f50d1d99c8631582032feddaaa5a452bb7ba9afc40fc6
4
- data.tar.gz: 728831ea6a9a57815fec54ac507f4712923bcfe5b012b31658ddd0c1b4d576ba
3
+ metadata.gz: 83054730bd07260d0293206623452abacfc4b0006f65900811bac214a026c8a0
4
+ data.tar.gz: dee0bf02404e401d98b065e0550cffb4fb8bdec9e208cb31d4e37155a4b9e29c
5
5
  SHA512:
6
- metadata.gz: d899543189d807cbc393fba4643274eea3b02134fa09aec828926dc2dced70adef3071b36092fa0f3ba9809217b3c74aa8e6d25849c22cfcc88640a6d257c85b
7
- data.tar.gz: ca0c24bbd41fdd983a128763c99a3ce43aef445266d71606d54263782894e9a4987dde638c08083eb037ae6cae322d51ba1f42e4b690422478f4c3550cec817b
6
+ metadata.gz: b62c7face7778e77164b5f5222c64b6623984e2925a5b1928de2eb9a5b15a224111aa87b427cdb79b6626e0ae0bee0fc2d59b0780bfc6e5d852f227d4ed4679b
7
+ data.tar.gz: 41407ade81d73fb1594c67ebd26311f69d3888445fa8b28ae23a0a48031a323dc9ac4a68dc6a9906b532e0855b2878edf9712565b5ef458ec2e9250d59864c2f
@@ -1,14 +1,16 @@
1
1
  module Delayed
2
2
  module Plugins
3
3
  # Provides integration with Delayed Job.
4
- # rubocop:disable Lint/RescueException
4
+ # rubocop:disable Metrics/BlockLength
5
5
  class Airbrake < ::Delayed::Plugin
6
6
  callbacks do |lifecycle|
7
7
  lifecycle.around(:invoke_job) do |job, *args, &block|
8
8
  begin
9
- # Forward the call to the next callback in the callback chain
10
- block.call(job, *args)
11
- rescue Exception => exception
9
+ timing = ::Airbrake::Benchmark.measure do
10
+ # Forward the call to the next callback in the callback chain
11
+ block.call(job, *args)
12
+ end
13
+ rescue Exception => exception # rubocop:disable Lint/RescueException
12
14
  params = job.as_json
13
15
 
14
16
  # If DelayedJob is used through ActiveJob, it contains extra info.
@@ -17,17 +19,31 @@ module Delayed
17
19
  job_class = job.payload_object.job_data['job_class']
18
20
  end
19
21
 
22
+ action = job_class || job.payload_object.class.name
23
+
20
24
  ::Airbrake.notify(exception, params) do |notice|
21
25
  notice[:context][:component] = 'delayed_job'
22
- notice[:context][:action] = job_class || job.payload_object.class.name
26
+ notice[:context][:action] = action
23
27
  end
24
28
 
29
+ ::Airbrake.notify_queue_sync(
30
+ queue: action,
31
+ error_count: 1,
32
+ timing: 0.01,
33
+ )
34
+
25
35
  raise exception
36
+ else
37
+ ::Airbrake.notify_queue_sync(
38
+ queue: job_class || job.payload_object.class.name,
39
+ error_count: 0,
40
+ timing: timing,
41
+ )
26
42
  end
27
43
  end
28
44
  end
29
45
  end
30
- # rubocop:enable Lint/RescueException
46
+ # rubocop:enable Metrics/BlockLength
31
47
  end
32
48
  end
33
49
 
@@ -18,7 +18,12 @@ module Airbrake
18
18
  context = notice[:context]
19
19
 
20
20
  context[:url] = request.url
21
- context[:userAddr] = request.ip
21
+ context[:userAddr] =
22
+ if request.respond_to?(:remote_ip)
23
+ request.remote_ip
24
+ else
25
+ request.ip
26
+ end
22
27
  context[:userAgent] = request.user_agent
23
28
 
24
29
  add_framework_version(context)
@@ -49,7 +54,7 @@ module Airbrake
49
54
  else
50
55
  {
51
56
  'rack_version' => ::Rack.version,
52
- 'rack_release' => ::Rack.release
57
+ 'rack_release' => ::Rack.release,
53
58
  }
54
59
  end
55
60
  end
@@ -9,7 +9,7 @@ module Airbrake
9
9
  HTTP_HEADER_PREFIXES = [
10
10
  'HTTP_'.freeze,
11
11
  'CONTENT_TYPE'.freeze,
12
- 'CONTENT_LENGTH'.freeze
12
+ 'CONTENT_LENGTH'.freeze,
13
13
  ].freeze
14
14
 
15
15
  # @return [Integer]
@@ -34,7 +34,7 @@ module Airbrake
34
34
  notice[:context].merge!(
35
35
  httpMethod: request.request_method,
36
36
  referer: request.referer,
37
- headers: http_headers
37
+ headers: http_headers,
38
38
  )
39
39
  end
40
40
  end
@@ -94,7 +94,7 @@ end
94
94
  Airbrake::Rack::SessionFilter,
95
95
  Airbrake::Rack::HttpParamsFilter,
96
96
  Airbrake::Rack::HttpHeadersFilter,
97
- Airbrake::Rack::RouteFilter
97
+ Airbrake::Rack::RouteFilter,
98
98
  ].each do |filter|
99
99
  Airbrake.add_filter(filter.new)
100
100
  end
@@ -12,7 +12,7 @@ module Airbrake
12
12
 
13
13
  # Rails.logger is not set in some Rake tasks such as
14
14
  # 'airbrake:deploy'. In this case we use a sensible fallback.
15
- level: (::Rails.logger ? ::Rails.logger.level : Logger::ERROR)
15
+ level: (::Rails.logger ? ::Rails.logger.level : Logger::ERROR),
16
16
  )
17
17
  end
18
18
  end
@@ -18,8 +18,8 @@ module Airbrake
18
18
  method: event.method,
19
19
  route: route,
20
20
  status_code: event.status_code,
21
- start_time: event.time,
22
- end_time: Time.new
21
+ timing: event.duration,
22
+ time: event.time,
23
23
  )
24
24
  end
25
25
  end
@@ -20,7 +20,8 @@ module Airbrake
20
20
  route: route,
21
21
  response_type: event.response_type,
22
22
  groups: groups,
23
- start_time: event.time
23
+ timing: event.duration,
24
+ time: event.time,
24
25
  }
25
26
 
26
27
  Airbrake.notify_performance_breakdown(breakdown_info, stash)
@@ -14,14 +14,14 @@ module Airbrake
14
14
 
15
15
  event = Airbrake::Rails::Event.new(*args)
16
16
  route = Airbrake::Rails::App.recognize_route(
17
- Airbrake::Rack::RequestStore[:request]
17
+ Airbrake::Rack::RequestStore[:request],
18
18
  )
19
19
  return unless route
20
20
 
21
21
  routes[route.path] = {
22
22
  method: event.method,
23
23
  response_type: event.response_type,
24
- groups: {}
24
+ groups: {},
25
25
  }
26
26
  end
27
27
  end
@@ -23,10 +23,33 @@ module Airbrake
23
23
  raise exception
24
24
  end
25
25
 
26
+ def self.perform(job, block)
27
+ timing = Airbrake::Benchmark.measure do
28
+ block.call
29
+ end
30
+ rescue StandardError => exception
31
+ Airbrake.notify_queue_sync(
32
+ queue: job.class.name,
33
+ error_count: 1,
34
+ timing: 0.01,
35
+ )
36
+ raise exception
37
+ else
38
+ Airbrake.notify_queue_sync(
39
+ queue: job.class.name,
40
+ error_count: 0,
41
+ timing: timing,
42
+ )
43
+ end
44
+
26
45
  included do
27
46
  rescue_from(Exception) do |exception|
28
47
  Airbrake::Rails::ActiveJob.notify_airbrake(exception, self)
29
48
  end
49
+
50
+ around_perform do |job, block|
51
+ Airbrake::Rails::ActiveJob.perform(job, block)
52
+ end
30
53
  end
31
54
  end
32
55
  end
@@ -22,8 +22,8 @@ module Airbrake
22
22
  func: frame[:function],
23
23
  file: frame[:file],
24
24
  line: frame[:line],
25
- start_time: event.time,
26
- end_time: event.end
25
+ timing: event.duration,
26
+ time: event.time,
27
27
  )
28
28
  end
29
29
  end
@@ -33,7 +33,7 @@ module Airbrake
33
33
  def last_caller
34
34
  exception = StandardError.new
35
35
  exception.set_backtrace(
36
- Airbrake::Rails::BacktraceCleaner.clean(Kernel.caller)
36
+ Airbrake::Rails::BacktraceCleaner.clean(Kernel.caller),
37
37
  )
38
38
  Airbrake::Backtrace.parse(exception).first || {}
39
39
  end
@@ -13,26 +13,42 @@ module Airbrake
13
13
  # Duplicate `request` because `recognize` *can* strip the request's
14
14
  # `path_info`, which results in broken engine links (when the engine has
15
15
  # an isolated namespace).
16
- ::Rails.application.routes.router.recognize(request.dup) do |route, _params|
17
- path =
18
- if route.app.respond_to?(:app) && route.app.app.respond_to?(:engine_name)
19
- "#{route.app.app.engine_name}##{route.path.spec}"
20
- else
21
- route.path.spec.to_s
22
- end
16
+ request_copy = request.dup
23
17
 
24
- # Rails can recognize multiple routes for the given request. For
25
- # example, if we visit /users/2/edit, then Rails sees these routes:
26
- # * "/users/:id/edit(.:format)"
27
- # * "/"
28
- #
29
- # We return the first route as, what it seems, the most optimal
30
- # approach.
31
- return Route.new(path)
18
+ # We must search every engine individually to find a concrete route. If
19
+ # we rely only on the `Rails.application.routes.router`, then the
20
+ # recognize call would return the root route, neglecting PATH_INFO
21
+ # completely. For example:
22
+ # * a request is made to `marketing#pricing`
23
+ # * `Rails.application` recognizes it as `marketing#/` (incorrect)
24
+ # * `Marketing::Engine` recognizes it as `marketing#/pricing` (correct)
25
+ engines.each do |engine|
26
+ engine.routes.router.recognize(request_copy) do |route, _params|
27
+ path =
28
+ if engine == ::Rails.application
29
+ route.path.spec.to_s
30
+ else
31
+ "#{engine.engine_name}##{route.path.spec}"
32
+ end
33
+
34
+ # Rails can recognize multiple routes for the given request. For
35
+ # example, if we visit /users/2/edit, then Rails sees these routes:
36
+ # * "/users/:id/edit(.:format)"
37
+ # * "/"
38
+ #
39
+ # We return the first route as, what it seems, the most optimal
40
+ # approach.
41
+ return Route.new(path)
42
+ end
32
43
  end
33
44
 
34
45
  nil
35
46
  end
47
+
48
+ def self.engines
49
+ @engines ||= [*::Rails::Engine.subclasses, ::Rails.application]
50
+ end
51
+ private_class_method :engines
36
52
  end
37
53
  end
38
54
  end
@@ -43,10 +43,6 @@ module Airbrake
43
43
  @event.time
44
44
  end
45
45
 
46
- def end
47
- @event.end
48
- end
49
-
50
46
  def groups
51
47
  groups = {}
52
48
  groups[:db] = db_runtime if db_runtime > 0
@@ -59,7 +55,7 @@ module Airbrake
59
55
 
60
56
  if @event.payload[:exception]
61
57
  status = ActionDispatch::ExceptionWrapper.status_code_for_exception(
62
- @event.payload[:exception].first
58
+ @event.payload[:exception].first,
63
59
  )
64
60
  status = 500 if status == 0
65
61
 
@@ -16,20 +16,20 @@ module Airbrake
16
16
  # exist in Rails 5 anymore.
17
17
  app.config.middleware.insert_after(
18
18
  ActionDispatch::DebugExceptions,
19
- Airbrake::Rack::Middleware
19
+ Airbrake::Rack::Middleware,
20
20
  )
21
21
  elsif defined?(::ActiveRecord::ConnectionAdapters::ConnectionManagement)
22
22
  # Insert after ConnectionManagement to avoid DB connection leakage:
23
23
  # https://github.com/airbrake/airbrake/pull/568
24
24
  app.config.middleware.insert_after(
25
25
  ::ActiveRecord::ConnectionAdapters::ConnectionManagement,
26
- 'Airbrake::Rack::Middleware'
26
+ 'Airbrake::Rack::Middleware',
27
27
  )
28
28
  else
29
29
  # Insert after DebugExceptions for apps without ActiveRecord.
30
30
  app.config.middleware.insert_after(
31
31
  ActionDispatch::DebugExceptions,
32
- 'Airbrake::Rack::Middleware'
32
+ 'Airbrake::Rack::Middleware',
33
33
  )
34
34
  end
35
35
  end
@@ -55,21 +55,21 @@ module Airbrake
55
55
  require 'airbrake/rails/action_controller_route_subscriber'
56
56
  ActiveSupport::Notifications.subscribe(
57
57
  'start_processing.action_controller',
58
- Airbrake::Rails::ActionControllerRouteSubscriber.new
58
+ Airbrake::Rails::ActionControllerRouteSubscriber.new,
59
59
  )
60
60
 
61
61
  # Send route stats.
62
62
  require 'airbrake/rails/action_controller_notify_subscriber'
63
63
  ActiveSupport::Notifications.subscribe(
64
64
  'process_action.action_controller',
65
- Airbrake::Rails::ActionControllerNotifySubscriber.new
65
+ Airbrake::Rails::ActionControllerNotifySubscriber.new,
66
66
  )
67
67
 
68
68
  # Send performance breakdown: where a request spends its time.
69
69
  require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
70
70
  ActiveSupport::Notifications.subscribe(
71
71
  'process_action.action_controller',
72
- Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new
72
+ Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber.new,
73
73
  )
74
74
 
75
75
  require 'airbrake/rails/net_http' if defined?(Net) && defined?(Net::HTTP)
@@ -112,8 +112,8 @@ module Airbrake
112
112
  # Filter out parameters from SQL body.
113
113
  Airbrake.add_performance_filter(
114
114
  Airbrake::Filters::SqlFilter.new(
115
- ::ActiveRecord::Base.connection_config[:adapter]
116
- )
115
+ ::ActiveRecord::Base.connection_config[:adapter],
116
+ ),
117
117
  )
118
118
  end
119
119
  end
@@ -30,7 +30,7 @@ module Rake
30
30
  notice[:params].merge!(
31
31
  rake_task: task_info,
32
32
  execute_args: args,
33
- argv: ARGV.join(' ')
33
+ argv: ARGV.join(' '),
34
34
  )
35
35
 
36
36
  Airbrake.notify_sync(notice)
@@ -55,7 +55,7 @@ namespace :airbrake do
55
55
  username: ENV['USERNAME'],
56
56
  revision: ENV['REVISION'],
57
57
  repository: ENV['REPOSITORY'],
58
- version: ENV['VERSION']
58
+ version: ENV['VERSION'],
59
59
  }
60
60
  promise = Airbrake.notify_deploy(deploy_params)
61
61
  promise.then do
@@ -27,3 +27,33 @@ module Resque
27
27
  end
28
28
  end
29
29
  end
30
+
31
+ module Resque
32
+ # Measures elapsed time of a job and notifies Airbrake of the execution
33
+ # status.
34
+ #
35
+ # @since v9.6.0
36
+ class Job
37
+ # Store the original method to use it later.
38
+ alias perform_without_airbrake perform
39
+
40
+ def perform
41
+ timing = Airbrake::Benchmark.measure do
42
+ perform_without_airbrake
43
+ end
44
+ rescue StandardError => exception
45
+ Airbrake.notify_queue_sync(
46
+ queue: payload['class'],
47
+ error_count: 1,
48
+ timing: 0.01,
49
+ )
50
+ raise exception
51
+ else
52
+ Airbrake.notify_queue_sync(
53
+ queue: payload['class'],
54
+ error_count: 0,
55
+ timing: timing,
56
+ )
57
+ end
58
+ end
59
+ end
@@ -4,11 +4,23 @@ module Airbrake
4
4
  class ErrorHandler
5
5
  # rubocop:disable Lint/RescueException
6
6
  def call(worker, queue, _sqs_msg, body)
7
- yield
7
+ timing = Airbrake::Benchmark.measure do
8
+ yield
9
+ end
8
10
  rescue Exception => exception
9
11
  notify_airbrake(exception, worker, queue, body)
10
-
12
+ Airbrake.notify_queue(
13
+ queue: worker.class.to_s,
14
+ error_count: 1,
15
+ timing: 0.01,
16
+ )
11
17
  raise exception
18
+ else
19
+ Airbrake.notify_queue(
20
+ queue: worker.class.to_s,
21
+ error_count: 0,
22
+ timing: timing,
23
+ )
12
24
  end
13
25
  # rubocop:enable Lint/RescueException
14
26
 
@@ -24,7 +36,7 @@ module Airbrake
24
36
  def notice_context(queue, body)
25
37
  {
26
38
  queue: queue,
27
- body: body.is_a?(Array) ? { batch: body } : { body: body }
39
+ body: body.is_a?(Array) ? { batch: body } : { body: body },
28
40
  }
29
41
  end
30
42
  end
@@ -4,14 +4,25 @@ module Airbrake
4
4
  module Sidekiq
5
5
  # Provides integration with Sidekiq v2+.
6
6
  class ErrorHandler
7
- # rubocop:disable Lint/RescueException
8
7
  def call(_worker, context, _queue)
9
- yield
10
- rescue Exception => exception
8
+ timing = Airbrake::Benchmark.measure do
9
+ yield
10
+ end
11
+ rescue Exception => exception # rubocop:disable Lint/RescueException
11
12
  notify_airbrake(exception, context)
13
+ Airbrake.notify_queue(
14
+ queue: context['class'],
15
+ error_count: 1,
16
+ timing: 0.01,
17
+ )
12
18
  raise exception
19
+ else
20
+ Airbrake.notify_queue(
21
+ queue: context['class'],
22
+ error_count: 0,
23
+ timing: timing,
24
+ )
13
25
  end
14
- # rubocop:enable Lint/RescueException
15
26
 
16
27
  private
17
28
 
@@ -34,14 +45,8 @@ module Airbrake
34
45
  end
35
46
  end
36
47
 
37
- if Sidekiq::VERSION < '3'
38
- Sidekiq.configure_server do |config|
39
- config.server_middleware do |chain|
40
- chain.add(Airbrake::Sidekiq::ErrorHandler)
41
- end
42
- end
43
- else
44
- Sidekiq.configure_server do |config|
45
- config.error_handlers << Airbrake::Sidekiq::ErrorHandler.new.method(:notify_airbrake)
48
+ Sidekiq.configure_server do |config|
49
+ config.server_middleware do |chain|
50
+ chain.add(Airbrake::Sidekiq::ErrorHandler)
46
51
  end
47
52
  end
@@ -32,3 +32,35 @@ module Airbrake
32
32
  end
33
33
 
34
34
  Sneakers.error_reporters << Airbrake::Sneakers::ErrorReporter.new
35
+
36
+ module Sneakers
37
+ # @todo Migrate to Sneakers v2.12.0 middleware API when it's released
38
+ # @see https://github.com/jondot/sneakers/pull/364
39
+ module Worker
40
+ # Sneakers v2.7.0+ renamed `do_work` to `process_work`.
41
+ if method_defined?(:process_work)
42
+ alias process_work_without_airbrake process_work
43
+ else
44
+ alias process_work_without_airbrake do_work
45
+ end
46
+
47
+ def process_work(delivery_info, metadata, msg, handler)
48
+ timing = Airbrake::Benchmark.measure do
49
+ process_work_without_airbrake(delivery_info, metadata, msg, handler)
50
+ end
51
+ rescue Exception => exception # rubocop:disable Lint/RescueException
52
+ Airbrake.notify_queue(
53
+ queue: self.class.to_s,
54
+ error_count: 1,
55
+ timing: 0.01,
56
+ )
57
+ raise exception
58
+ else
59
+ Airbrake.notify_queue(
60
+ queue: self.class.to_s,
61
+ error_count: 0,
62
+ timing: timing,
63
+ )
64
+ end
65
+ end
66
+ end
@@ -1,5 +1,5 @@
1
1
  # We use Semantic Versioning v2.0.0
2
2
  # More information: http://semver.org/
3
3
  module Airbrake
4
- AIRBRAKE_VERSION = '9.5.5'.freeze
4
+ AIRBRAKE_VERSION = '10.0.0'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airbrake
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.5.5
4
+ version: 10.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airbrake Technologies, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-02 00:00:00.000000000 Z
11
+ date: 2020-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: airbrake-ruby
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.8'
19
+ version: '4.12'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '4.8'
26
+ version: '4.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -254,6 +254,20 @@ dependencies:
254
254
  - - '='
255
255
  - !ruby/object:Gem::Version
256
256
  version: 1.9.0
257
+ - !ruby/object:Gem::Dependency
258
+ name: redis-namespace
259
+ requirement: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - '='
262
+ - !ruby/object:Gem::Version
263
+ version: 1.6.0
264
+ type: :development
265
+ prerelease: false
266
+ version_requirements: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - '='
269
+ - !ruby/object:Gem::Version
270
+ version: 1.6.0
257
271
  - !ruby/object:Gem::Dependency
258
272
  name: sidekiq
259
273
  requirement: !ruby/object:Gem::Requirement