sentry-rails 4.4.0 → 5.0.2

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: 4fba76642a6793e6026aca10630ca659fae4832d31aed0710d31805da14676c3
4
- data.tar.gz: 15a570cc7acefceeb6e601d52cd2b55763761cb9e855d21282ba75b5a05a578b
3
+ metadata.gz: dbb2adfc21656bba09244e0895c88a20f58e2401fcb5d4b693f48d10319c9121
4
+ data.tar.gz: 6e2c595d8d719208524bfa270d6aa0e8d2123c60b80923fe05323f93bb29f98f
5
5
  SHA512:
6
- metadata.gz: a57118b831bf7830caea725b3fdd008d4015026db29bb82dbbdccf98476a0686a795868b4d4831e7ee09cd8cbffa0adeadeb2ab646a37f37ee3c74da90f34874
7
- data.tar.gz: 0e0e165ce9d0ee629bd8df754e08615fc1ce73b68928b483ba2abe5304bfe71ee92037c617f63b594b41286f722c62bbc79f44ff116a0546ef833e749fdba81b
6
+ metadata.gz: b3af907f32e77d292f5d86b99bfa5d62e580118e4971f940eb07278951147a9e53b4680926d436833d69548b0872eb560cb2c73dc44361b86ab2e951271d9519
7
+ data.tar.gz: daad9ecf642f47a149ff2065ee3ce79e56ab33b2379b477f60d86c85ca051c8e0c4cc924c1c68786bdb015b7eac4e998c336b8d5ad0883fe0f11050586fc1103
data/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Changelog
2
2
 
3
+ Individual gem's changelog has been deprecated. Please check the [project changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md).
4
+
3
5
  ## 4.4.0
4
6
 
5
7
  ### Features
data/Gemfile CHANGED
@@ -2,36 +2,42 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in sentry-ruby.gemspec
4
4
  gemspec
5
+ gem "sentry-ruby", path: "../sentry-ruby"
5
6
 
6
7
  rails_version = ENV["RAILS_VERSION"]
7
- rails_version = "6.1.0" if rails_version.nil?
8
+ rails_version = "7.0.0" if rails_version.nil?
9
+ rails_version = Gem::Version.new(rails_version)
8
10
 
9
11
  gem 'activerecord-jdbcmysql-adapter', platform: :jruby
10
12
  gem "jdbc-sqlite3", platform: :jruby
11
13
 
12
- if rails_version.to_f < 6
14
+ if rails_version < Gem::Version.new("6.0.0")
13
15
  gem "sqlite3", "~> 1.3.0", platform: :ruby
14
16
  else
15
17
  gem "sqlite3", platform: :ruby
16
18
  end
17
19
 
18
- gem "rails", "~> #{rails_version}"
20
+ if rails_version >= Gem::Version.new("7.0.0")
21
+ gem "rails", github: "rails/rails", branch: "7-0-stable"
22
+ else
23
+ gem "rails", "~> #{rails_version}"
24
+ end
25
+
19
26
  gem "sprockets-rails"
20
27
 
28
+ gem "sidekiq"
29
+
21
30
  gem "rspec", "~> 3.0"
22
31
  gem "rspec-retry"
23
32
  gem "rspec-rails", "~> 4.0"
24
- gem "codecov", "0.2.12"
33
+ gem 'simplecov'
34
+ gem "simplecov-cobertura", "~> 1.4"
35
+ gem "rexml"
25
36
 
26
37
  gem "rake", "~> 12.0"
27
38
 
28
- # TODO: Remove this if https://github.com/jruby/jruby/issues/6547 is addressed
29
- gem "i18n", "<= 1.8.7"
30
-
31
- gem "sidekiq"
32
-
33
- gem "sentry-ruby", path: "../sentry-ruby"
34
-
39
+ gem "object_tracer"
40
+ gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
35
41
  gem "pry"
36
42
 
37
43
  gem "benchmark-ips"
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 st0012
3
+ Copyright (c) 2020 Sentry
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/Rakefile CHANGED
@@ -5,4 +5,10 @@ RSpec::Core::RakeTask.new(:spec).tap do |task|
5
5
  task.rspec_opts = "--order rand"
6
6
  end
7
7
 
