sentry-rails 5.3.0 → 5.8.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: c10021ca91c13dc4b34f024269a01974d75e8971b72b027f497c7c3c248ba448
4
- data.tar.gz: e4daa4206bd67b93787a7b08653808d72f7e1f667caab27f2382496e9dec474b
3
+ metadata.gz: 7338e366bfa078e533320c9d9fcac994ca4202104a3a3efb2069644d4ac80e9c
4
+ data.tar.gz: 27b90498fc73e7884ffcdea4733244723fa0e6f8a48d3322f9e7a91b25f8b73b
5
5
  SHA512:
6
- metadata.gz: 18b27b1e7b1acc3facd390069f7cd62ef434bd94b5dee2cd440f6f29cfb7b3411193c7425851116aaa199394f57df93c3d1be4c634e8d9a985786342a7ca6745
7
- data.tar.gz: f4a3c87c7b053b9e3c0adaffa620570b0d92be984d8c2337df552fcab1a9cae1b34c299f3bdb5506106037d960f35b8cc8f51a9f3b73d8666e2ee0ae02634055
6
+ metadata.gz: 7c67ec56cf2d1cd69d8808f7a83ce2af69fea58781fff3c5979bac4005ea077451b9682e6e45b1b8333d9d1b42cb29690dc53cc59b6baef4ba2ef47895bd0bb0
7
+ data.tar.gz: 1ec19c91b4d6e7bd2255c2f73ad12f035d90433a1d36a6fbba4f7ec21cbe6d5694b9ec44690ac22411003ab2e6948b9a56da8ba441123a84daa1d4b477266a51
data/Gemfile CHANGED
@@ -18,12 +18,14 @@ else
18
18
  gem "sqlite3", platform: :ruby
19
19
  end
20
20
 
21
- if rails_version >= Gem::Version.new("7.0.0")
22
- 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"
23
23
  else
24
24
  gem "rails", "~> #{rails_version}"
25
25
  end
26
26
 
27
+ gem "mini_magick"
28
+
27
29
  gem "sprockets-rails"
28
30
 
29
31
  gem "sidekiq"
@@ -2,6 +2,8 @@ module Sentry
2
2
  module Rails
3
3
  module ActionCableExtensions
4
4
  class ErrorHandler
5
+ OP_NAME = "websocket.server".freeze
6
+
5
7
  class << self
6
8
  def capture(connection, transaction_name:, extra_context: nil, &block)
7
9
  return block.call unless Sentry.initialized?
@@ -13,13 +15,14 @@ module Sentry
13
15
  Sentry.with_scope do |scope|
14
16
  scope.set_rack_env(env)
15
17
  scope.set_context("action_cable", extra_context) if extra_context
16
- scope.set_transaction_name(transaction_name)
17
- transaction = start_transaction(env, scope.transaction_name)
18
+ scope.set_transaction_name(transaction_name, source: :view)
19
+ transaction = start_transaction(env, scope)
18
20
  scope.set_span(transaction) if transaction
19
21
 
20
22
  begin
21
- block.call
23
+ result = block.call
22
24
  finish_transaction(transaction, 200)
25
+ result
23
26
  rescue Exception => e # rubocop:disable Lint/RescueException
24
27
  Sentry::Rails.capture_exception(e)
25
28
  finish_transaction(transaction, 500)
@@ -29,10 +32,12 @@ module Sentry
29
32
  end
30
33
  end
31
34
 
32
- def start_transaction(env, transaction_name)
35
+ def start_transaction(env, scope)
33
36
  sentry_trace = env["HTTP_SENTRY_TRACE"]
34
- options = { name: transaction_name, op: "rails.action_cable".freeze }
35
- transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
37
+ baggage = env["HTTP_BAGGAGE"]
38
+
39
+ options = { name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME }
40
+ transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, baggage: baggage, **options) if sentry_trace
36
41
  Sentry.start_transaction(transaction: transaction, **options)
37
42
  end
38
43
 
@@ -16,16 +16,18 @@ module Sentry
16
16
  end
17
17
 
18
18
  class SentryReporter
19
+ OP_NAME = "queue.active_job".freeze
20
+
19
21
  class << self
20
22
  def record(job, &block)
21
23
  Sentry.with_scope do |scope|
22
24
  begin
23
- scope.set_transaction_name(job.class.name)
25
+ scope.set_transaction_name(job.class.name, source: :task)
24
26
  transaction =
25
27
  if job.is_a?(::Sentry::SendEventJob)
26
28
  nil
27
29
  else
28
- Sentry.start_transaction(name: scope.transaction_name, op: "active_job")
30
+ Sentry.start_transaction(name: scope.transaction_name, source: scope.transaction_source, op: OP_NAME)
29
31
  end
30
32
 
31
33
  scope.set_span(transaction) if transaction
@@ -1,14 +1,12 @@
1
1
  module Sentry
2
2
  class BackgroundWorker
3
3
  def _perform(&block)
4
+ block.call
5
+ ensure
4
6
  # some applications have partial or even no AR connection
