sentry-rails 5.1.0 → 5.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f45143dd79cff19a0e7338912f235cec728d9ceb81a37e7a50df78a1722ce1b8
4
- data.tar.gz: 7b5a8dec4f9b6875f6f42794911d30e7a75e0a8662e7d5e83584726066eb3fd4
3
+ metadata.gz: 92b1952096935f672e03a41883297d867b70e433c92434b24420062c37d2325f
4
+ data.tar.gz: 3cdfb19c85436bdc509e00512734fe6eb11880bdbe22ef50e6d99908f38daf16
5
5
  SHA512:
6
- metadata.gz: 0dbdd5331da560f4bc67a84390bb1f3579fbe7e03da95758cc2e3b103540f407bb2efb153202070f57dc4e2e1b5044dd9dca7e237272460560531d160890211c
7
- data.tar.gz: 1163c26220a308aca6fe3f624e4358446f82d1919eda4daf0c38729f1977eba08b53c4f8bb65543adfc1df7a129ca4098af35060acb3d921d8ddf58025176633
6
+ metadata.gz: 2271053cd6e6d9f04ba55258d177347f8df8ce74d6c15bdb3083eef6cc3cd1b8f4847c448071c8e03b33d90498acc04f384c4cfe3730c792af046a1860a76a53
7
+ data.tar.gz: 345700856d420c3e562201cedb88d18d396d4f60487bb945f262bffba028ca7f9b12aa481deeebad7607e8f9baa0c4db30308d97a856b45bd7fd0e3f75e06258
data/.gitignore CHANGED
@@ -5,7 +5,7 @@
5
5
  /doc/
6
6
  /pkg/
7
7
  /spec/reports/
8
- /spec/support/test_rails_app/db
8
+ /spec/dummy/test_rails_app/db
9
9
  /tmp/
10
10
 
11
11
  # rspec failure tracking
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source "https://rubygems.org"
2
+ git_source(:github) { |name| "https://github.com/#{name}.git" }
2
3
 
3
4
  # Specify your gem's dependencies in sentry-ruby.gemspec
4
5
  gemspec
@@ -17,12 +18,14 @@ else
17
18
  gem "sqlite3", platform: :ruby
18
19
  end
19
20
 
20
- if rails_version >= Gem::Version.new("7.0.0")
21
- gem "rails", github: "rails/rails", branch: "7-0-stable"
21
+ if rails_version > Gem::Version.new("7.0.0")
22
+ gem "rails", github: "rails/rails"
22
23
  else
23
24
  gem "rails", "~> #{rails_version}"
24
25
  end
25
26
 
27
+ gem "mini_magick"
28
+
26
29
  gem "sprockets-rails"
27
30
 
28
31
  gem "sidekiq"
@@ -5,76 +5,80 @@ module Sentry
5
5
  if !Sentry.initialized? || already_supported_by_sentry_integration?
6
6
  super
7
7
  else
8
- Sentry.with_scope do |scope|
9
- capture_and_reraise_with_sentry(scope) do
10
- super
11
- end
8
+ SentryReporter.record(self) do
9
+ super
12
10
  end
13
11
  end
14
12
  end
15
13
 
16
- def capture_and_reraise_with_sentry(scope, &block)
17
- scope.set_transaction_name(self.class.name)
18
- transaction =
19
- if is_a?(::Sentry::SendEventJob)
20
- nil
21
- else
22
- Sentry.start_transaction(name: scope.transaction_name, op: "active_job")
23
- end
24
-
25
- scope.set_span(transaction) if transaction
26
-
27
- return_value = block.call
14
+ def already_supported_by_sentry_integration?
15
+ Sentry.configuration.rails.skippable_job_adapters.include?(self.class.queue_adapter.class.to_s)
16
+ end
28
17
 
29
- finish_sentry_transaction(transaction, 200)
18
+ class SentryReporter
19
+ class << self
20
+ def record(job, &block)
21
+ Sentry.with_scope do |scope|
22
+ begin
23
+ scope.set_transaction_name(job.class.name)
24
+ transaction =
25
+ if job.is_a?(::Sentry::SendEventJob)
26
+ nil
27
+ else
28
+ Sentry.start_transaction(name: scope.transaction_name, op: "active_job")
29
+ end
30
30
 
31
- return_value
32
- rescue Exception => e # rubocop:disable Lint/RescueException
33
- finish_sentry_transaction(transaction, 500)
31
+ scope.set_span(transaction) if transaction
34
32
 
35
- Sentry::Rails.capture_exception(
36
- e,
37
- extra: sentry_context,
38
- tags: {
39
- job_id: job_id,
40
- provider_job_id: provider_job_id
41
- }
42
- )
43
- raise e
44
- end
33
+ yield.tap do
34
+ finish_sentry_transaction(transaction, 200)
35
+ end
36
+ rescue Exception => e # rubocop:disable Lint/RescueException
37
+ finish_sentry_transaction(transaction, 500)
45
38
 