8
- task :default => :spec
8
+ task :isolated_specs do
9
+ Dir["spec/isolated/*"].each do |file|
10
+ sh "bundle exec ruby #{file}"
11
+ end
12
+ end
13
+
14
+ task :default => [:spec, :isolated_specs]
@@ -16,17 +16,12 @@ if defined?(ActiveJob)
16
16
  discard_on ActiveJob::DeserializationError
17
17
  else
18
18
  # mimic what discard_on does for Rails 5.0
19
- rescue_from ActiveJob::DeserializationError do
20
- logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{error.cause.inspect}."
19
+ rescue_from ActiveJob::DeserializationError do |exception|
20
+ logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{exception.cause.inspect}."
21
21
  end
22
22
  end
23
23
 
24
24
  def perform(event, hint = {})
25
- # users don't need the tracing result of this job
26
- if transaction = Sentry.get_current_scope.span
27
- transaction.instance_variable_set(:@sampled, false)
28
- end
29
-
30
25
  Sentry.send_event(event, hint)
31
26
  end
32
27
  end
@@ -0,0 +1,96 @@
1
+ module Sentry
2
+ module Rails
3
+ module ActionCableExtensions
4
+ class ErrorHandler
5
+ class << self
6
+ def capture(connection, transaction_name:, extra_context: nil, &block)
7
+ return block.call unless Sentry.initialized?
8
+ # ActionCable's ConnectionStub (for testing) doesn't implement the exact same interfaces as Connection::Base.
9
+ # One thing that's missing is `env`. So calling `connection.env` direclty will fail in test environments when `stub_connection` is used.
10
+ # See https://github.com/getsentry/sentry-ruby/pull/1684 for more information.
11
+ env = connection.respond_to?(:env) ? connection.env : {}
12
+
13
+ Sentry.with_scope do |scope|
14
+ scope.set_rack_env(env)
15
+ 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_span(transaction) if transaction
19
+
20
+ begin
21
+ block.call
22
+ finish_transaction(transaction, 200)
23
+ rescue Exception => e # rubocop:disable Lint/RescueException
24
+ Sentry::Rails.capture_exception(e)
25
+ finish_transaction(transaction, 500)
26
+
27
+ raise
28
+ end
29
+ end
30
+ end
31
+
32
+ def start_transaction(env, transaction_name)
33
+ 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
36
+ Sentry.start_transaction(transaction: transaction, **options)
37
+ end
38
+
39
+ def finish_transaction(transaction, status_code)
40
+ return unless transaction
41
+
42
+ transaction.set_http_status(status_code)
43
+ transaction.finish
44
+ end
45
+ end
46
+ end
47
+
48
+ module Connection
49
+ private
50
+
51
+ def handle_open
52
+ ErrorHandler.capture(self, transaction_name: "#{self.class.name}#connect") do
53
+ super
54
+ end
55
+ end
56
+
57
+ def handle_close
58
+ ErrorHandler.capture(self, transaction_name: "#{self.class.name}#disconnect") do
59
+ super
60
+ end
61
+ end
62
+ end
63
+
64
+ module Channel
65
+ module Subscriptions
66
+ def self.included(base)
67
+ base.class_eval do
68
+ set_callback :subscribe, :around, ->(_, block) { sentry_capture(:subscribed, &block) }, prepend: true
69
+ set_callback :unsubscribe, :around, ->(_, block) { sentry_capture(:unsubscribed, &block) }, prepend: true
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def sentry_capture(hook, &block)
76
+ extra_context = { params: params }
77
+
78
+ ErrorHandler.capture(connection, transaction_name: "#{self.class.name}##{hook}", extra_context: extra_context, &block)
79
+ end
80
+ end
81
+
82
+ module Actions
83
+ private
84
+
85
+ def dispatch_action(action, data)
86
+ extra_context = { params: params, data: data }
87
+
88
+ ErrorHandler.capture(connection, transaction_name: "#{self.class.name}##{action}", extra_context: extra_context) do
89
+ super
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,74 +1,69 @@
1
1
  module Sentry
2
2
  module Rails
3
3
  module ActiveJobExtensions
4
- def self.included(base)
5
- base.class_eval do
6
- around_perform do |job, block|
7
- if Sentry.initialized?
8
- if already_supported_by_specific_integration?(job)
9
- block.call
10
- else
11
- Sentry.with_scope do |scope|
12
- capture_and_reraise_with_sentry(job, scope, block)
13
- end
14
- end
15
- else
16
- block.call
4
+ def perform_now
5
+ if !Sentry.initialized? || already_supported_by_sentry_integration?
6
+ super
7
+ else
8
+ Sentry.with_scope do |scope|
9
+ capture_and_reraise_with_sentry(scope) do
10
+ super
17
11
  end