5
7
  if ActiveRecord::Base.connected?
6
8
  # make sure the background worker returns AR connection if it accidentally acquire one during serialization
7
- ActiveRecord::Base.connection_pool.with_connection do
8
- block.call
9
- end
10
- else
11
- block.call
9
+ ActiveRecord::Base.connection_pool.release_connection
12
10
  end
13
11
  end
14
12
  end
@@ -1,11 +1,11 @@
1
1
  module Sentry
2
2
  module Rails
3
3
  class CaptureExceptions < Sentry::Rack::CaptureExceptions
4
- def initialize(app)
4
+ def initialize(_)
5
5
  super
6
6
 
7
- if defined?(::Sprockets::Rails)
8
- @assets_regex = %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
7
+ if Sentry.initialized?
8
+ @assets_regexp = Sentry.configuration.rails.assets_regexp
9
9
  end
10
10
  end
11
11
 
@@ -17,28 +17,30 @@ module Sentry
17
17
  end
18
18
 
19
19
  def transaction_op
20
- "rails.request".freeze
20
+ "http.server".freeze
21
21
  end
22
22
 
23
- def capture_exception(exception)
24
- current_scope = Sentry.get_current_scope
23
+ def capture_exception(exception, env)
24
+ request = ActionDispatch::Request.new(env)
25
25
 
26
- if original_transaction = current_scope.rack_env["sentry.original_transaction"]
27
- current_scope.set_transaction_name(original_transaction)
26
+ # the exception will be swallowed by ShowExceptions middleware
27
+ return if request.show_exceptions? && !Sentry.configuration.rails.report_rescued_exceptions
28
+ Sentry::Rails.capture_exception(exception).tap do |event|
29
+ env[ERROR_EVENT_ID_KEY] = event.event_id if event
28
30
  end
29
-
30
- Sentry::Rails.capture_exception(exception)
31
31
  end
32
32
 
33
33
  def start_transaction(env, scope)
34
34
  sentry_trace = env["HTTP_SENTRY_TRACE"]
35
- options = { name: scope.transaction_name, op: transaction_op }
35
+ baggage = env["HTTP_BAGGAGE"]
36
+
37
+ options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
36
38
 
37
- if @assets_regex && scope.transaction_name.match?(@assets_regex)
39
+ if @assets_regexp && scope.transaction_name.match?(@assets_regexp)
38
40
  options.merge!(sampled: false)
39
41
  end
40
42
 
41
- transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
43
+ transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, baggage: baggage, **options) if sentry_trace
42
44
  Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
43
45
  end
44
46
  end
@@ -60,12 +60,29 @@ module Sentry
60
60
 
61
61
  attr_accessor :tracing_subscribers
62
62
 
63
+ # sentry-rails by default skips asset request' transactions by checking if the path matches
64
+ #
65
+ # ```rb
66
+ # %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
67
+ # ```
68
+ #
69
+ # If you want to use a different pattern, you can configure the `assets_regexp` option like:
70
+ #
71
+ # ```rb
72
+ # Sentry.init do |config|
73
+ # config.rails.assets_regexp = /my_regexp/
74
+ # end
75
+ # ```
76
+ attr_accessor :assets_regexp
77
+
63
78
  def initialize
64
79
  @register_error_subscriber = false
65
80
  @report_rescued_exceptions = true
66
81
  @skippable_job_adapters = []
82
+ @assets_regexp = if defined?(::Sprockets::Rails)
83
+ %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
84
+ end
67
85
  @tracing_subscribers = Set.new([
68
- Sentry::Rails::Tracing::ActionControllerSubscriber,
69
86
  Sentry::Rails::Tracing::ActionViewSubscriber,
70
87
  Sentry::Rails::Tracing::ActiveRecordSubscriber,
71
88
  Sentry::Rails::Tracing::ActiveStorageSubscriber
@@ -2,8 +2,34 @@ module Sentry
2
2
  module Rails
3
3
  module ControllerTransaction
4
4
  def self.included(base)
5
- base.prepend_before_action do |controller|
6
- Sentry.get_current_scope.set_transaction_name("#{controller.class}##{controller.action_name}")
5
+ base.prepend_around_action(:sentry_around_action)
6
+ end
7
+
8
+ private
9
+
10
+ def sentry_around_action
11
+ if Sentry.initialized?
12
+ transaction_name = "#{self.class}##{action_name}"
13
+ Sentry.get_current_scope.set_transaction_name(transaction_name, source: :view)
14
+ Sentry.with_child_span(op: "view.process_action.action_controller", description: transaction_name) do |child_span|
15
+ if child_span
16
+ begin
17
+ result = yield
18
+ ensure
19
+ child_span.set_http_status(response.status)
20
+ child_span.set_data(:format, request.format)
21
+ child_span.set_data(:method, request.method)
22
+ child_span.set_data(:path, request.path)
23
+ child_span.set_data(:params, request.params)
24
+ end
25
+
26
+ result
27
+ else
28
+ yield
29
+ end
30
+ end
31
+ else
32
+ yield
7
33
  end
8
34
  end
9
35
  end
@@ -1,10 +1,25 @@
1
1
  module Sentry
2
2
  module Rails
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
- # See https://github.com/rails/rails/blob/main/activesupport/lib/active_support/error_reporter.rb for more information.
4
+ # See https://github.com/rails/rails/blob/main/activesupport/lib/active_support/error_reporter.rb to learn more about reporting APIs.
5
+ # If you want Sentry to subscribe to the error reporter, please set `config.rails.register_error_subscriber` to `true`.
5
6
  class ErrorSubscriber
6
- def report(error, handled:, severity:, context:)
7
- Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: { handled: handled })
7
+ SKIP_SOURCES = Regexp.union([/.*_cache_store.active_support/])
8
+
9
+ def report(error, handled:, severity:, context:, source: nil)
10
+ tags = { handled: handled }
11
+
12
+ if source
13
+ return if SKIP_SOURCES.match?(source)
14
+ tags[:source] = source
15
+ end
16
+
17
+ if context[:tags].is_a?(Hash)
18
+ context = context.dup
19
+ tags.merge!(context.delete(:tags))
20
+ end
21
+
22
+ Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: tags)
8
23
  end