46
- def finish_sentry_transaction(transaction, status)
47
- return unless transaction
39
+ Sentry::Rails.capture_exception(
40
+ e,
41
+ extra: sentry_context(job),
42
+ tags: {
43
+ job_id: job.job_id,
44
+ provider_job_id: job.provider_job_id
45
+ }
46
+ )
47
+ raise
48
+ end
49
+ end
50
+ end
48
51
 
49
- transaction.set_http_status(status)
50
- transaction.finish
51
- end
52
+ def finish_sentry_transaction(transaction, status)
53
+ return unless transaction
52
54
 
53
- def already_supported_by_sentry_integration?
54
- Sentry.configuration.rails.skippable_job_adapters.include?(self.class.queue_adapter.class.to_s)
55
- end
55
+ transaction.set_http_status(status)
56
+ transaction.finish
57
+ end
56
58
 
57
- def sentry_context
58
- {
59
- active_job: self.class.name,
60
- arguments: sentry_serialize_arguments(arguments),
61
- scheduled_at: scheduled_at,
62
- job_id: job_id,
63
- provider_job_id: provider_job_id,
64
- locale: locale
65
- }
66
- end
59
+ def sentry_context(job)
60
+ {
61
+ active_job: job.class.name,
62
+ arguments: sentry_serialize_arguments(job.arguments),
63
+ scheduled_at: job.scheduled_at,
64
+ job_id: job.job_id,
65
+ provider_job_id: job.provider_job_id,
66
+ locale: job.locale
67
+ }
68
+ end
67
69
 
68
- def sentry_serialize_arguments(argument)
69
- case argument
70
- when Hash
71
- argument.transform_values { |v| sentry_serialize_arguments(v) }
72
- when Array, Enumerable
73
- argument.map { |v| sentry_serialize_arguments(v) }
74
- when ->(v) { v.respond_to?(:to_global_id) }
75
- argument.to_global_id.to_s rescue argument
76
- else
77
- argument
70
+ def sentry_serialize_arguments(argument)
71
+ case argument
72
+ when Hash
73
+ argument.transform_values { |v| sentry_serialize_arguments(v) }
74
+ when Array, Enumerable
75
+ argument.map { |v| sentry_serialize_arguments(v) }
76
+ when ->(v) { v.respond_to?(:to_global_id) }
77
+ argument.to_global_id.to_s rescue argument
78
+ else
79
+ argument
80
+ end
81
+ end
78
82
  end
79
83
  end
80
84
  end
@@ -1,10 +1,10 @@
1
1
  module Sentry
2
2
  class BackgroundWorker
3
3
  def _perform(&block)
4
+ block.call
5
+ ensure
4
6
  # make sure the background worker returns AR connection if it accidentally acquire one during serialization
5
- ActiveRecord::Base.connection_pool.with_connection do
6
- block.call
7
- end
7
+ ActiveRecord::Base.connection_pool.release_connection
8
8
  end
9
9
  end
10
10
  end
@@ -20,14 +20,21 @@ module Sentry
20
20
  "rails.request".freeze
21
21
  end
22
22
 
23
- def capture_exception(exception)
23
+ def capture_exception(exception, env)
24
+ request = ActionDispatch::Request.new(env)
25
+
26
+ # the exception will be swallowed by ShowExceptions middleware
27
+ return if request.show_exceptions? && !Sentry.configuration.rails.report_rescued_exceptions
28
+
24
29
  current_scope = Sentry.get_current_scope
25
30
 
26
- if original_transaction = current_scope.rack_env["sentry.original_transaction"]
31
+ if original_transaction = env["sentry.original_transaction"]
27
32
  current_scope.set_transaction_name(original_transaction)
28
33
  end
29
34
 
30
- Sentry::Rails.capture_exception(exception)
35
+ Sentry::Rails.capture_exception(exception).tap do |event|
36
+ env[ERROR_EVENT_ID_KEY] = event.event_id if event
37
+ end
31
38
  end
32
39
 
33
40
  def start_transaction(env, scope)
@@ -39,7 +46,7 @@ module Sentry
39
46
  end
40
47
 
41
48
  transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
42
- Sentry.start_transaction(transaction: transaction, **options)
49
+ Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
43
50
  end
44
51
  end
45
52
  end
@@ -42,6 +42,12 @@ module Sentry
42
42
  'ActiveRecord::RecordNotFound'
43
43
  ].freeze
44
44
  class Configuration
45
+ # Rails 7.0 introduced a new error reporter feature, which the SDK once opted-in by default.
46
+ # But after receiving multiple issue reports, the integration seemed to cause serious troubles to some users.
47
+ # So the integration is now controlled by this configuration, which is disabled (false) by default.
48
+ # More information can be found from: https://github.com/rails/rails/pull/43625#issuecomment-1072514175
49
+ attr_accessor :register_error_subscriber
50
+
45
51
  # Rails catches exceptions in the ActionDispatch::ShowExceptions or
