sentry-rails 5.17.3 → 5.18.1
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/Gemfile +5 -2
- data/lib/generators/sentry_generator.rb +19 -0
- data/lib/sentry/rails/action_cable.rb +8 -1
- data/lib/sentry/rails/active_job.rb +7 -1
- data/lib/sentry/rails/capture_exceptions.rb +7 -1
- data/lib/sentry/rails/configuration.rb +10 -0
- data/lib/sentry/rails/controller_transaction.rb +3 -1
- data/lib/sentry/rails/tracing/action_controller_subscriber.rb +2 -0
- data/lib/sentry/rails/tracing/action_view_subscriber.rb +8 -1
- data/lib/sentry/rails/tracing/active_record_subscriber.rb +80 -24
- data/lib/sentry/rails/tracing/active_storage_subscriber.rb +9 -1
- data/lib/sentry/rails/version.rb +1 -1
- data/sentry-rails.gemspec +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f37e46eaedbb7739f9def9819546a7f4b1457c7fefd076bb394104fdf18910c1
|
4
|
+
data.tar.gz: f7360c8d456797deef74837c24ee44ae7a5fd875cc602b83382ac345d6498c44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5ec2e4609761381f9414e88c58559086dae1fb177d8f7b9a91e52bce88b3ea82f9f201d4aabd498e39d52f91637a7a1d5778f726d91afa1138f429136a96294
|
7
|
+
data.tar.gz: e58d7d66bb42a9dc0ff8679d7667c9c9bcb1fe268313c1fced2a6bd8713bf04b2dd95d407547b95052a8f57a9e93a393ace8e03108c9d9491bbc727414983944
|
data/Gemfile
CHANGED
@@ -17,8 +17,11 @@ rails_version = Gem::Version.new(rails_version)
|
|
17
17
|
if rails_version < Gem::Version.new("6.0.0")
|
18
18
|
gem "sqlite3", "~> 1.3.0", platform: :ruby
|
19
19
|
else
|
20
|
-
|
21
|
-
|
20
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
21
|
+
gem "sqlite3", "~> 1.7.3", platform: :ruby
|
22
|
+
else
|
23
|
+
gem "sqlite3", "~> 1.6.9", platform: :ruby
|
24
|
+
end
|
22
25
|
end
|
23
26
|
|
24
27
|
if rails_version >= Gem::Version.new("7.2.0.alpha")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
|
3
|
+
class SentryGenerator < ::Rails::Generators::Base
|
4
|
+
class_option :dsn, type: :string, desc: "Sentry DSN"
|
5
|
+
|
6
|
+
def copy_initializer_file
|
7
|
+
dsn = options[:dsn] ? "'#{options[:dsn]}'" : "ENV['SENTRY_DSN']"
|
8
|
+
|
9
|
+
create_file "config/initializers/sentry.rb", <<~RUBY
|
10
|
+
# frozen_string_literal: true
|
11
|
+
|
12
|
+
Sentry.init do |config|
|
13
|
+
config.breadcrumbs_logger = [:active_support_logger]
|
14
|
+
config.dsn = #{dsn}
|
15
|
+
config.enable_tracing = true
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
end
|
@@ -3,6 +3,7 @@ module Sentry
|
|
3
3
|
module ActionCableExtensions
|
4
4
|
class ErrorHandler
|
5
5
|
OP_NAME = "websocket.server".freeze
|
6
|
+
SPAN_ORIGIN = "auto.http.rails.actioncable"
|
6
7
|
|
7
8
|
class << self
|
8
9
|
def capture(connection, transaction_name:, extra_context: nil, &block)
|
@@ -33,7 +34,13 @@ module Sentry
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def start_transaction(env, scope)
|
36
|
-
options = {
|
37
|
+
options = {
|
38
|
+
name: scope.transaction_name,
|
39
|
+
source: scope.transaction_source,
|
40
|
+
op: OP_NAME,
|
41
|
+
origin: SPAN_ORIGIN
|
42
|
+
}
|
43
|
+
|
37
44
|
transaction = Sentry.continue_trace(env, **options)
|
38
45
|
Sentry.start_transaction(transaction: transaction, **options)
|
39
46
|
end
|
@@ -17,6 +17,7 @@ module Sentry
|
|
17
17
|
|
18
18
|
class SentryReporter
|
19
19
|
OP_NAME = "queue.active_job".freeze
|
20
|
+
SPAN_ORIGIN = "auto.queue.active_job".freeze
|
20
21
|
|
21
22
|
class << self
|
22
23
|
def record(job, &block)
|
@@ -27,7 +28,12 @@ module Sentry
|
|
27
28
|
if job.is_a?(::Sentry::SendEventJob)
|
28
29
|
nil
|
29
30
|
else
|
30
|
-
Sentry.start_transaction(
|
31
|
+
Sentry.start_transaction(
|
32
|
+
name: scope.transaction_name,
|
33
|
+
source: scope.transaction_source,
|
34
|
+
op: OP_NAME,
|
35
|
+
origin: SPAN_ORIGIN
|
36
|
+
)
|
31
37
|
end
|
32
38
|
|
33
39
|
scope.set_span(transaction) if transaction
|
@@ -2,6 +2,7 @@ module Sentry
|
|
2
2
|
module Rails
|
3
3
|
class CaptureExceptions < Sentry::Rack::CaptureExceptions
|
4
4
|
RAILS_7_1 = Gem::Version.new(::Rails.version) >= Gem::Version.new("7.1.0.alpha")
|
5
|
+
SPAN_ORIGIN = 'auto.http.rails'.freeze
|
5
6
|
|
6
7
|
def initialize(_)
|
7
8
|
super
|
@@ -32,7 +33,12 @@ module Sentry
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def start_transaction(env, scope)
|
35
|
-
options = {
|
36
|
+
options = {
|
37
|
+
name: scope.transaction_name,
|
38
|
+
source: scope.transaction_source,
|
39
|
+
op: transaction_op,
|
40
|
+
origin: SPAN_ORIGIN
|
41
|
+
}
|
36
42
|
|
37
43
|
if @assets_regexp && scope.transaction_name.match?(@assets_regexp)
|
38
44
|
options.merge!(sampled: false)
|
@@ -126,6 +126,14 @@ module Sentry
|
|
126
126
|
|
127
127
|
attr_accessor :tracing_subscribers
|
128
128
|
|
129
|
+
# When the ActiveRecordSubscriber is enabled, capture the source location of the query in the span data.
|
130
|
+
# This is enabled by default, but can be disabled by setting this to false.
|
131
|
+
attr_accessor :enable_db_query_source
|
132
|
+
|
133
|
+
# The threshold in milliseconds for the ActiveRecordSubscriber to capture the source location of the query
|
134
|
+
# in the span data. Default is 100ms.
|
135
|
+
attr_accessor :db_query_source_threshold_ms
|
136
|
+
|
129
137
|
# sentry-rails by default skips asset request' transactions by checking if the path matches
|
130
138
|
#
|
131
139
|
# ```rb
|
@@ -157,6 +165,8 @@ module Sentry
|
|
157
165
|
Sentry::Rails::Tracing::ActiveRecordSubscriber,
|
158
166
|
Sentry::Rails::Tracing::ActiveStorageSubscriber
|
159
167
|
])
|
168
|
+
@enable_db_query_source = true
|
169
|
+
@db_query_source_threshold_ms = 100
|
160
170
|
@active_support_logger_subscription_items = Sentry::Rails::ACTIVE_SUPPORT_LOGGER_SUBSCRIPTION_ITEMS_DEFAULT.dup
|
161
171
|
end
|
162
172
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Sentry
|
2
2
|
module Rails
|
3
3
|
module ControllerTransaction
|
4
|
+
SPAN_ORIGIN = 'auto.view.rails'.freeze
|
5
|
+
|
4
6
|
def self.included(base)
|
5
7
|
base.prepend_around_action(:sentry_around_action)
|
6
8
|
end
|
@@ -11,7 +13,7 @@ module Sentry
|
|
11
13
|
if Sentry.initialized?
|
12
14
|
transaction_name = "#{self.class}##{action_name}"
|
13
15
|
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|
|
16
|
+
Sentry.with_child_span(op: "view.process_action.action_controller", description: transaction_name, origin: SPAN_ORIGIN) do |child_span|
|
15
17
|
if child_span
|
16
18
|
begin
|
17
19
|
result = yield
|
@@ -9,6 +9,7 @@ module Sentry
|
|
9
9
|
|
10
10
|
EVENT_NAMES = ["process_action.action_controller"].freeze
|
11
11
|
OP_NAME = "view.process_action.action_controller".freeze
|
12
|
+
SPAN_ORIGIN = "auto.view.rails".freeze
|
12
13
|
|
13
14
|
def self.subscribe!
|
14
15
|
Sentry.logger.warn <<~MSG
|
@@ -22,6 +23,7 @@ module Sentry
|
|
22
23
|
|
23
24
|
record_on_current_span(
|
24
25
|
op: OP_NAME,
|
26
|
+
origin: SPAN_ORIGIN,
|
25
27
|
start_timestamp: payload[START_TIMESTAMP_NAME],
|
26
28
|
description: "#{controller}##{action}",
|
27
29
|
duration: duration
|
@@ -6,10 +6,17 @@ module Sentry
|
|
6
6
|
class ActionViewSubscriber < AbstractSubscriber
|
7
7
|
EVENT_NAMES = ["render_template.action_view"].freeze
|
8
8
|
SPAN_PREFIX = "template.".freeze
|
9
|
+
SPAN_ORIGIN = "auto.template.rails".freeze
|
9
10
|
|
10
11
|
def self.subscribe!
|
11
12
|
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
12
|
-
record_on_current_span(
|
13
|
+
record_on_current_span(
|
14
|
+
op: SPAN_PREFIX + event_name,
|
15
|
+
origin: SPAN_ORIGIN,
|
16
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
17
|
+
description: payload[:identifier],
|
18
|
+
duration: duration
|
19
|
+
)
|
13
20
|
end
|
14
21
|
end
|
15
22
|
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,41 +7,95 @@ 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
|
-
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
13
|
-
next if EXCLUDED_EVENTS.include? payload[:name]
|
14
|
+
SUPPORT_SOURCE_LOCATION = ActiveSupport::BacktraceCleaner.method_defined?(:clean_frame)
|
14
15
|
|
15
|
-
|
16
|
-
|
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
|
17
21
|
|
18
|
-
|
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
|
19
26
|
|
20
|
-
|
21
|
-
|
27
|
+
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
28
|
+
next if EXCLUDED_EVENTS.include? payload[:name]
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
38
|
|
27
|
-
|
39
|
+
connection = payload[:connection]
|
28
40
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
connection.
|
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] }
|
34
46
|
end
|
35
47
|
|
36
|
-
|
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
|
56
|
+
|
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
|
37
69
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
70
|
+
source_location = query_source_location
|
71
|
+
|
72
|
+
if source_location
|
73
|
+
backtrace_line = Sentry::Backtrace::Line.parse(source_location)
|
74
|
+
span.set_data(Span::DataConventions::FILEPATH, backtrace_line.file) if backtrace_line.file
|
75
|
+
span.set_data(Span::DataConventions::LINENO, backtrace_line.number) if backtrace_line.number
|
76
|
+
span.set_data(Span::DataConventions::FUNCTION, backtrace_line.method) if backtrace_line.method
|
77
|
+
# Only JRuby has namespace in the backtrace
|
78
|
+
span.set_data(Span::DataConventions::NAMESPACE, backtrace_line.module_name) if backtrace_line.module_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Thread.each_caller_location is an API added in Ruby 3.2 that doesn't always collect the entire stack like
|
85
|
+
# Kernel#caller or #caller_locations do. See https://github.com/rails/rails/pull/49095 for more context.
|
86
|
+
if SUPPORT_SOURCE_LOCATION && Thread.respond_to?(:each_caller_location)
|
87
|
+
def query_source_location
|
88
|
+
Thread.each_caller_location do |location|
|
89
|
+
frame = backtrace_cleaner.clean_frame(location)
|
90
|
+
return frame if frame
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
else
|
95
|
+
# Since Sentry is mostly used in production, we don't want to fallback to the slower implementation
|
96
|
+
# and adds potentially big overhead to the application.
|
97
|
+
def query_source_location
|
98
|
+
nil
|
43
99
|
end
|
44
100
|
end
|
45
101
|
end
|
@@ -19,9 +19,17 @@ module Sentry
|
|
19
19
|
analyze.active_storage
|
20
20
|
].freeze
|
21
21
|
|
22
|
+
SPAN_ORIGIN = "auto.file.rails".freeze
|
23
|
+
|
22
24
|
def self.subscribe!
|
23
25
|
subscribe_to_event(EVENT_NAMES) do |event_name, duration, payload|
|
24
|
-
record_on_current_span(
|
26
|
+
record_on_current_span(
|
27
|
+
op: "file.#{event_name}".freeze,
|
28
|
+
origin: SPAN_ORIGIN,
|
29
|
+
start_timestamp: payload[START_TIMESTAMP_NAME],
|
30
|
+
description: payload[:service],
|
31
|
+
duration: duration
|
32
|
+
) do |span|
|
25
33
|
payload.each do |key, value|
|
26
34
|
span.set_data(key, value) unless key == START_TIMESTAMP_NAME
|
27
35
|
end
|
data/lib/sentry/rails/version.rb
CHANGED
data/sentry-rails.gemspec
CHANGED
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.
|
4
|
+
version: 5.18.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-02 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: 5.
|
33
|
+
version: 5.18.1
|
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.
|
40
|
+
version: 5.18.1
|
41
41
|
description: A gem that provides Rails integration for the Sentry error logger
|
42
42
|
email: accounts@sentry.io
|
43
43
|
executables: []
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- app/jobs/sentry/send_event_job.rb
|
58
58
|
- bin/console
|
59
59
|
- bin/setup
|
60
|
+
- lib/generators/sentry_generator.rb
|
60
61
|
- lib/sentry-rails.rb
|
61
62
|
- lib/sentry/rails.rb
|
62
63
|
- lib/sentry/rails/action_cable.rb
|
@@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
106
|
- !ruby/object:Gem::Version
|
106
107
|
version: '0'
|
107
108
|
requirements: []
|
108
|
-
rubygems_version: 3.
|
109
|
+
rubygems_version: 3.5.11
|
109
110
|
signing_key:
|
110
111
|
specification_version: 4
|
111
112
|
summary: A gem that provides Rails integration for the Sentry error logger
|