18
12
  end
19
13
  end
20
14
  end
21
15
 
22
- def capture_and_reraise_with_sentry(job, scope, block)
23
- scope.set_transaction_name(job.class.name)
24
- transaction = Sentry.start_transaction(name: scope.transaction_name, op: "active_job")
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
25
24
 
26
25
  scope.set_span(transaction) if transaction
27
26
 
28
- block.call
27
+ return_value = block.call
28
+
29
+ finish_sentry_transaction(transaction, 200)
29
30
 
30
- finish_transaction(transaction, 200)
31
+ return_value
31
32
  rescue Exception => e # rubocop:disable Lint/RescueException
32
- rescue_handler_result = rescue_with_handler(e)
33
- finish_transaction(transaction, 500)
34
- return rescue_handler_result if rescue_handler_result
33
+ finish_sentry_transaction(transaction, 500)
35
34
 
36
35
  Sentry::Rails.capture_exception(
37
36
  e,
38
- extra: sentry_context(job),
37
+ extra: sentry_context,
39
38
  tags: {
40
- job_id: job.job_id,
41
- provider_job_id: job.provider_job_id
39
+ job_id: job_id,
40
+ provider_job_id:provider_job_id
42
41
  }
43
42
  )
44
43
  raise e
45
44
  end
46
45
 
47
- def finish_transaction(transaction, status)
46
+ def finish_sentry_transaction(transaction, status)
48
47
  return unless transaction
49
48
 
50
49
  transaction.set_http_status(status)
51
50
  transaction.finish
52
51
  end
53
52
 
54
- def already_supported_by_specific_integration?(job)
55
- Sentry.configuration.rails.skippable_job_adapters.include?(job.class.queue_adapter.class.to_s)
53
+ def already_supported_by_sentry_integration?
54
+ Sentry.configuration.rails.skippable_job_adapters.include?(self.class.queue_adapter.class.to_s)
56
55
  end
57
56
 
58
- def sentry_context(job)
57
+ def sentry_context
59
58
  {
60
- active_job: job.class.name,
61
- arguments: job.arguments,
62
- scheduled_at: job.scheduled_at,
63
- job_id: job.job_id,
64
- provider_job_id: job.provider_job_id,
65
- locale: job.locale
59
+ active_job: self.class.name,
60
+ arguments: arguments,
61
+ scheduled_at: scheduled_at,
62
+ job_id: job_id,
63
+ provider_job_id: provider_job_id,
64
+ locale: locale
66
65
  }
67
66
  end
68
67
  end
69
68
  end
70
69
  end
71
-
72
- class ActiveJob::Base
73
- include Sentry::Rails::ActiveJobExtensions
74
- end
@@ -1,11 +1,9 @@
1
1
  module Sentry
2
2
  class BackgroundWorker
3
- def perform(&block)
4
- @executor.post do
5
- # make sure the background worker returns AR connection if it accidentally acquire one during serialization
6
- ActiveRecord::Base.connection_pool.with_connection do
7
- block.call
8
- end
3
+ def _perform(&block)
4
+ # 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
9
7
  end
10
8
  end
11
9
  end
@@ -1,9 +1,11 @@
1
+ require "sentry/rails/instrument_payload_cleanup_helper"
2
+
1
3
  module Sentry
2
4
  module Rails
3
5
  module Breadcrumb
4
6
  module ActiveSupportLogger
5
7
  class << self
6
- IGNORED_DATA_TYPES = [:request, :headers, :exception, :exception_object]
8
+ include InstrumentPayloadCleanupHelper
7
9
 
8
10
  def add(name, started, _finished, _unique_id, data)
9
11
  # skip Rails' internal events
@@ -23,12 +25,6 @@ module Sentry
23
25
  Sentry.add_breadcrumb(crumb)
24
26
  end
25
27
 
26
- def cleanup_data(data)
27
- IGNORED_DATA_TYPES.each do |key|
28
- data.delete(key) if data.key?(key)
29
- end
30
- end
31
-
32
28
  def inject
33
29
  @subscriber = ::ActiveSupport::Notifications.subscribe(/.*/) do |name, started, finished, unique_id, data|