9
24
  end
10
25
  end
@@ -53,6 +53,13 @@ module Sentry
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
+ if $ERROR_INFO && !($ERROR_INFO.is_a?(SystemExit) && $ERROR_INFO.success?)
60
+ Sentry::Rails.capture_exception($ERROR_INFO, tags: { source: "runner" })
61
+ end
62
+ end
56
63
  end
57
64
 
58
65
  def configure_project_root
@@ -110,7 +117,7 @@ module Sentry
110
117
  end
111
118
 
112
119
  def activate_tracing
113
- if Sentry.configuration.tracing_enabled?
120
+ if Sentry.configuration.tracing_enabled? && Sentry.configuration.instrumenter == :sentry
114
121
  subscribers = Sentry.configuration.rails.tracing_subscribers
115
122
  Sentry::Rails::Tracing.register_subscribers(subscribers)
116
123
  Sentry::Rails::Tracing.subscribe_tracing_events
@@ -8,14 +8,20 @@ module Sentry
8
8
  extend InstrumentPayloadCleanupHelper
9
9
 
10
10
  EVENT_NAMES = ["process_action.action_controller"].freeze
11
+ OP_NAME = "view.process_action.action_controller".freeze
11
12
 
12
13
  def self.subscribe!
14
+ Sentry.logger.warn <<~MSG
15
+ DEPRECATION WARNING: sentry-rails has changed its approach on controller span recording and #{self.name} is now depreacted.
16
+ Please stop using or referencing #{self.name} as it will be removed in the next major release.
17
+ MSG
18
+
13
19
  subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
14
20
  controller = payload[:controller]
15
21
  action = payload[:action]
16
22
 
17
23
  record_on_current_span(
18
- op: event_name,
24
+ op: OP_NAME,
19
25
  start_timestamp: payload[START_TIMESTAMP_NAME],
20
26
  description: "#{controller}##{action}",
21
27
  duration: duration
@@ -14,6 +14,7 @@ module Sentry
14
14
 
15
15
  record_on_current_span(op: SPAN_PREFIX + event_name, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:sql], duration: duration) do |span|
16
16
  span.set_data(:connection_id, payload[:connection_id])
17
+ span.set_tag(:cached, true) if payload.fetch(:cached, false) # cached key is only set for hits in the QueryCache, from Rails 5.1
17
18
  end
18
19
  end
19
20
  end
@@ -21,7 +21,7 @@ module Sentry
21
21
 
22
22
  def self.subscribe!
23
23
  subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
24
- record_on_current_span(op: event_name, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:service], duration: duration) do |span|
24
+ record_on_current_span(op: "file.#{event_name}".freeze, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:service], duration: duration) do |span|
25
25
  payload.each do |key, value|
26
26
  span.set_data(key, value) unless key == START_TIMESTAMP_NAME
27
27
  end
@@ -67,7 +67,7 @@ module Sentry
67
67
  end
68
68
 
69
69
  def self.get_current_transaction
70
- Sentry.get_current_scope.get_transaction
70
+ Sentry.get_current_scope.get_transaction if Sentry.initialized?
71
71
  end
72
72
 
73
73
  # it's just a container for the extended method
@@ -1,5 +1,5 @@
1
1
  module Sentry
2
2
  module Rails
3
- VERSION = "5.3.0"
3
+ VERSION = "5.8.0"
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.3.0"
26
+ spec.add_dependency "sentry-ruby", "~> 5.8.0"
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.3.0
4
+ version: 5.8.0
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-04-27 00:00:00.000000000 Z
11
+ date: 2023-02-06 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.3.0
33
+ version: 5.8.0
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.3.0
40
+ version: 5.8.0
41
41
  description: A gem that provides Rails integration for the Sentry error logger
42
42
  email: accounts@sentry.io
43
43
  executables: []