46
52
  # ActionDispatch::DebugExceptions middlewares, depending on the environment.
47
53
  # When `rails_report_rescued_exceptions` is true (it is by default), Sentry
@@ -55,6 +61,7 @@ module Sentry
55
61
  attr_accessor :tracing_subscribers
56
62
 
57
63
  def initialize
64
+ @register_error_subscriber = false
58
65
  @report_rescued_exceptions = true
59
66
  @skippable_job_adapters = []
60
67
  @tracing_subscribers = Set.new([
@@ -3,17 +3,17 @@ module Sentry
3
3
  # This is not a user-facing class. You should use it with Rails 7.0's error reporter feature and its interfaces.
4
4
  # See https://github.com/rails/rails/blob/main/activesupport/lib/active_support/error_reporter.rb for more information.
5
5
  class ErrorSubscriber
6
- def report(error, handled:, severity:, context:)
7
- # a component may already have an integration to capture exceptions while its operation is also wrapped inside an `app.executor.wrap` (e.g. ActionCable)
8
- # in such condition, the exception would be captured repeatedly. it usually happens in this order:
9
- #
10
- # 1. exception captured and reported by the component integration and re-raised
11
- # 2. exception captured by the executor, which then reports it with executor.error_reporter
12
- #
13
- # and because there's no direct communication between the 2 callbacks, we need a way to identify if an exception has been captured before
14
- # using a Sentry-specific intance variable should be the last impactful way
15
- return if error.instance_variable_get(:@__sentry_captured)
16
- Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: { handled: handled })
6
+ SKIP_SOURCES = Regexp.union([/.*_cache_store.active_support/])
7
+
8
+ def report(error, handled:, severity:, context:, source: nil)
9
+ tags = { handled: handled }
10
+
11
+ if source
12
+ return if SKIP_SOURCES.match?(source)
13
+ tags[:source] = source
14
+ end
15
+
16
+ Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: tags)
17
17
  end
18
18
  end
19
19
  end
@@ -47,12 +47,17 @@ module Sentry
47
47
  inject_breadcrumbs_logger
48
48
  activate_tracing
49
49
 
50
- register_error_subscriber(app) if ::Rails.version.to_f >= 7.0
50
+ register_error_subscriber(app) if ::Rails.version.to_f >= 7.0 && Sentry.configuration.rails.register_error_subscriber
51
51
  end
52
52
 
53
53
  runner do
54
54
  next unless Sentry.initialized?
55
55
  Sentry.configuration.background_worker_threads = 0
56
+
57
+ at_exit do
58
+ # TODO: Add a condition for Rails 7.1 to avoid confliction with https://github.com/rails/rails/pull/44999
59
+ Sentry::Rails.capture_exception($ERROR_INFO, tags: { source: "runner" }) if $ERROR_INFO
60
+ end
56
61
  end
57
62
 
58
63
  def configure_project_root
@@ -40,15 +40,12 @@ module Sentry
40
40
  def record_on_current_span(duration:, **options)
41
41
  return unless options[:start_timestamp]
42
42
 
43
- scope = Sentry.get_current_scope
44
- transaction = scope.get_transaction
45
- return unless transaction && transaction.sampled
46
-
47
- span = transaction.start_child(**options)
48
- # duration in ActiveSupport is computed in millisecond
49
- # so we need to covert it as second before calculating the timestamp
50
- span.set_timestamp(span.start_timestamp + duration / 1000)
51
- yield(span) if block_given?
43
+ Sentry.with_child_span(**options) do |child_span|
44
+ # duration in ActiveSupport is computed in millisecond
45
+ # so we need to covert it as second before calculating the timestamp
46
+ child_span.set_timestamp(child_span.start_timestamp + duration / 1000)
47
+ yield(child_span) if block_given?
48
+ end
52
49
  end
53
50
  end
54
51
  end
@@ -1,5 +1,5 @@
1
1
  module Sentry
2
2
  module Rails
3
- VERSION = "5.1.0"
3
+ VERSION = "5.4.2"
4
4
  end
5
5
  end
data/sentry-rails.gemspec CHANGED
@@ -23,5 +23,5 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "railties", ">= 5.0"
26
- spec.add_dependency "sentry-ruby-core", "~> 5.1.0"
26
+ spec.add_dependency "sentry-ruby", "~> 5.4.2"
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentry-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sentry Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-10 00:00:00.000000000 Z
11
+ date: 2022-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sentry-ruby-core
28
+ name: sentry-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 5.1.0
33
+ version: 5.4.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 5.1.0
40
+ version: 5.4.2
41
41
  description: A gem that provides Rails integration for the Sentry error logger
42
42
  email: accounts@sentry.io
43
43
  executables: []