sentry-ruby 5.10.0 → 5.16.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 +2 -13
- data/README.md +9 -9
- data/lib/sentry/background_worker.rb +8 -1
- data/lib/sentry/backpressure_monitor.rb +75 -0
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +48 -10
- data/lib/sentry/configuration.rb +50 -4
- data/lib/sentry/cron/configuration.rb +23 -0
- data/lib/sentry/cron/monitor_check_ins.rb +75 -0
- data/lib/sentry/cron/monitor_config.rb +53 -0
- data/lib/sentry/cron/monitor_schedule.rb +42 -0
- data/lib/sentry/envelope.rb +1 -1
- data/lib/sentry/event.rb +6 -28
- data/lib/sentry/hub.rb +69 -1
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/single_exception.rb +5 -3
- data/lib/sentry/net/http.rb +25 -22
- data/lib/sentry/profiler.rb +18 -7
- data/lib/sentry/propagation_context.rb +134 -0
- data/lib/sentry/puma.rb +11 -4
- data/lib/sentry/rack/capture_exceptions.rb +1 -4
- data/lib/sentry/rake.rb +0 -13
- data/lib/sentry/redis.rb +8 -3
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/scope.rb +29 -13
- data/lib/sentry/span.rb +39 -2
- data/lib/sentry/test_helper.rb +18 -12
- data/lib/sentry/transaction.rb +18 -19
- data/lib/sentry/transaction_event.rb +0 -3
- data/lib/sentry/transport/configuration.rb +74 -1
- data/lib/sentry/transport/http_transport.rb +68 -37
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +21 -17
- data/lib/sentry/utils/argument_checking_helper.rb +6 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +83 -25
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 565289974a80625ef7ecac6926cfb7292569dfafd84f12584a8214619bdd5ed5
|
|
4
|
+
data.tar.gz: 005b3e5c27b7188058c412d36981779eb759f7be1032429eea17a2e4a7ffcb9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d0e68db7961263d6aa070feaa131fae4c2039884e565cd248795298a99f08d66e7c921df1a6f6175e68ac0ed554185b4b94769f8b0fcba12d76e6aa042fc3359
|
|
7
|
+
data.tar.gz: 5e10f1406d7a7809aed02cef80e1d4355e61af54ed42ffd9a1b3a54a730229abfef4f0a690980c646757b93fffa6219d6500c5700b08a6eef61b6eb682d63620
|
data/Gemfile
CHANGED
|
@@ -12,22 +12,9 @@ gem "redis", "~> #{redis_rb_version}"
|
|
|
12
12
|
|
|
13
13
|
gem "puma"
|
|
14
14
|
|
|
15
|
-
gem "rake", "~> 12.0"
|
|
16
|
-
gem "rspec", "~> 3.0"
|
|
17
|
-
gem "rspec-retry"
|
|
18
15
|
gem "timecop"
|
|
19
|
-
gem "simplecov"
|
|
20
|
-
gem "simplecov-cobertura", "~> 1.4"
|
|
21
|
-
gem "rexml"
|
|
22
16
|
gem "stackprof" unless RUBY_PLATFORM == "java"
|
|
23
17
|
|
|
24
|
-
if RUBY_VERSION.to_f >= 2.6
|
|
25
|
-
gem "debug", github: "ruby/debug", platform: :ruby
|
|
26
|
-
gem "irb"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
gem "pry"
|
|
30
|
-
|
|
31
18
|
gem "benchmark-ips"
|
|
32
19
|
gem "benchmark_driver"
|
|
33
20
|
gem "benchmark-ipsa"
|
|
@@ -35,3 +22,5 @@ gem "benchmark-memory"
|
|
|
35
22
|
|
|
36
23
|
gem "yard", github: "lsegal/yard"
|
|
37
24
|
gem "webrick"
|
|
25
|
+
|
|
26
|
+
eval_gemfile File.expand_path("../Gemfile", __dir__)
|
data/README.md
CHANGED
|
@@ -13,14 +13,14 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
|
|
|
13
13
|
Sentry SDK for Ruby
|
|
14
14
|
===========
|
|
15
15
|
|
|
16
|
-
| current version
|
|
17
|
-
| ---
|
|
18
|
-
| [](https://rubygems.org/gems/sentry-ruby)
|
|
19
|
-
| [](https://rubygems.org/gems/sentry-rails)
|
|
20
|
-
| [](https://rubygems.org/gems/sentry-sidekiq)
|
|
21
|
-
| [](https://rubygems.org/gems/sentry-delayed_job)
|
|
22
|
-
| [](https://rubygems.org/gems/sentry-resque)
|
|
23
|
-
| [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://rubygems.org/gems/sentry-ruby) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_ruby_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-ruby/) |
|
|
19
|
+
| [](https://rubygems.org/gems/sentry-rails) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_rails_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-rails/) |
|
|
20
|
+
| [](https://rubygems.org/gems/sentry-sidekiq) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-sidekiq/) |
|
|
21
|
+
| [](https://rubygems.org/gems/sentry-delayed_job) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-delayed_job/) |
|
|
22
|
+
| [](https://rubygems.org/gems/sentry-resque) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-resque/) |
|
|
23
|
+
| [](https://rubygems.org/gems/sentry-opentelemetry) | [](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [](https://rubygems.org/gems/sentry-opentelemetry/) |
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
@@ -33,7 +33,7 @@ If you're using `sentry-raven`, we recommend you to migrate to this new SDK. You
|
|
|
33
33
|
|
|
34
34
|
## Requirements
|
|
35
35
|
|
|
36
|
-
We test
|
|
36
|
+
We test from Ruby 2.4 to Ruby 3.2 at the latest patchlevel/teeny version. We also support JRuby 9.0.
|
|
37
37
|
|
|
38
38
|
If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
|
|
39
39
|
|
|
@@ -13,10 +13,12 @@ module Sentry
|
|
|
13
13
|
attr_reader :logger
|
|
14
14
|
attr_accessor :shutdown_timeout
|
|
15
15
|
|
|
16
|
+
DEFAULT_MAX_QUEUE = 30
|
|
17
|
+
|
|
16
18
|
def initialize(configuration)
|
|
17
|
-
@max_queue = 30
|
|
18
19
|
@shutdown_timeout = 1
|
|
19
20
|
@number_of_threads = configuration.background_worker_threads
|
|
21
|
+
@max_queue = configuration.background_worker_max_queue
|
|
20
22
|
@logger = configuration.logger
|
|
21
23
|
@debug = configuration.debug
|
|
22
24
|
@shutdown_callback = nil
|
|
@@ -63,6 +65,11 @@ module Sentry
|
|
|
63
65
|
@shutdown_callback&.call
|
|
64
66
|
end
|
|
65
67
|
|
|
68
|
+
def full?
|
|
69
|
+
@executor.is_a?(Concurrent::ThreadPoolExecutor) &&
|
|
70
|
+
@executor.remaining_capacity == 0
|
|
71
|
+
end
|
|
72
|
+
|
|
66
73
|
private
|
|
67
74
|
|
|
68
75
|
def _perform(&block)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
class BackpressureMonitor
|
|
5
|
+
include LoggingHelper
|
|
6
|
+
|
|
7
|
+
DEFAULT_INTERVAL = 10
|
|
8
|
+
MAX_DOWNSAMPLE_FACTOR = 10
|
|
9
|
+
|
|
10
|
+
def initialize(configuration, client, interval: DEFAULT_INTERVAL)
|
|
11
|
+
@interval = interval
|
|
12
|
+
@client = client
|
|
13
|
+
@logger = configuration.logger
|
|
14
|
+
|
|
15
|
+
@thread = nil
|
|
16
|
+
@exited = false
|
|
17
|
+
|
|
18
|
+
@healthy = true
|
|
19
|
+
@downsample_factor = 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def healthy?
|
|
23
|
+
ensure_thread
|
|
24
|
+
@healthy
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def downsample_factor
|
|
28
|
+
ensure_thread
|
|
29
|
+
@downsample_factor
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def run
|
|
33
|
+
check_health
|
|
34
|
+
set_downsample_factor
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def check_health
|
|
38
|
+
@healthy = !(@client.transport.any_rate_limited? || Sentry.background_worker&.full?)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def set_downsample_factor
|
|
42
|
+
if @healthy
|
|
43
|
+
log_debug("[BackpressureMonitor] health check positive, reverting to normal sampling") if @downsample_factor.positive?
|
|
44
|
+
@downsample_factor = 0
|
|
45
|
+
else
|
|
46
|
+
@downsample_factor += 1 if @downsample_factor < MAX_DOWNSAMPLE_FACTOR
|
|
47
|
+
log_debug("[BackpressureMonitor] health check negative, downsampling with a factor of #{@downsample_factor}")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def kill
|
|
52
|
+
log_debug("[BackpressureMonitor] killing monitor")
|
|
53
|
+
|
|
54
|
+
@exited = true
|
|
55
|
+
@thread&.kill
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def ensure_thread
|
|
61
|
+
return if @exited
|
|
62
|
+
return if @thread&.alive?
|
|
63
|
+
|
|
64
|
+
@thread = Thread.new do
|
|
65
|
+
loop do
|
|
66
|
+
sleep(@interval)
|
|
67
|
+
run
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
rescue ThreadError
|
|
71
|
+
log_debug("[BackpressureMonitor] Thread creation failed")
|
|
72
|
+
@exited = true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/sentry/breadcrumb.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Sentry
|
|
|
9
9
|
# @return [Hash, nil]
|
|
10
10
|
attr_accessor :data
|
|
11
11
|
# @return [String, nil]
|
|
12
|
-
|
|
12
|
+
attr_reader :level
|
|
13
13
|
# @return [Time, Integer, nil]
|
|
14
14
|
attr_accessor :timestamp
|
|
15
15
|
# @return [String, nil]
|
|
@@ -26,10 +26,10 @@ module Sentry
|
|
|
26
26
|
def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
|
|
27
27
|
@category = category
|
|
28
28
|
@data = data || {}
|
|
29
|
-
@level = level
|
|
30
29
|
@timestamp = timestamp || Sentry.utc_now.to_i
|
|
31
30
|
@type = type
|
|
32
31
|
self.message = message
|
|
32
|
+
self.level = level
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# @return [Hash]
|
|
@@ -50,6 +50,12 @@ module Sentry
|
|
|
50
50
|
@message = (message || "").byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# @param level [String]
|
|
54
|
+
# @return [void]
|
|
55
|
+
def level=(level) # needed to meet the Sentry spec
|
|
56
|
+
@level = level == "warn" ? "warning" : level
|
|
57
|
+
end
|
|
58
|
+
|
|
53
59
|
private
|
|
54
60
|
|
|
55
61
|
def serialized_data
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
require 'sentry/cron/monitor_config'
|
|
5
|
+
|
|
6
|
+
module Sentry
|
|
7
|
+
class CheckInEvent < Event
|
|
8
|
+
TYPE = 'check_in'
|
|
9
|
+
|
|
10
|
+
# uuid to identify this check-in.
|
|
11
|
+
# @return [String]
|
|
12
|
+
attr_accessor :check_in_id
|
|
13
|
+
|
|
14
|
+
# Identifier of the monitor for this check-in.
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_accessor :monitor_slug
|
|
17
|
+
|
|
18
|
+
# Duration of this check since it has started in seconds.
|
|
19
|
+
# @return [Integer, nil]
|
|
20
|
+
attr_accessor :duration
|
|
21
|
+
|
|
22
|
+
# Monitor configuration to support upserts.
|
|
23
|
+
# @return [Cron::MonitorConfig, nil]
|
|
24
|
+
attr_accessor :monitor_config
|
|
25
|
+
|
|
26
|
+
# Status of this check-in.
|
|
27
|
+
# @return [Symbol]
|
|
28
|
+
attr_accessor :status
|
|
29
|
+
|
|
30
|
+
VALID_STATUSES = %i(ok in_progress error)
|
|
31
|
+
|
|
32
|
+
def initialize(
|
|
33
|
+
slug:,
|
|
34
|
+
status:,
|
|
35
|
+
duration: nil,
|
|
36
|
+
monitor_config: nil,
|
|
37
|
+
check_in_id: nil,
|
|
38
|
+
**options
|
|
39
|
+
)
|
|
40
|
+
super(**options)
|
|
41
|
+
|
|
42
|
+
self.monitor_slug = slug
|
|
43
|
+
self.status = status
|
|
44
|
+
self.duration = duration
|
|
45
|
+
self.monitor_config = monitor_config
|
|
46
|
+
self.check_in_id = check_in_id || SecureRandom.uuid.delete('-')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Hash]
|
|
50
|
+
def to_hash
|
|
51
|
+
data = super
|
|
52
|
+
data[:check_in_id] = check_in_id
|
|
53
|
+
data[:monitor_slug] = monitor_slug
|
|
54
|
+
data[:status] = status
|
|
55
|
+
data[:duration] = duration if duration
|
|
56
|
+
data[:monitor_config] = monitor_config.to_hash if monitor_config
|
|
57
|
+
data
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/sentry/client.rb
CHANGED
|
@@ -10,6 +10,10 @@ module Sentry
|
|
|
10
10
|
# @return [Transport]
|
|
11
11
|
attr_reader :transport
|
|
12
12
|
|
|
13
|
+
# The Transport object that'll send events for the client.
|
|
14
|
+
# @return [SpotlightTransport, nil]
|
|
15
|
+
attr_reader :spotlight_transport
|
|
16
|
+
|
|
13
17
|
# @!macro configuration
|
|
14
18
|
attr_reader :configuration
|
|
15
19
|
|
|
@@ -32,6 +36,8 @@ module Sentry
|
|
|
32
36
|
DummyTransport.new(configuration)
|
|
33
37
|
end
|
|
34
38
|
end
|
|
39
|
+
|
|
40
|
+
@spotlight_transport = SpotlightTransport.new(configuration) if configuration.spotlight
|
|
35
41
|
end
|
|
36
42
|
|
|
37
43
|
# Applies the given scope's data to the event and sends it to Sentry.
|
|
@@ -42,7 +48,7 @@ module Sentry
|
|
|
42
48
|
def capture_event(event, scope, hint = {})
|
|
43
49
|
return unless configuration.sending_allowed?
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
if event.is_a?(ErrorEvent) && !configuration.sample_allowed?
|
|
46
52
|
transport.record_lost_event(:sample_rate, 'event')
|
|
47
53
|
return
|
|
48
54
|
end
|
|
@@ -51,7 +57,7 @@ module Sentry
|
|
|
51
57
|
event = scope.apply_to_event(event, hint)
|
|
52
58
|
|
|
53
59
|
if event.nil?
|
|
54
|
-
|
|
60
|
+
log_debug("Discarded event because one of the event processors returned nil")
|
|
55
61
|
transport.record_lost_event(:event_processor, event_type)
|
|
56
62
|
return
|
|
57
63
|
end
|
|
@@ -104,6 +110,37 @@ module Sentry
|
|
|
104
110
|
event
|
|
105
111
|
end
|
|
106
112
|
|
|
113
|
+
# Initializes a CheckInEvent object with the given options.
|
|
114
|
+
#
|
|
115
|
+
# @param slug [String] identifier of this monitor
|
|
116
|
+
# @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
|
|
117
|
+
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
|
118
|
+
# @param duration [Integer, nil] seconds elapsed since this monitor started
|
|
119
|
+
# @param monitor_config [Cron::MonitorConfig, nil] configuration for this monitor
|
|
120
|
+
# @param check_in_id [String, nil] for updating the status of an existing monitor
|
|
121
|
+
#
|
|
122
|
+
# @return [Event]
|
|
123
|
+
def event_from_check_in(
|
|
124
|
+
slug,
|
|
125
|
+
status,
|
|
126
|
+
hint = {},
|
|
127
|
+
duration: nil,
|
|
128
|
+
monitor_config: nil,
|
|
129
|
+
check_in_id: nil
|
|
130
|
+
)
|
|
131
|
+
return unless configuration.sending_allowed?
|
|
132
|
+
|
|
133
|
+
CheckInEvent.new(
|
|
134
|
+
configuration: configuration,
|
|
135
|
+
integration_meta: Sentry.integrations[hint[:integration]],
|
|
136
|
+
slug: slug,
|
|
137
|
+
status: status,
|
|
138
|
+
duration: duration,
|
|
139
|
+
monitor_config: monitor_config,
|
|
140
|
+
check_in_id: check_in_id
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
|
|
107
144
|
# Initializes an Event object with the given Transaction object.
|
|
108
145
|
# @param transaction [Transaction] the transaction to be recorded.
|
|
109
146
|
# @return [TransactionEvent]
|
|
@@ -119,7 +156,7 @@ module Sentry
|
|
|
119
156
|
event = configuration.before_send.call(event, hint)
|
|
120
157
|
|
|
121
158
|
if event.nil?
|
|
122
|
-
|
|
159
|
+
log_debug("Discarded event because before_send returned nil")
|
|
123
160
|
transport.record_lost_event(:before_send, 'event')
|
|
124
161
|
return
|
|
125
162
|
end
|
|
@@ -129,25 +166,24 @@ module Sentry
|
|
|
129
166
|
event = configuration.before_send_transaction.call(event, hint)
|
|
130
167
|
|
|
131
168
|
if event.nil?
|
|
132
|
-
|
|
169
|
+
log_debug("Discarded event because before_send_transaction returned nil")
|
|
133
170
|
transport.record_lost_event(:before_send, 'transaction')
|
|
134
171
|
return
|
|
135
172
|
end
|
|
136
173
|
end
|
|
137
174
|
|
|
138
175
|
transport.send_event(event)
|
|
176
|
+
spotlight_transport&.send_event(event)
|
|
139
177
|
|
|
140
178
|
event
|
|
141
179
|
rescue => e
|
|
142
|
-
|
|
143
|
-
log_error("#{loggable_event_type} sending failed", e, debug: configuration.debug)
|
|
144
|
-
|
|
145
|
-
event_info = Event.get_log_message(event.to_hash)
|
|
146
|
-
log_info("Unreported #{loggable_event_type}: #{event_info}")
|
|
180
|
+
log_error("Event sending failed", e, debug: configuration.debug)
|
|
147
181
|
transport.record_lost_event(:network_error, event_type)
|
|
148
182
|
raise
|
|
149
183
|
end
|
|
150
184
|
|
|
185
|
+
# @deprecated use Sentry.get_traceparent instead.
|
|
186
|
+
#
|
|
151
187
|
# Generates a Sentry trace for distribted tracing from the given Span.
|
|
152
188
|
# Returns `nil` if `config.propagate_traces` is `false`.
|
|
153
189
|
# @param span [Span] the span to generate trace from.
|
|
@@ -160,7 +196,9 @@ module Sentry
|
|
|
160
196
|
trace
|
|
161
197
|
end
|
|
162
198
|
|
|
163
|
-
#
|
|
199
|
+
# @deprecated Use Sentry.get_baggage instead.
|
|
200
|
+
#
|
|
201
|
+
# Generates a W3C Baggage header for distributed tracing from the given Span.
|
|
164
202
|
# Returns `nil` if `config.propagate_traces` is `false`.
|
|
165
203
|
# @param span [Span] the span to generate trace from.
|
|
166
204
|
# @return [String, nil]
|
data/lib/sentry/configuration.rb
CHANGED
|
@@ -7,6 +7,7 @@ require 'sentry/utils/custom_inspection'
|
|
|
7
7
|
require "sentry/dsn"
|
|
8
8
|
require "sentry/release_detector"
|
|
9
9
|
require "sentry/transport/configuration"
|
|
10
|
+
require "sentry/cron/configuration"
|
|
10
11
|
require "sentry/linecache"
|
|
11
12
|
require "sentry/interfaces/stacktrace_builder"
|
|
12
13
|
|
|
@@ -40,6 +41,13 @@ module Sentry
|
|
|
40
41
|
# @return [Integer]
|
|
41
42
|
attr_accessor :background_worker_threads
|
|
42
43
|
|
|
44
|
+
# The maximum queue size for the background worker.
|
|
45
|
+
# Jobs will be rejected above this limit.
|
|
46
|
+
#
|
|
47
|
+
# Default is {BackgroundWorker::DEFAULT_MAX_QUEUE}.
|
|
48
|
+
# @return [Integer]
|
|
49
|
+
attr_accessor :background_worker_max_queue
|
|
50
|
+
|
|
43
51
|
# a proc/lambda that takes an array of stack traces
|
|
44
52
|
# it'll be used to silence (reduce) backtrace of the exception
|
|
45
53
|
#
|
|
@@ -142,6 +150,14 @@ module Sentry
|
|
|
142
150
|
# @return [Boolean]
|
|
143
151
|
attr_accessor :include_local_variables
|
|
144
152
|
|
|
153
|
+
# Whether to capture events and traces into Spotlight. Default is false.
|
|
154
|
+
# If you set this to true, Sentry will send events and traces to the local
|
|
155
|
+
# Sidecar proxy at http://localhost:8969/stream.
|
|
156
|
+
# If you want to use a different Sidecar proxy address, set this to String
|
|
157
|
+
# with the proxy URL.
|
|
158
|
+
# @return [Boolean, String]
|
|
159
|
+
attr_accessor :spotlight
|
|
160
|
+
|
|
145
161
|
# @deprecated Use {#include_local_variables} instead.
|
|
146
162
|
alias_method :capture_exception_frame_locals, :include_local_variables
|
|
147
163
|
|
|
@@ -211,10 +227,14 @@ module Sentry
|
|
|
211
227
|
# @return [String]
|
|
212
228
|
attr_accessor :server_name
|
|
213
229
|
|
|
214
|
-
#
|
|
215
|
-
# @return [Transport]
|
|
230
|
+
# Transport related configuration.
|
|
231
|
+
# @return [Transport::Configuration]
|
|
216
232
|
attr_reader :transport
|
|
217
233
|
|
|
234
|
+
# Cron related configuration.
|
|
235
|
+
# @return [Cron::Configuration]
|
|
236
|
+
attr_reader :cron
|
|
237
|
+
|
|
218
238
|
# Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
|
|
219
239
|
# @return [Float, nil]
|
|
220
240
|
attr_reader :traces_sample_rate
|
|
@@ -243,6 +263,17 @@ module Sentry
|
|
|
243
263
|
# @return [Boolean]
|
|
244
264
|
attr_accessor :auto_session_tracking
|
|
245
265
|
|
|
266
|
+
# Whether to downsample transactions automatically because of backpressure.
|
|
267
|
+
# Starts a new monitor thread to check health of the SDK every 10 seconds.
|
|
268
|
+
# Default is false
|
|
269
|
+
# @return [Boolean]
|
|
270
|
+
attr_accessor :enable_backpressure_handling
|
|
271
|
+
|
|
272
|
+
# Allowlist of outgoing request targets to which sentry-trace and baggage headers are attached.
|
|
273
|
+
# Default is all (/.*/)
|
|
274
|
+
# @return [Array<String, Regexp>]
|
|
275
|
+
attr_accessor :trace_propagation_targets
|
|
276
|
+
|
|
246
277
|
# The instrumenter to use, :sentry or :otel
|
|
247
278
|
# @return [Symbol]
|
|
248
279
|
attr_reader :instrumenter
|
|
@@ -253,6 +284,11 @@ module Sentry
|
|
|
253
284
|
# @return [Float, nil]
|
|
254
285
|
attr_reader :profiles_sample_rate
|
|
255
286
|
|
|
287
|
+
# Array of patches to apply.
|
|
288
|
+
# Default is {DEFAULT_PATCHES}
|
|
289
|
+
# @return [Array<Symbol>]
|
|
290
|
+
attr_accessor :enabled_patches
|
|
291
|
+
|
|
256
292
|
# these are not config options
|
|
257
293
|
# @!visibility private
|
|
258
294
|
attr_reader :errors, :gem_specs
|
|
@@ -290,6 +326,10 @@ module Sentry
|
|
|
290
326
|
|
|
291
327
|
INSTRUMENTERS = [:sentry, :otel]
|
|
292
328
|
|
|
329
|
+
PROPAGATION_TARGETS_MATCH_ALL = /.*/.freeze
|
|
330
|
+
|
|
331
|
+
DEFAULT_PATCHES = %i(redis puma http).freeze
|
|
332
|
+
|
|
293
333
|
class << self
|
|
294
334
|
# Post initialization callbacks are called at the end of initialization process
|
|
295
335
|
# allowing extending the configuration of sentry-ruby by multiple extensions
|
|
@@ -307,6 +347,7 @@ module Sentry
|
|
|
307
347
|
self.app_dirs_pattern = nil
|
|
308
348
|
self.debug = false
|
|
309
349
|
self.background_worker_threads = Concurrent.processor_count
|
|
350
|
+
self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE
|
|
310
351
|
self.backtrace_cleanup_callback = nil
|
|
311
352
|
self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
|
|
312
353
|
self.breadcrumbs_logger = []
|
|
@@ -328,10 +369,14 @@ module Sentry
|
|
|
328
369
|
self.skip_rake_integration = false
|
|
329
370
|
self.send_client_reports = true
|
|
330
371
|
self.auto_session_tracking = true
|
|
372
|
+
self.enable_backpressure_handling = false
|
|
331
373
|
self.trusted_proxies = []
|
|
332
374
|
self.dsn = ENV['SENTRY_DSN']
|
|
375
|
+
self.spotlight = false
|
|
333
376
|
self.server_name = server_name_from_env
|
|
334
377
|
self.instrumenter = :sentry
|
|
378
|
+
self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
|
|
379
|
+
self.enabled_patches = DEFAULT_PATCHES.dup
|
|
335
380
|
|
|
336
381
|
self.before_send = nil
|
|
337
382
|
self.before_send_transaction = nil
|
|
@@ -340,6 +385,7 @@ module Sentry
|
|
|
340
385
|
self.enable_tracing = nil
|
|
341
386
|
|
|
342
387
|
@transport = Transport::Configuration.new
|
|
388
|
+
@cron = Cron::Configuration.new
|
|
343
389
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
|
344
390
|
|
|
345
391
|
run_post_initialization_callbacks
|
|
@@ -428,14 +474,14 @@ module Sentry
|
|
|
428
474
|
|
|
429
475
|
def profiles_sample_rate=(profiles_sample_rate)
|
|
430
476
|
raise ArgumentError, "profiles_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(profiles_sample_rate)
|
|
431
|
-
|
|
477
|
+
log_warn("Please make sure to include the 'stackprof' gem in your Gemfile to use Profiling with Sentry.") unless defined?(StackProf)
|
|
432
478
|
@profiles_sample_rate = profiles_sample_rate
|
|
433
479
|
end
|
|
434
480
|
|
|
435
481
|
def sending_allowed?
|
|
436
482
|
@errors = []
|
|
437
483
|
|
|
438
|
-
valid? && capture_in_environment?
|
|
484
|
+
spotlight || (valid? && capture_in_environment?)
|
|
439
485
|
end
|
|
440
486
|
|
|
441
487
|
def sample_allowed?
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sentry
|
|
4
|
+
module Cron
|
|
5
|
+
class Configuration
|
|
6
|
+
# Defaults set here will apply to all {Cron::MonitorConfig} objects unless overwritten.
|
|
7
|
+
|
|
8
|
+
# How long (in minutes) after the expected checkin time will we wait
|
|
9
|
+
# until we consider the checkin to have been missed.
|
|
10
|
+
# @return [Integer, nil]
|
|
11
|
+
attr_accessor :default_checkin_margin
|
|
12
|
+
|
|
13
|
+
# How long (in minutes) is the checkin allowed to run for in in_progress
|
|
14
|
+
# before it is considered failed.
|
|
15
|
+
# @return [Integer, nil]
|
|
16
|
+
attr_accessor :default_max_runtime
|
|
17
|
+
|
|
18
|
+
# tz database style timezone string
|
|
19
|
+
# @return [String, nil]
|
|
20
|
+
attr_accessor :default_timezone
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module Sentry
|
|
2
|
+
module Cron
|
|
3
|
+
module MonitorCheckIns
|
|
4
|
+
MAX_SLUG_LENGTH = 50
|
|
5
|
+
|
|
6
|
+
module Patch
|
|
7
|
+
def perform(*args, **opts)
|
|
8
|
+
slug = self.class.sentry_monitor_slug
|
|
9
|
+
monitor_config = self.class.sentry_monitor_config
|
|
10
|
+
|
|
11
|
+
check_in_id = Sentry.capture_check_in(slug,
|
|
12
|
+
:in_progress,
|
|
13
|
+
monitor_config: monitor_config)
|
|
14
|
+
|
|
15
|
+
start = Sentry.utc_now.to_i
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
# need to do this on ruby <= 2.6 sadly
|
|
19
|
+
ret = method(:perform).super_method.arity == 0 ? super() : super
|
|
20
|
+
duration = Sentry.utc_now.to_i - start
|
|
21
|
+
|
|
22
|
+
Sentry.capture_check_in(slug,
|
|
23
|
+
:ok,
|
|
24
|
+
check_in_id: check_in_id,
|
|
25
|
+
duration: duration,
|
|
26
|
+
monitor_config: monitor_config)
|
|
27
|
+
|
|
28
|
+
ret
|
|
29
|
+
rescue Exception
|
|
30
|
+
duration = Sentry.utc_now.to_i - start
|
|
31
|
+
|
|
32
|
+
Sentry.capture_check_in(slug,
|
|
33
|
+
:error,
|
|
34
|
+
check_in_id: check_in_id,
|
|
35
|
+
duration: duration,
|
|
36
|
+
monitor_config: monitor_config)
|
|
37
|
+
|
|
38
|
+
raise
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module ClassMethods
|
|
44
|
+
def sentry_monitor_check_ins(slug: nil, monitor_config: nil)
|
|
45
|
+
if monitor_config && Sentry.configuration
|
|
46
|
+
cron_config = Sentry.configuration.cron
|
|
47
|
+
monitor_config.checkin_margin ||= cron_config.default_checkin_margin
|
|
48
|
+
monitor_config.max_runtime ||= cron_config.default_max_runtime
|
|
49
|
+
monitor_config.timezone ||= cron_config.default_timezone
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
@sentry_monitor_slug = slug
|
|
53
|
+
@sentry_monitor_config = monitor_config
|
|
54
|
+
|
|
55
|
+
prepend Patch
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def sentry_monitor_slug(name: self.name)
|
|
59
|
+
@sentry_monitor_slug ||= begin
|
|
60
|
+
slug = name.gsub('::', '-').downcase
|
|
61
|
+
slug[-MAX_SLUG_LENGTH..-1] || slug
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def sentry_monitor_config
|
|
66
|
+
@sentry_monitor_config
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.included(base)
|
|
71
|
+
base.extend(ClassMethods)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|