34
30
  # we only record events that has a started timestamp
@@ -0,0 +1,44 @@
1
+ require "sentry/rails/instrument_payload_cleanup_helper"
2
+
3
+ module Sentry
4
+ module Rails
5
+ module Breadcrumb
6
+ module MonotonicActiveSupportLogger
7
+ class << self
8
+ include InstrumentPayloadCleanupHelper
9
+
10
+ def add(name, started, _finished, _unique_id, data)
11
+ # skip Rails' internal events
12
+ return if name.start_with?("!")
13
+
14
+ if data.is_a?(Hash)
15
+ # we should only mutate the copy of the data
16
+ data = data.dup
17
+ cleanup_data(data)
18
+ end
19
+
20
+ crumb = Sentry::Breadcrumb.new(
21
+ data: data,
22
+ category: name,
23
+ timestamp: started.to_i
24
+ )
25
+ Sentry.add_breadcrumb(crumb)
26
+ end
27
+
28
+ def inject
29
+ @subscriber = ::ActiveSupport::Notifications.monotonic_subscribe(/.*/) do |name, started, finished, unique_id, data|
30
+ # we only record events that has a float as started timestamp
31
+ if started.is_a?(Float)
32
+ add(name, started, finished, unique_id, data)
33
+ end
34
+ end
35
+ end
36
+
37
+ def detach
38
+ ::ActiveSupport::Notifications.unsubscribe(@subscriber)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,6 +1,7 @@
1
1
  require "sentry/rails/tracing/action_controller_subscriber"
2
2
  require "sentry/rails/tracing/action_view_subscriber"
3
3
  require "sentry/rails/tracing/active_record_subscriber"
4
+ require "sentry/rails/tracing/active_storage_subscriber"
4
5
 
5
6
  module Sentry
6
7
  class Configuration
@@ -59,7 +60,8 @@ module Sentry
59
60
  @tracing_subscribers = Set.new([
60
61
  Sentry::Rails::Tracing::ActionControllerSubscriber,
61
62
  Sentry::Rails::Tracing::ActionViewSubscriber,
62
- Sentry::Rails::Tracing::ActiveRecordSubscriber
63
+ Sentry::Rails::Tracing::ActiveRecordSubscriber,
64
+ Sentry::Rails::Tracing::ActiveStorageSubscriber
63
65
  ])
64
66
  end
65
67
  end
@@ -0,0 +1,13 @@
1
+ module Sentry
2
+ module Rails
3
+ module InstrumentPayloadCleanupHelper
4
+ IGNORED_DATA_TYPES = [:request, :response, :headers, :exception, :exception_object, Tracing::START_TIMESTAMP_NAME]
5
+
6
+ def cleanup_data(data)
7
+ IGNORED_DATA_TYPES.each do |key|
8
+ data.delete(key) if data.key?(key)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -7,9 +7,32 @@ module Sentry
7
7
  # middlewares can't be injected after initialize
8
8
  initializer "sentry.use_rack_middleware" do |app|
9
9
  # placed after all the file-sending middlewares so we can avoid unnecessary transactions
10
- app.config.middleware.insert_after ActionDispatch::Executor, Sentry::Rails::CaptureExceptions
11
- # need to be placed at last to smuggle app exceptions via env
12
- app.config.middleware.use(Sentry::Rails::RescuedExceptionInterceptor)
10
+ app.config.middleware.insert_after ActionDispatch::ShowExceptions, Sentry::Rails::CaptureExceptions
11
+ # need to place as close to DebugExceptions as possible to intercept most of the exceptions, including those raised by middlewares
12
+ app.config.middleware.insert_after ActionDispatch::DebugExceptions, Sentry::Rails::RescuedExceptionInterceptor
13
+ end
14
+
15
+ # because the extension works by registering the around_perform callcack, it should always be ran
16
+ # before the application is eager-loaded (before user's jobs register their own callbacks)
17
+ # See https://github.com/getsentry/sentry-ruby/issues/1249#issuecomment-853871871 for the detail explanation
18
+ initializer "sentry.extend_active_job", before: :eager_load! do |app|
19
+ ActiveSupport.on_load(:active_job) do
20
+ require "sentry/rails/active_job"
21
+ prepend Sentry::Rails::ActiveJobExtensions
22
+ end
23
+ end
24
+
25
+ initializer "sentry.extend_action_cable", before: :eager_load! do |app|
26
+ ActiveSupport.on_load(:action_cable_connection) do
27
+ require "sentry/rails/action_cable"
28
+ prepend Sentry::Rails::ActionCableExtensions::Connection
29
+ end
30
+
31
+ ActiveSupport.on_load(:action_cable_channel) do
32
+ require "sentry/rails/action_cable"
33
+ include Sentry::Rails::ActionCableExtensions::Channel::Subscriptions
34
+ prepend Sentry::Rails::ActionCableExtensions::Channel::Actions
35
+ end
13
36
  end
