sentry-rails 5.10.0 → 5.26.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 +4 -4
- data/.gitignore +1 -1
- data/Gemfile +36 -31
- data/README.md +1 -1
- data/Rakefile +13 -10
- data/app/jobs/sentry/send_event_job.rb +2 -1
- data/bin/console +1 -0
- data/lib/generators/sentry_generator.rb +31 -0
- data/lib/sentry/rails/action_cable.rb +12 -6
- data/lib/sentry/rails/active_job.rb +71 -10
- data/lib/sentry/rails/background_worker.rb +2 -0
- data/lib/sentry/rails/backtrace_cleaner.rb +7 -7
- data/lib/sentry/rails/breadcrumb/active_support_logger.rb +6 -64
- data/lib/sentry/rails/breadcrumb/monotonic_active_support_logger.rb +2 -0
- data/lib/sentry/rails/capture_exceptions.rb +11 -6
- data/lib/sentry/rails/configuration.rb +107 -18
- data/lib/sentry/rails/controller_methods.rb +2 -0
- data/lib/sentry/rails/controller_transaction.rb +9 -3
- data/lib/sentry/rails/engine.rb +2 -0
- data/lib/sentry/rails/error_subscriber.rb +9 -1
- data/lib/sentry/rails/instrument_payload_cleanup_helper.rb +2 -0
- data/lib/sentry/rails/overrides/streaming_reporter.rb +2 -0
- data/lib/sentry/rails/railtie.rb +17 -4
- data/lib/sentry/rails/rescued_exception_interceptor.rb +12 -1
- data/lib/sentry/rails/tracing/abstract_subscriber.rb +2 -1
- data/lib/sentry/rails/tracing/action_controller_subscriber.rb +6 -2
- data/lib/sentry/rails/tracing/action_view_subscriber.rb +11 -2
- data/lib/sentry/rails/tracing/active_record_subscriber.rb +89 -7
- data/lib/sentry/rails/tracing/active_storage_subscriber.rb +17 -4
- data/lib/sentry/rails/tracing/active_support_subscriber.rb +63 -0
- data/lib/sentry/rails/tracing.rb +2 -0
- data/lib/sentry/rails/version.rb +3 -1
- data/lib/sentry/rails.rb +2 -0
- data/lib/sentry-rails.rb +2 -0
- data/sentry-rails.gemspec +14 -6
- metadata +14 -13
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/tracing/action_controller_subscriber"
|
2
4
|
require "sentry/rails/tracing/action_view_subscriber"
|
3
5
|
require "sentry/rails/tracing/active_record_subscriber"
|
4
6
|
require "sentry/rails/tracing/active_storage_subscriber"
|
7
|
+
require "sentry/rails/tracing/active_support_subscriber"
|
5
8
|
|
6
9
|
module Sentry
|
7
10
|
class Configuration
|
@@ -12,9 +15,14 @@ module Sentry
|
|
12
15
|
@excluded_exceptions = @excluded_exceptions.concat(Sentry::Rails::IGNORE_DEFAULT)
|
13
16
|
|
14
17
|
if ::Rails.logger
|
15
|
-
|
18
|
+
if defined?(::ActiveSupport::BroadcastLogger) && ::Rails.logger.is_a?(::ActiveSupport::BroadcastLogger)
|
19
|
+
dupped_broadcasts = ::Rails.logger.broadcasts.map(&:dup)
|
20
|
+
self.sdk_logger = ::ActiveSupport::BroadcastLogger.new(*dupped_broadcasts)
|
21
|
+
else
|
22
|
+
self.sdk_logger = ::Rails.logger.dup
|
23
|
+
end
|
16
24
|
else
|
17
|
-
|
25
|
+
sdk_logger.warn(Sentry::LOGGER_PROGNAME) do
|
18
26
|
<<~MSG
|
19
27
|
sentry-rails can't detect Rails.logger. it may be caused by misplacement of the SDK initialization code
|
20
28
|
please make sure you place the Sentry.init block under the `config/initializers` folder, e.g. `config/initializers/sentry.rb`
|
@@ -26,21 +34,82 @@ module Sentry
|
|
26
34
|
|
27
35
|
module Rails
|
28
36
|
IGNORE_DEFAULT = [
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
"AbstractController::ActionNotFound",
|
38
|
+
"ActionController::BadRequest",
|
39
|
+
"ActionController::InvalidAuthenticityToken",
|
40
|
+
"ActionController::InvalidCrossOriginRequest",
|
41
|
+
"ActionController::MethodNotAllowed",
|
42
|
+
"ActionController::NotImplemented",
|
43
|
+
"ActionController::ParameterMissing",
|
44
|
+
"ActionController::RoutingError",
|
45
|
+
"ActionController::UnknownAction",
|
46
|
+
"ActionController::UnknownFormat",
|
47
|
+
"ActionDispatch::Http::MimeNegotiation::InvalidType",
|
48
|
+
"ActionController::UnknownHttpMethod",
|
49
|
+
"ActionDispatch::Http::Parameters::ParseError",
|
50
|
+
"ActiveRecord::RecordNotFound"
|
43
51
|
].freeze
|
52
|
+
|
53
|
+
ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT = {
|
54
|
+
# action_controller
|
55
|
+
"write_fragment.action_controller" => %i[key],
|
56
|
+
"read_fragment.action_controller" => %i[key],
|
57
|
+
"exist_fragment?.action_controller" => %i[key],
|
58
|
+
"expire_fragment.action_controller" => %i[key],
|
59
|
+
"start_processing.action_controller" => %i[controller action params format method path],
|
60
|
+
"process_action.action_controller" => %i[controller action params format method path status view_runtime db_runtime],
|
61
|
+
"send_file.action_controller" => %i[path],
|
62
|
+
"redirect_to.action_controller" => %i[status location],
|
63
|
+
"halted_callback.action_controller" => %i[filter],
|
64
|
+
# action_dispatch
|
65
|
+
"process_middleware.action_dispatch" => %i[middleware],
|
66
|
+
# action_view
|
67
|
+
"render_template.action_view" => %i[identifier layout],
|
68
|
+
"render_partial.action_view" => %i[identifier],
|
69
|
+
"render_collection.action_view" => %i[identifier count cache_hits],
|
70
|
+
"render_layout.action_view" => %i[identifier],
|
71
|
+
# active_record
|
72
|
+
"sql.active_record" => %i[sql name statement_name cached],
|
73
|
+
"instantiation.active_record" => %i[record_count class_name],
|
74
|
+
# action_mailer
|
75
|
+
# not including to, from, or subject..etc. because of PII concern
|
76
|
+
"deliver.action_mailer" => %i[mailer date perform_deliveries],
|
77
|
+
"process.action_mailer" => %i[mailer action params],
|
78
|
+
# active_support
|
79
|
+
"cache_read.active_support" => %i[key store hit],
|
80
|
+
"cache_generate.active_support" => %i[key store],
|
81
|
+
"cache_fetch_hit.active_support" => %i[key store],
|
82
|
+
"cache_write.active_support" => %i[key store],
|
83
|
+
"cache_delete.active_support" => %i[key store],
|
84
|
+
"cache_exist?.active_support" => %i[key store],
|
85
|
+
# active_job
|
86
|
+
"enqueue_at.active_job" => %i[],
|
87
|
+
"enqueue.active_job" => %i[],
|
88
|
+
"enqueue_retry.active_job" => %i[],
|
89
|
+
"perform_start.active_job" => %i[],
|
90
|
+
"perform.active_job" => %i[],
|
91
|
+
"retry_stopped.active_job" => %i[],
|
92
|
+
"discard.active_job" => %i[],
|
93
|
+
# action_cable
|
94
|
+
"perform_action.action_cable" => %i[channel_class action],
|
95
|
+
"transmit.action_cable" => %i[channel_class],
|
96
|
+
"transmit_subscription_confirmation.action_cable" => %i[channel_class],
|
97
|
+
"transmit_subscription_rejection.action_cable" => %i[channel_class],
|
98
|
+
"broadcast.action_cable" => %i[broadcasting],
|
99
|
+
# active_storage
|
100
|
+
"service_upload.active_storage" => %i[service key checksum],
|
101
|
+
"service_streaming_download.active_storage" => %i[service key],
|
102
|
+
"service_download_chunk.active_storage" => %i[service key],
|
103
|
+
"service_download.active_storage" => %i[service key],
|
104
|
+
"service_delete.active_storage" => %i[service key],
|
105
|
+
"service_delete_prefixed.active_storage" => %i[service prefix],
|
106
|
+
"service_exist.active_storage" => %i[service key exist],
|
107
|
+
"service_url.active_storage" => %i[service key url],
|
108
|
+
"service_update_metadata.active_storage" => %i[service key],
|
109
|
+
"preview.active_storage" => %i[key],
|
110
|
+
"analyze.active_storage" => %i[analyzer]
|
111
|
+
}.freeze
|
112
|
+
|
44
113
|
class Configuration
|
45
114
|
# Rails 7.0 introduced a new error reporter feature, which the SDK once opted-in by default.
|
46
115
|
# But after receiving multiple issue reports, the integration seemed to cause serious troubles to some users.
|
@@ -50,8 +119,8 @@ module Sentry
|
|
50
119
|
|
51
120
|
# Rails catches exceptions in the ActionDispatch::ShowExceptions or
|
52
121
|
# ActionDispatch::DebugExceptions middlewares, depending on the environment.
|
53
|
-
# When `
|
54
|
-
#
|
122
|
+
# When `report_rescued_exceptions` is true (it is by default), Sentry will
|
123
|
+
# report exceptions even when they are rescued by these middlewares.
|
55
124
|
attr_accessor :report_rescued_exceptions
|
56
125
|
|
57
126
|
# Some adapters, like sidekiq, already have their own sentry integration.
|
@@ -60,6 +129,14 @@ module Sentry
|
|
60
129
|
|
61
130
|
attr_accessor :tracing_subscribers
|
62
131
|
|
132
|
+
# When the ActiveRecordSubscriber is enabled, capture the source location of the query in the span data.
|
133
|
+
# This is enabled by default, but can be disabled by setting this to false.
|
134
|
+
attr_accessor :enable_db_query_source
|
135
|
+
|
136
|
+
# The threshold in milliseconds for the ActiveRecordSubscriber to capture the source location of the query
|
137
|
+
# in the span data. Default is 100ms.
|
138
|
+
attr_accessor :db_query_source_threshold_ms
|
139
|
+
|
63
140
|
# sentry-rails by default skips asset request' transactions by checking if the path matches
|
64
141
|
#
|
65
142
|
# ```rb
|
@@ -75,6 +152,13 @@ module Sentry
|
|
75
152
|
# ```
|
76
153
|
attr_accessor :assets_regexp
|
77
154
|
|
155
|
+
# Hash of subscription items that will be shown in breadcrumbs active support logger.
|
156
|
+
# @return [Hash<String, Array<Symbol>>]
|
157
|
+
attr_accessor :active_support_logger_subscription_items
|
158
|
+
|
159
|
+
# Set this option to true if you want Sentry to capture each retry failure
|
160
|
+
attr_accessor :active_job_report_on_retry_error
|
161
|
+
|
78
162
|
def initialize
|
79
163
|
@register_error_subscriber = false
|
80
164
|
@report_rescued_exceptions = true
|
@@ -84,9 +168,14 @@ module Sentry
|
|
84
168
|
end
|
85
169
|
@tracing_subscribers = Set.new([
|
86
170
|
Sentry::Rails::Tracing::ActionViewSubscriber,
|
171
|
+
Sentry::Rails::Tracing::ActiveSupportSubscriber,
|
87
172
|
Sentry::Rails::Tracing::ActiveRecordSubscriber,
|
88
173
|
Sentry::Rails::Tracing::ActiveStorageSubscriber
|
89
174
|
])
|
175
|
+
@enable_db_query_source = true
|
176
|
+
@db_query_source_threshold_ms = 100
|
177
|
+
@active_support_logger_subscription_items = Sentry::Rails::ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT.dup
|
178
|
+
@active_job_report_on_retry_error = false
|
90
179
|
end
|
91
180
|
end
|
92
181
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Rails
|
3
5
|
module ControllerTransaction
|
6
|
+
SPAN_ORIGIN = "auto.view.rails"
|
7
|
+
|
4
8
|
def self.included(base)
|
5
9
|
base.prepend_around_action(:sentry_around_action)
|
6
10
|
end
|
@@ -11,7 +15,7 @@ module Sentry
|
|
11
15
|
if Sentry.initialized?
|
12
16
|
transaction_name = "#{self.class}##{action_name}"
|
13
17
|
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|
|
18
|
+
Sentry.with_child_span(op: "view.process_action.action_controller", description: transaction_name, origin: SPAN_ORIGIN) do |child_span|
|
15
19
|
if child_span
|
16
20
|
begin
|
17
21
|
result = yield
|
@@ -19,8 +23,10 @@ module Sentry
|
|
19
23
|
child_span.set_http_status(response.status)
|
20
24
|
child_span.set_data(:format, request.format)
|
21
25
|
child_span.set_data(:method, request.method)
|
22
|
-
|
23
|
-
|
26
|
+
|
27
|
+
pii = Sentry.configuration.send_default_pii
|
28
|
+
child_span.set_data(:path, pii ? request.fullpath : request.filtered_path)
|
29
|
+
child_span.set_data(:params, pii ? request.params : request.filtered_parameters)
|
24
30
|
end
|
25
31
|
|
26
32
|
result
|
data/lib/sentry/rails/engine.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Rails
|
3
5
|
# This is not a user-facing class. You should use it with Rails 7.0's error reporter feature and its interfaces.
|
@@ -19,7 +21,13 @@ module Sentry
|
|
19
21
|
tags.merge!(context.delete(:tags))
|
20
22
|
end
|
21
23
|
|
22
|
-
|
24
|
+
hint = {}
|
25
|
+
if context[:hint].is_a?(Hash)
|
26
|
+
context = context.dup
|
27
|
+
hint.merge!(context.delete(:hint))
|
28
|
+
end
|
29
|
+
|
30
|
+
Sentry::Rails.capture_exception(error, level: severity, contexts: { "rails.error" => context }, tags: tags, hint: hint)
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
data/lib/sentry/rails/railtie.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/capture_exceptions"
|
2
4
|
require "sentry/rails/rescued_exception_interceptor"
|
3
5
|
require "sentry/rails/backtrace_cleaner"
|
@@ -12,7 +14,7 @@ module Sentry
|
|
12
14
|
app.config.middleware.insert_after ActionDispatch::DebugExceptions, Sentry::Rails::RescuedExceptionInterceptor
|
13
15
|
end
|
14
16
|
|
15
|
-
# because the extension works by registering the around_perform
|
17
|
+
# because the extension works by registering the around_perform callback, it should always be run
|
16
18
|
# before the application is eager-loaded (before user's jobs register their own callbacks)
|
17
19
|
# See https://github.com/getsentry/sentry-ruby/issues/1249#issuecomment-853871871 for the detail explanation
|
18
20
|
initializer "sentry.extend_active_job", before: :eager_load! do |app|
|
@@ -40,6 +42,7 @@ module Sentry
|
|
40
42
|
|
41
43
|
configure_project_root
|
42
44
|
configure_trusted_proxies
|
45
|
+
configure_cron_timezone
|
43
46
|
extend_controller_methods if defined?(ActionController)
|
44
47
|
patch_background_worker if defined?(ActiveRecord)
|
45
48
|
override_streaming_reporter if defined?(ActionView)
|
@@ -48,6 +51,11 @@ module Sentry
|
|
48
51
|
activate_tracing
|
49
52
|
|
50
53
|
register_error_subscriber(app) if ::Rails.version.to_f >= 7.0 && Sentry.configuration.rails.register_error_subscriber
|
54
|
+
|
55
|
+
# Presence of ActiveJob is no longer a reliable cue
|
56
|
+
if defined?(Sentry::Rails::ActiveJobExtensions)
|
57
|
+
Sentry::Rails::ActiveJobExtensions::SentryReporter.register_event_handlers
|
58
|
+
end
|
51
59
|
end
|
52
60
|
|
53
61
|
runner do
|
@@ -70,6 +78,11 @@ module Sentry
|
|
70
78
|
Sentry.configuration.trusted_proxies += Array(::Rails.application.config.action_dispatch.trusted_proxies)
|
71
79
|
end
|
72
80
|
|
81
|
+
def configure_cron_timezone
|
82
|
+
tz_info = ::ActiveSupport::TimeZone.find_tzinfo(::Rails.application.config.time_zone)
|
83
|
+
Sentry.configuration.cron.default_timezone = tz_info.name
|
84
|
+
end
|
85
|
+
|
73
86
|
def extend_controller_methods
|
74
87
|
require "sentry/rails/controller_methods"
|
75
88
|
require "sentry/rails/controller_transaction"
|
@@ -88,14 +101,14 @@ module Sentry
|
|
88
101
|
|
89
102
|
def inject_breadcrumbs_logger
|
90
103
|
if Sentry.configuration.breadcrumbs_logger.include?(:active_support_logger)
|
91
|
-
require
|
92
|
-
Sentry::Rails::Breadcrumb::ActiveSupportLogger.inject
|
104
|
+
require "sentry/rails/breadcrumb/active_support_logger"
|
105
|
+
Sentry::Rails::Breadcrumb::ActiveSupportLogger.inject(Sentry.configuration.rails.active_support_logger_subscription_items)
|
93
106
|
end
|
94
107
|
|
95
108
|
if Sentry.configuration.breadcrumbs_logger.include?(:monotonic_active_support_logger)
|
96
109
|
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
|
97
110
|
|
98
|
-
require
|
111
|
+
require "sentry/rails/breadcrumb/monotonic_active_support_logger"
|
99
112
|
Sentry::Rails::Breadcrumb::MonotonicActiveSupportLogger.inject
|
100
113
|
end
|
101
114
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Rails
|
3
5
|
class RescuedExceptionInterceptor
|
@@ -17,7 +19,16 @@ module Sentry
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def report_rescued_exceptions?
|
20
|
-
Sentry.configuration.
|
22
|
+
# In rare edge cases, `Sentry.configuration` might be `nil` here.
|
23
|
+
# Hence, we use a safe navigation and fallback to a reasonable default
|
24
|
+
# of `true` in case the configuration couldn't be loaded.
|
25
|
+
# See https://github.com/getsentry/sentry-ruby/issues/2386
|
26
|
+
report_rescued_exceptions = Sentry.configuration&.rails&.report_rescued_exceptions
|
27
|
+
return report_rescued_exceptions unless report_rescued_exceptions.nil?
|
28
|
+
|
29
|
+
# `true` is the default for `report_rescued_exceptions`, as specified in
|
30
|
+
# `sentry-rails/lib/sentry/rails/configuration.rb`.
|
31
|
+
true
|
21
32
|
end
|
22
33
|
end
|
23
34
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/tracing/abstract_subscriber"
|
2
4
|
require "sentry/rails/instrument_payload_cleanup_helper"
|
3
5
|
|
@@ -8,10 +10,11 @@ module Sentry
|
|
8
10
|
extend InstrumentPayloadCleanupHelper
|
9
11
|
|
10
12
|
EVENT_NAMES = ["process_action.action_controller"].freeze
|
11
|
-
OP_NAME = "view.process_action.action_controller"
|
13
|
+
OP_NAME = "view.process_action.action_controller"
|
14
|
+
SPAN_ORIGIN = "auto.view.rails"
|
12
15
|
|
13
16
|
def self.subscribe!
|
14
|
-
Sentry.
|
17
|
+
Sentry.sdk_logger.warn <<~MSG
|
15
18
|
DEPRECATION WARNING: sentry-rails has changed its approach on controller span recording and #{self.name} is now depreacted.
|
16
19
|
Please stop using or referencing #{self.name} as it will be removed in the next major release.
|
17
20
|
MSG
|
@@ -22,6 +25,7 @@ module Sentry
|
|
22
25
|
|
23
26
|
record_on_current_span(
|
24
27
|
op: OP_NAME,
|
28
|
+
origin: SPAN_ORIGIN,
|
25
29
|
start_timestamp: payload[START_TIMESTAMP_NAME],
|
26
30
|
description: "#{controller}##{action}",
|
27
31
|
duration: duration
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/tracing/abstract_subscriber"
|
2
4
|
|
3
5
|
module Sentry
|
@@ -5,11 +7,18 @@ module Sentry
|
|
5
7
|
module Tracing
|
6
8
|
class ActionViewSubscriber < AbstractSubscriber
|
7
9
|
EVENT_NAMES = ["render_template.action_view"].freeze
|
8
|
-
SPAN_PREFIX = "template."
|
10
|
+
SPAN_PREFIX = "template."
|
11
|
+
SPAN_ORIGIN = "auto.template.rails"
|
9
12
|
|
10
13
|
def self.subscribe!
|
11
14
|
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
12
|
-
record_on_current_span(
|
15
|
+
record_on_current_span(
|
16
|
+
op: SPAN_PREFIX + event_name,
|
17
|
+
origin: SPAN_ORIGIN,
|
18
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
19
|
+
description: payload[:identifier],
|
20
|
+
duration: duration
|
21
|
+
)
|
13
22
|
end
|
14
23
|
end
|
15
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/tracing/abstract_subscriber"
|
2
4
|
|
3
5
|
module Sentry
|
@@ -5,16 +7,96 @@ module Sentry
|
|
5
7
|
module Tracing
|
6
8
|
class ActiveRecordSubscriber < AbstractSubscriber
|
7
9
|
EVENT_NAMES = ["sql.active_record"].freeze
|
8
|
-
SPAN_PREFIX = "db."
|
10
|
+
SPAN_PREFIX = "db."
|
11
|
+
SPAN_ORIGIN = "auto.db.rails"
|
9
12
|
EXCLUDED_EVENTS = ["SCHEMA", "TRANSACTION"].freeze
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
SUPPORT_SOURCE_LOCATION = ActiveSupport::BacktraceCleaner.method_defined?(:clean_frame)
|
15
|
+
|
16
|
+
if SUPPORT_SOURCE_LOCATION
|
17
|
+
class_attribute :backtrace_cleaner, default: (ActiveSupport::BacktraceCleaner.new.tap do |cleaner|
|
18
|
+
cleaner.add_silencer { |line| line.include?("sentry-ruby/lib") || line.include?("sentry-rails/lib") }
|
19
|
+
end)
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def subscribe!
|
24
|
+
record_query_source = SUPPORT_SOURCE_LOCATION && Sentry.configuration.rails.enable_db_query_source
|
25
|
+
query_source_threshold = Sentry.configuration.rails.db_query_source_threshold_ms
|
26
|
+
|
27
|
+
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
28
|
+
next if EXCLUDED_EVENTS.include? payload[:name]
|
29
|
+
|
30
|
+
record_on_current_span(
|
31
|
+
op: SPAN_PREFIX + event_name,
|
32
|
+
origin: SPAN_ORIGIN,
|
33
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
34
|
+
description: payload[:sql],
|
35
|
+
duration: duration
|
36
|
+
) do |span|
|
37
|
+
span.set_tag(:cached, true) if payload.fetch(:cached, false) # cached key is only set for hits in the QueryCache, from Rails 5.1
|
38
|
+
|
39
|
+
connection = payload[:connection]
|
40
|
+
|
41
|
+
if payload[:connection_id]
|
42
|
+
span.set_data(:connection_id, payload[:connection_id])
|
43
|
+
|
44
|
+
# we fallback to the base connection on rails < 6.0.0 since the payload doesn't have it
|
45
|
+
connection ||= ActiveRecord::Base.connection_pool.connections.find { |conn| conn.object_id == payload[:connection_id] }
|
46
|
+
end
|
47
|
+
|
48
|
+
next unless connection
|
49
|
+
|
50
|
+
db_config =
|
51
|
+
if connection.pool.respond_to?(:db_config)
|
52
|
+
connection.pool.db_config.configuration_hash
|
53
|
+
elsif connection.pool.respond_to?(:spec)
|
54
|
+
connection.pool.spec.config
|
55
|
+
end
|
14
56
|
|
15
|
-
|
16
|
-
|
17
|
-
|
57
|
+
next unless db_config
|
58
|
+
|
59
|
+
span.set_data(Span::DataConventions::DB_SYSTEM, db_config[:adapter]) if db_config[:adapter]
|
60
|
+
span.set_data(Span::DataConventions::DB_NAME, db_config[:database]) if db_config[:database]
|
61
|
+
span.set_data(Span::DataConventions::SERVER_ADDRESS, db_config[:host]) if db_config[:host]
|
62
|
+
span.set_data(Span::DataConventions::SERVER_PORT, db_config[:port]) if db_config[:port]
|
63
|
+
span.set_data(Span::DataConventions::SERVER_SOCKET_ADDRESS, db_config[:socket]) if db_config[:socket]
|
64
|
+
|
65
|
+
next unless record_query_source
|
66
|
+
|
67
|
+
# both duration and query_source_threshold are in ms
|
68
|
+
next unless duration >= query_source_threshold
|
69
|
+
|
70
|
+
source_location = query_source_location
|
71
|
+
|
72
|
+
if source_location
|
73
|
+
backtrace_line = Sentry::Backtrace::Line.parse(source_location)
|
74
|
+
|
75
|
+
span.set_data(Span::DataConventions::FILEPATH, backtrace_line.file) if backtrace_line.file
|
76
|
+
span.set_data(Span::DataConventions::LINENO, backtrace_line.number) if backtrace_line.number
|
77
|
+
span.set_data(Span::DataConventions::FUNCTION, backtrace_line.method) if backtrace_line.method
|
78
|
+
# Only JRuby has namespace in the backtrace
|
79
|
+
span.set_data(Span::DataConventions::NAMESPACE, backtrace_line.module_name) if backtrace_line.module_name
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Thread.each_caller_location is an API added in Ruby 3.2 that doesn't always collect the entire stack like
|
86
|
+
# Kernel#caller or #caller_locations do. See https://github.com/rails/rails/pull/49095 for more context.
|
87
|
+
if SUPPORT_SOURCE_LOCATION && Thread.respond_to?(:each_caller_location)
|
88
|
+
def query_source_location
|
89
|
+
Thread.each_caller_location do |location|
|
90
|
+
frame = backtrace_cleaner.clean_frame(location)
|
91
|
+
return frame if frame
|
92
|
+
end
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
else
|
96
|
+
# Since Sentry is mostly used in production, we don't want to fallback to the slower implementation
|
97
|
+
# and adds potentially big overhead to the application.
|
98
|
+
def query_source_location
|
99
|
+
nil
|
18
100
|
end
|
19
101
|
end
|
20
102
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/rails/tracing/abstract_subscriber"
|
2
4
|
|
3
5
|
module Sentry
|
4
6
|
module Rails
|
5
7
|
module Tracing
|
6
8
|
class ActiveStorageSubscriber < AbstractSubscriber
|
7
|
-
EVENT_NAMES = %w
|
9
|
+
EVENT_NAMES = %w[
|
8
10
|
service_upload.active_storage
|
9
11
|
service_download.active_storage
|
10
12
|
service_streaming_download.active_storage
|
@@ -17,13 +19,24 @@ module Sentry
|
|
17
19
|
service_update_metadata.active_storage
|
18
20
|
preview.active_storage
|
19
21
|
analyze.active_storage
|
20
|
-
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
SPAN_ORIGIN = "auto.file.rails"
|
21
25
|
|
22
26
|
def self.subscribe!
|
23
27
|
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
24
|
-
record_on_current_span(
|
28
|
+
record_on_current_span(
|
29
|
+
op: "file.#{event_name}",
|
30
|
+
origin: SPAN_ORIGIN,
|
31
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
32
|
+
description: payload[:service],
|
33
|
+
duration: duration
|
34
|
+
) do |span|
|
25
35
|
payload.each do |key, value|
|
26
|
-
|
36
|
+
next if key == START_TIMESTAMP_NAME
|
37
|
+
next if key == :key && !Sentry.configuration.send_default_pii
|
38
|
+
|
39
|
+
span.set_data(key, value)
|
27
40
|
end
|
28
41
|
end
|
29
42
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sentry/rails/tracing/abstract_subscriber"
|
4
|
+
|
5
|
+
module Sentry
|
6
|
+
module Rails
|
7
|
+
module Tracing
|
8
|
+
class ActiveSupportSubscriber < AbstractSubscriber
|
9
|
+
READ_EVENT_NAMES = %w[
|
10
|
+
cache_read.active_support
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
WRITE_EVENT_NAMES = %w[
|
14
|
+
cache_write.active_support
|
15
|
+
cache_increment.active_support
|
16
|
+
cache_decrement.active_support
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
REMOVE_EVENT_NAMES = %w[
|
20
|
+
cache_delete.active_support
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
FLUSH_EVENT_NAMES = %w[
|
24
|
+
cache_prune.active_support
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
EVENT_NAMES = READ_EVENT_NAMES + WRITE_EVENT_NAMES + REMOVE_EVENT_NAMES + FLUSH_EVENT_NAMES
|
28
|
+
|
29
|
+
SPAN_ORIGIN = "auto.cache.rails"
|
30
|
+
|
31
|
+
def self.subscribe!
|
32
|
+
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
33
|
+
record_on_current_span(
|
34
|
+
op: operation_name(event_name),
|
35
|
+
origin: SPAN_ORIGIN,
|
36
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
37
|
+
description: payload[:store],
|
38
|
+
duration: duration
|
39
|
+
) do |span|
|
40
|
+
span.set_data("cache.key", [*payload[:key]].select { |key| Utils::EncodingHelper.valid_utf_8?(key) })
|
41
|
+
span.set_data("cache.hit", payload[:hit] == true) # Handle nil case
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.operation_name(event_name)
|
47
|
+
case
|
48
|
+
when READ_EVENT_NAMES.include?(event_name)
|
49
|
+
"cache.get"
|
50
|
+
when WRITE_EVENT_NAMES.include?(event_name)
|
51
|
+
"cache.put"
|
52
|
+
when REMOVE_EVENT_NAMES.include?(event_name)
|
53
|
+
"cache.remove"
|
54
|
+
when FLUSH_EVENT_NAMES.include?(event_name)
|
55
|
+
"cache.flush"
|
56
|
+
else
|
57
|
+
"other"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/sentry/rails/tracing.rb
CHANGED
data/lib/sentry/rails/version.rb
CHANGED
data/lib/sentry/rails.rb
CHANGED
data/lib/sentry-rails.rb
CHANGED