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 +4 -4
- data/CHANGELOG.md +2 -0
- data/Gemfile +17 -11
- data/LICENSE.txt +1 -1
- data/Rakefile +7 -1
- data/app/jobs/sentry/send_event_job.rb +2 -7
- data/lib/sentry/rails/action_cable.rb +96 -0
- data/lib/sentry/rails/active_job.rb +33 -38
- data/lib/sentry/rails/background_worker.rb +4 -6
- data/lib/sentry/rails/breadcrumb/active_support_logger.rb +3 -7
- data/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb +44 -0
- data/lib/sentry/rails/configuration.rb +3 -1
- data/lib/sentry/rails/instrument_payload_cleanup_helper.rb +13 -0
- data/lib/sentry/rails/railtie.rb +39 -10
- data/lib/sentry/rails/rescued_exception_interceptor.rb +0 -16
- data/lib/sentry/rails/tracing/abstract_subscriber.rb +20 -12
- data/lib/sentry/rails/tracing/action_controller_subscriber.rb +7 -5
- data/lib/sentry/rails/tracing/action_view_subscriber.rb +3 -3
- data/lib/sentry/rails/tracing/active_record_subscriber.rb +3 -3
- data/lib/sentry/rails/tracing/active_storage_subscriber.rb +34 -0
- data/lib/sentry/rails/tracing.rb +16 -4
- data/lib/sentry/rails/version.rb +1 -1
- data/lib/sentry/rails.rb +1 -1
- data/sentry-rails.gemspec +3 -3
- metadata +11 -8
- data/.craft.yml +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbb2adfc21656bba09244e0895c88a20f58e2401fcb5d4b693f48d10319c9121
|
4
|
+
data.tar.gz: 6e2c595d8d719208524bfa270d6aa0e8d2123c60b80923fe05323f93bb29f98f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3af907f32e77d292f5d86b99bfa5d62e580118e4971f940eb07278951147a9e53b4680926d436833d69548b0872eb560cb2c73dc44361b86ab2e951271d9519
|
7
|
+
data.tar.gz: daad9ecf642f47a149ff2065ee3ce79e56ab33b2379b477f60d86c85ca051c8e0c4cc924c1c68786bdb015b7eac4e998c336b8d5ad0883fe0f11050586fc1103
|
data/CHANGELOG.md
CHANGED
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 = "
|
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
|
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
|
-
|
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
|
33
|
+
gem 'simplecov'
|
34
|
+
gem "simplecov-cobertura", "~> 1.4"
|
35
|
+
gem "rexml"
|
25
36
|
|
26
37
|
gem "rake", "~> 12.0"
|
27
38
|
|
28
|
-
|
29
|
-
gem "
|
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
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 :
|
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 #{
|
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
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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(
|
23
|
-
scope.set_transaction_name(
|
24
|
-
transaction =
|
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
|
-
|
31
|
+
return_value
|
31
32
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
32
|
-
|
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
|
37
|
+
extra: sentry_context,
|
39
38
|
tags: {
|
40
|
-
job_id:
|
41
|
-
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
|
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
|
55
|
-
Sentry.configuration.rails.skippable_job_adapters.include?(
|
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
|
57
|
+
def sentry_context
|
59
58
|
{
|
60
|
-
active_job:
|
61
|
-
arguments:
|
62
|
-
scheduled_at:
|
63
|
-
job_id:
|
64
|
-
provider_job_id:
|
65
|
-
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
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
data/lib/sentry/rails/railtie.rb
CHANGED
@@ -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::
|
11
|
-
# need to
|
12
|
-
app.config.middleware.
|
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
|
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
|
-
|
12
|
+
self::EVENT_NAMES.each do |name|
|
13
|
+
ActiveSupport::Notifications.unsubscribe(name)
|
14
|
+
end
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
21
|
-
|
23
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
24
|
+
yield(event_name, event.duration, event.payload)
|
25
|
+
end
|
22
26
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
8
|
+
extend InstrumentPayloadCleanupHelper
|
9
|
+
|
10
|
+
EVENT_NAMES = ["process_action.action_controller"].freeze
|
8
11
|
|
9
12
|
def self.subscribe!
|
10
|
-
subscribe_to_event(
|
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[
|
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
|
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
|
-
|
7
|
+
EVENT_NAMES = ["render_template.action_view"].freeze
|
8
8
|
|
9
9
|
def self.subscribe!
|
10
|
-
subscribe_to_event(
|
11
|
-
record_on_current_span(op: event_name, start_timestamp: payload[
|
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
|
-
|
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(
|
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[
|
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
|
data/lib/sentry/rails/tracing.rb
CHANGED
@@ -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
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
data/lib/sentry/rails/version.rb
CHANGED
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 = '
|
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/
|
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", "~>
|
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
|
+
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:
|
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:
|
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:
|
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
|
-
-
|
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/
|
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.
|
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
|