14
37
 
15
38
  config.after_initialize do |app|
@@ -18,7 +41,6 @@ module Sentry
18
41
  configure_project_root
19
42
  configure_trusted_proxies
20
43
  extend_controller_methods if defined?(ActionController)
21
- extend_active_job if defined?(ActiveJob)
22
44
  patch_background_worker if defined?(ActiveRecord)
23
45
  override_streaming_reporter if defined?(ActionView)
24
46
  setup_backtrace_cleanup_callback
@@ -26,6 +48,11 @@ module Sentry
26
48
  activate_tracing
27
49
  end
28
50
 
51
+ runner do
52
+ next unless Sentry.initialized?
53
+ Sentry.configuration.background_worker_threads = 0
54
+ end
55
+
29
56
  def configure_project_root
30
57
  Sentry.configuration.project_root = ::Rails.root.to_s
31
58
  end
@@ -34,11 +61,6 @@ module Sentry
34
61
  Sentry.configuration.trusted_proxies += Array(::Rails.application.config.action_dispatch.trusted_proxies)
35
62
  end
36
63
 
37
- def extend_active_job
38
- require "sentry/rails/active_job"
39
- ActiveJob::Base.send(:prepend, Sentry::Rails::ActiveJobExtensions)
40
- end
41
-
42
64
  def extend_controller_methods
43
65
  require "sentry/rails/controller_methods"
44
66
  require "sentry/rails/controller_transaction"
@@ -60,12 +82,19 @@ module Sentry
60
82
  require 'sentry/rails/breadcrumb/active_support_logger'
61
83
  Sentry::Rails::Breadcrumb::ActiveSupportLogger.inject
62
84
  end
85
+
86
+ if Sentry.configuration.breadcrumbs_logger.include?(:monotonic_active_support_logger)
87
+ return warn "Usage of `monotonic_active_support_logger` require a version of Rails >= 6.1, please upgrade your Rails version or use another logger" if ::Rails.version.to_f < 6.1
88
+
89
+ require 'sentry/rails/breadcrumb/monotonic_active_support_logger'
90
+ Sentry::Rails::Breadcrumb::MonotonicActiveSupportLogger.inject
91
+ end
63
92
  end
64
93
 
65
94
  def setup_backtrace_cleanup_callback
66
95
  backtrace_cleaner = Sentry::Rails::BacktraceCleaner.new
67
96
 
68
- Sentry.configuration.backtrace_cleanup_callback = lambda do |backtrace|
97
+ Sentry.configuration.backtrace_cleanup_callback ||= lambda do |backtrace|
69
98
  backtrace_cleaner.clean(backtrace)
70
99
  end
71
100
  end
@@ -11,22 +11,6 @@ module Sentry
11
11
  begin
12
12
  @app.call(env)
13
13
  rescue => e
14
- request = ActionDispatch::Request.new(env)
15
-
16
- # Rails' ShowExceptions#render_exception will mutate env for the exceptions app
17
- # so we need to hold a copy of env to report the accurate data (like request's url)
18
- if request.show_exceptions?
19
- scope = Sentry.get_current_scope
20
- copied_env = scope.rack_env.dup
21
- copied_env["sentry.original_transaction"] = scope.transaction_name
22
- scope.set_rack_env(copied_env)
23
-
24
- if report_rescued_exceptions?
25
- Sentry::Rails.capture_exception(e)
26
- env["sentry.already_captured"] = true
27
- end
28
- end
29
-
30
14
  env["sentry.rescued_exception"] = e if report_rescued_exceptions?
31
15
  raise e
32
16
  end
@@ -9,22 +9,30 @@ module Sentry
9
9
  end
10
10
 
11
11
  def unsubscribe!
12
- ActiveSupport::Notifications.unsubscribe(self::EVENT_NAME)
12
+ self::EVENT_NAMES.each do |name|
13
+ ActiveSupport::Notifications.unsubscribe(name)
14
+ end
13
15
  end
14
16
 
15
- def subscribe_to_event(event_name)
16
- if ::Rails.version.to_i == 5
17
- ActiveSupport::Notifications.subscribe(event_name) do |*args|
18
- next unless Tracing.get_current_transaction
17
+ if ::Rails.version.to_i == 5
18
+ def subscribe_to_event(event_names)
19
+ event_names.each do |event_name|
20
+ ActiveSupport::Notifications.subscribe(event_name) do |*args|
21
+ next unless Tracing.get_current_transaction
19
22
 
20
- event = ActiveSupport::Notifications::Event.new(*args)
21
- yield(event_name, event.duration, event.payload)
23
+ event = ActiveSupport::Notifications::Event.new(*args)
24
+ yield(event_name, event.duration, event.payload)
25
+ end
22
26
  end
23
- else
24
- ActiveSupport::Notifications.subscribe(event_name) do |event|
25
- next unless Tracing.get_current_transaction
26
-
27
- yield(event_name, event.duration, event.payload)
27
+ end
28
+ else
29
+ def subscribe_to_event(event_names)
30
+ event_names.each do |event_name|
31
+ ActiveSupport::Notifications.subscribe(event_name) do |event|
32
+ next unless Tracing.get_current_transaction
33
+
34
+ yield(event_name, event.duration, event.payload)
35
+ end
28
36
  end
29
37
  end
30
38
  end
@@ -1,25 +1,27 @@
1
1
  require "sentry/rails/tracing/abstract_subscriber"
2
+ require "sentry/rails/instrument_payload_cleanup_helper"
2
3
 
3
4
  module Sentry
4
5
  module Rails
5
6
  module Tracing
6
7
  class ActionControllerSubscriber < AbstractSubscriber
7
- EVENT_NAME = "process_action.action_controller".freeze
8
+ extend InstrumentPayloadCleanupHelper
9
+
10
+ EVENT_NAMES = ["process_action.action_controller"].freeze
8
11
 
9
12
  def self.subscribe!
10
- subscribe_to_event(EVENT_NAME) do |event_name, duration, payload|
13
+ subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
11
14
  controller = payload[:controller]
12
15
  action = payload[:action]
13
16
 
14
17
  record_on_current_span(
15
18
  op: event_name,
16
- start_timestamp: payload[:start_timestamp],
19
+ start_timestamp: payload[START_TIMESTAMP_NAME],
17
20
  description: "#{controller}##{action}",
18
21
  duration: duration
19
22
  ) do |span|
20
23
  payload = payload.dup
21
- payload.delete(:headers)
22
- payload.delete(:request)
24
+ cleanup_data(payload)
23
25
  span.set_data(:payload, payload)
24
26
  span.set_http_status(payload[:status])
25
27
  end
@@ -4,11 +4,11 @@ module Sentry
4
4
  module Rails
5
5
  module Tracing
6
6
  class ActionViewSubscriber < AbstractSubscriber
7
- EVENT_NAME = "render_template.action_view".freeze
7
+ EVENT_NAMES = ["render_template.action_view"].freeze
8
8
 
9
9
  def self.subscribe!
10
- subscribe_to_event(EVENT_NAME) do |event_name, duration, payload|
11
- record_on_current_span(op: event_name, start_timestamp: payload[:start_timestamp], description: payload[:identifier], duration: duration)
10
+ subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
11
+ record_on_current_span(op: event_name, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:identifier], duration: duration)
12
12
  end
13
13
  end
14
14
  end
@@ -4,14 +4,14 @@ module Sentry
4
4
  module Rails
5
5
  module Tracing
6
6
  class ActiveRecordSubscriber < AbstractSubscriber
7
- EVENT_NAME = "sql.active_record".freeze
7
+ EVENT_NAMES = ["sql.active_record"].freeze
8
8
  EXCLUDED_EVENTS = ["SCHEMA", "TRANSACTION"].freeze
9
9
 
10
10
  def self.subscribe!
11
- subscribe_to_event(EVENT_NAME) do |event_name, duration, payload|
11
+ subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
12
12
  next if EXCLUDED_EVENTS.include? payload[:name]
13
13
 
14
- record_on_current_span(op: event_name, start_timestamp: payload[:start_timestamp], description: payload[:sql], duration: duration) do |span|
14
+ record_on_current_span(op: event_name, start_timestamp: payload[START_TIMESTAMP_NAME], description: payload[:sql], duration: duration) do |span|
15
15
  span.set_data(:connection_id, payload[:connection_id])
16
16
  end
17
17
  end
@@ -0,0 +1,34 @@
1
+ require "sentry/rails/tracing/abstract_subscriber"
2
+
3
+ module Sentry
4
+ module Rails
5
+ module Tracing
6
+ class ActiveStorageSubscriber < AbstractSubscriber
7
+ EVENT_NAMES = %w(
8
+ service_upload.active_storage
9
+ service_download.active_storage
10
+ service_streaming_download.active_storage
11
+ service_download_chunk.active_storage
12
+ service_delete.active_storage
13
+ service_delete_prefixed.active_storage
14
+ service_exist.active_storage
15
+ service_url.active_storage
16
+ service_mirror.active_storage
17
+ service_update_metadata.active_storage
18
+ preview.active_storage
19
+ analyze.active_storage
20
+ ).freeze
21
+
22
+ def self.subscribe!
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|
25
+ payload.each do |key, value|
26
+ span.set_data(key, value) unless key == START_TIMESTAMP_NAME
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,8 @@
1
1
  module Sentry
2
2
  module Rails
3
3
  module Tracing
4
+ START_TIMESTAMP_NAME = :sentry_start_timestamp
5
+
4
6
  def self.register_subscribers(subscribers)
5
7
  @subscribers = subscribers
6
8
  end
@@ -9,11 +11,19 @@ module Sentry
9
11
  @subscribers
10
12
  end
11
13
 
14
+ def self.subscribed_tracing_events
15
+ @subscribed_tracing_events ||= []
16
+ end
17
+
12
18
  def self.subscribe_tracing_events
13
19
  # need to avoid duplicated subscription
14
20
  return if @subscribed
15
21
 
16
- subscribers.each(&:subscribe!)
22
+ subscribers.each do |subscriber|
23
+ subscriber.subscribe!
24
+ @subscribed_tracing_events ||= []
25
+ @subscribed_tracing_events += subscriber::EVENT_NAMES
26
+ end
17
27
 
18
28
  @subscribed = true
19
29
  end
@@ -22,6 +32,7 @@ module Sentry
22
32
  return unless @subscribed
23
33
 
24
34
  subscribers.each(&:unsubscribe!)
35
+ subscribed_tracing_events.clear
25
36
 
26
37
  @subscribed = false
27
38
  end
@@ -35,9 +46,10 @@ module Sentry
35
46
 
36
47
  SentryNotificationExtension.module_eval do
37
48
  def instrument(name, payload = {}, &block)
38
- is_public_event = name[0] != "!"
39
-
40
- payload[:start_timestamp] = Time.now.utc.to_f if is_public_event
49
+ # only inject timestamp to the events the SDK subscribes to
50
+ if Tracing.subscribed_tracing_events.include?(name)
51
+ payload[START_TIMESTAMP_NAME] = Time.now.utc.to_f if name[0] != "!" && payload.is_a?(Hash)
52
+ end
41
53
 
42
54
  super(name, payload, &block)
43
55
  end
@@ -1,5 +1,5 @@
1
1
  module Sentry
2
2
  module Rails
3
- VERSION = "4.4.0"
3
+ VERSION = "5.0.2"
4
4
  end
5
5
  end
data/lib/sentry/rails.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require "rails"
2
2
  require "sentry-ruby"
3
3
  require "sentry/integrable"
4
+ require "sentry/rails/tracing"
4
5
  require "sentry/rails/configuration"
5
6
  require "sentry/rails/engine"
6
7
  require "sentry/rails/railtie"
7
- require "sentry/rails/tracing"
8
8
 
9
9
  module Sentry
10
10
  module Rails
data/sentry-rails.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Sentry Team"]
7
7
  spec.description = spec.summary = "A gem that provides Rails integration for the Sentry error logger"
8
8
  spec.email = "accounts@sentry.io"
9
- spec.license = 'Apache-2.0'
9
+ spec.license = 'MIT'
10
10
  spec.homepage = "https://github.com/getsentry/sentry-ruby"
11
11
 
12
12
  spec.platform = Gem::Platform::RUBY
@@ -16,12 +16,12 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
19
- spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/sentry-rails/CHANGELOG.md"
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
20
20
 
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "railties", ">= 5.0"
26
- spec.add_dependency "sentry-ruby-core", "~> 4.4.0.pre.beta"
26
+ spec.add_dependency "sentry-ruby-core", "~> 5.0.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: 4.4.0
4
+ version: 5.0.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: 2021-05-03 00:00:00.000000000 Z
11
+ date: 2022-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 4.4.0.pre.beta
33
+ version: 5.0.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: 4.4.0.pre.beta
40
+ version: 5.0.2
41
41
  description: A gem that provides Rails integration for the Sentry error logger
42
42
  email: accounts@sentry.io
43
43
  executables: []
@@ -46,7 +46,6 @@ extra_rdoc_files:
46
46
  - README.md
47
47
  - LICENSE.txt
48
48
  files:
49
- - ".craft.yml"
50
49
  - ".gitignore"
51
50
  - ".rspec"
52
51
  - CHANGELOG.md
@@ -61,15 +60,18 @@ files:
61
60
  - bin/setup
62
61
  - lib/sentry-rails.rb
63
62
  - lib/sentry/rails.rb
63
+ - lib/sentry/rails/action_cable.rb
64
64
  - lib/sentry/rails/active_job.rb
65
65
  - lib/sentry/rails/background_worker.rb
66
66
  - lib/sentry/rails/backtrace_cleaner.rb
67
67
  - lib/sentry/rails/breadcrumb/active_support_logger.rb
68
+ - lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb
68
69
  - lib/sentry/rails/capture_exceptions.rb
69
70
  - lib/sentry/rails/configuration.rb
70
71
  - lib/sentry/rails/controller_methods.rb
71
72
  - lib/sentry/rails/controller_transaction.rb
72
73
  - lib/sentry/rails/engine.rb
74
+ - lib/sentry/rails/instrument_payload_cleanup_helper.rb
73
75
  - lib/sentry/rails/overrides/streaming_reporter.rb
74
76
  - lib/sentry/rails/railtie.rb
75
77
  - lib/sentry/rails/rescued_exception_interceptor.rb
@@ -78,15 +80,16 @@ files:
78
80
  - lib/sentry/rails/tracing/action_controller_subscriber.rb
79
81
  - lib/sentry/rails/tracing/action_view_subscriber.rb
80
82
  - lib/sentry/rails/tracing/active_record_subscriber.rb
83
+ - lib/sentry/rails/tracing/active_storage_subscriber.rb
81
84
  - lib/sentry/rails/version.rb
82
85
  - sentry-rails.gemspec
83
86
  homepage: https://github.com/getsentry/sentry-ruby
84
87
  licenses:
85
- - Apache-2.0
88
+ - MIT
86
89
  metadata:
87
90
  homepage_uri: https://github.com/getsentry/sentry-ruby
88
91
  source_code_uri: https://github.com/getsentry/sentry-ruby
89
- changelog_uri: https://github.com/getsentry/sentry-ruby/blob/master/sentry-rails/CHANGELOG.md
92
+ changelog_uri: https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md
90
93
  post_install_message:
91
94
  rdoc_options: []
92
95
  require_paths:
@@ -102,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
105
  - !ruby/object:Gem::Version
103
106
  version: '0'
104
107
  requirements: []
105
- rubygems_version: 3.0.3.1
108
+ rubygems_version: 3.1.6
106
109
  signing_key:
107
110
  specification_version: 4
108
111
  summary: A gem that provides Rails integration for the Sentry error logger
data/.craft.yml DELETED
@@ -1,20 +0,0 @@
1
- minVersion: '0.13.2'
2
- github:
3
- owner: getsentry
4
- repo: sentry-ruby
5
- changelogPolicy: simple
6
- preReleaseCommand: ruby ../.scripts/bump-version.rb
7
- releaseBranchPrefix: release-sentry-rails
8
- statusProvider:
9
- name: github
10
- artifactProvider:
11
- name: github
12
- targets:
13
- - name: gem
14
- - name: registry
15
- type: sdk
16
- config:
17
- canonical: 'gem:sentry-rails'
18
- - name: github
19
- tagPrefix: sentry-rails-v
20
- changelog: sentry-rails/CHANGELOG.md