sentry-ruby-core 4.7.1 → 4.8.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 +4 -2
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/bin/console +5 -1
- data/lib/sentry/background_worker.rb +30 -2
- data/lib/sentry/breadcrumb/sentry_logger.rb +2 -0
- data/lib/sentry/breadcrumb.rb +2 -0
- data/lib/sentry/breadcrumb_buffer.rb +2 -0
- data/lib/sentry/client.rb +13 -1
- data/lib/sentry/configuration.rb +57 -77
- data/lib/sentry/core_ext/object/deep_dup.rb +2 -0
- data/lib/sentry/core_ext/object/duplicable.rb +1 -0
- data/lib/sentry/dsn.rb +2 -0
- data/lib/sentry/envelope.rb +25 -0
- data/lib/sentry/event.rb +5 -0
- data/lib/sentry/exceptions.rb +2 -0
- data/lib/sentry/hub.rb +13 -4
- data/lib/sentry/integrable.rb +2 -0
- data/lib/sentry/interface.rb +2 -0
- data/lib/sentry/interfaces/exception.rb +2 -0
- data/lib/sentry/interfaces/single_exception.rb +31 -0
- data/lib/sentry/interfaces/stacktrace.rb +10 -0
- data/lib/sentry/interfaces/stacktrace_builder.rb +2 -0
- data/lib/sentry/interfaces/threads.rb +2 -0
- data/lib/sentry/linecache.rb +2 -0
- data/lib/sentry/net/http.rb +2 -0
- data/lib/sentry/rack/capture_exceptions.rb +2 -0
- data/lib/sentry/rack.rb +2 -0
- data/lib/sentry/rake.rb +4 -4
- data/lib/sentry/release_detector.rb +38 -0
- data/lib/sentry/scope.rb +8 -4
- data/lib/sentry/span.rb +1 -0
- data/lib/sentry/transaction.rb +6 -1
- data/lib/sentry/transport/configuration.rb +2 -0
- data/lib/sentry/transport/dummy_transport.rb +2 -0
- data/lib/sentry/transport/http_transport.rb +6 -4
- data/lib/sentry/transport.rb +77 -19
- data/lib/sentry/utils/argument_checking_helper.rb +2 -0
- data/lib/sentry/utils/custom_inspection.rb +14 -0
- data/lib/sentry/utils/exception_cause_chain.rb +10 -10
- data/lib/sentry/utils/logging_helper.rb +2 -0
- data/lib/sentry/utils/real_ip.rb +2 -0
- data/lib/sentry/utils/request_id.rb +2 -0
- data/lib/sentry/version.rb +3 -1
- data/lib/sentry-ruby.rb +26 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0d62d3133d461116b39ce7e822a3cc523c378417eafade8b3a904f76bce5289
|
4
|
+
data.tar.gz: 4ae280d6e7d88107e7f34f0794d266182d1c801407373023293c38db038aae50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8027f22238a8012bb1aca95d528cb479e287a5b6b17269c9789056d6959f33cab558fac3166147b82b2bda7ee6ad87f4d484ad83634d41804bf198ea7fddd7b2
|
7
|
+
data.tar.gz: ea6681465bf4f538139b0ba6057ea34dec7cb848e77be48ca65c5d7ee5080c492f324dda7903f40d1db275d4bea4f3887048ebf144d7748d02be35314e5fb977
|
data/Gemfile
CHANGED
@@ -10,10 +10,12 @@ gem "rspec", "~> 3.0"
|
|
10
10
|
gem "rspec-retry"
|
11
11
|
gem "webmock"
|
12
12
|
gem "timecop"
|
13
|
-
gem
|
13
|
+
gem 'simplecov'
|
14
|
+
gem "simplecov-cobertura", "~> 1.4"
|
15
|
+
gem "rexml"
|
14
16
|
|
15
17
|
gem "object_tracer"
|
16
|
-
gem "debug", github: "ruby/debug" if RUBY_VERSION.to_f >= 2.6
|
18
|
+
gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
|
17
19
|
gem "pry"
|
18
20
|
|
19
21
|
gem "benchmark-ips"
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -10,13 +10,13 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he
|
|
10
10
|
Sentry SDK for Ruby
|
11
11
|
===========
|
12
12
|
|
13
|
-
| current version | build | coverage | downloads |
|
14
|
-
| --- | ----- | -------- | --------- |
|
15
|
-
| [](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/) |
|
16
|
-
| [](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/) |
|
17
|
-
| [](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/) |
|
18
|
-
| [](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/) |
|
19
|
-
| [](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/) |
|
13
|
+
| current version | build | coverage | downloads |
|
14
|
+
| --- | ----- | -------- | --------- |
|
15
|
+
| [](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/) |
|
16
|
+
| [](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/) |
|
17
|
+
| [](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/) |
|
18
|
+
| [](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/) |
|
19
|
+
| [](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/) |
|
20
20
|
|
21
21
|
|
22
22
|
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
-
require "sentry
|
4
|
+
require "sentry-ruby"
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,9 @@ require "sentry/ruby"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
+
# Sentry.init do |config|
|
14
|
+
# config.dsn = 'https://2fb45f003d054a7ea47feb45898f7649@o447951.ingest.sentry.io/5434472'
|
15
|
+
# end
|
16
|
+
|
13
17
|
require "irb"
|
14
18
|
IRB.start(__FILE__)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/executor/thread_pool_executor"
|
2
4
|
require "concurrent/executor/immediate_executor"
|
3
5
|
require "concurrent/configuration"
|
@@ -7,11 +9,15 @@ module Sentry
|
|
7
9
|
include LoggingHelper
|
8
10
|
|
9
11
|
attr_reader :max_queue, :number_of_threads, :logger
|
12
|
+
attr_accessor :shutdown_timeout
|
10
13
|
|
11
14
|
def initialize(configuration)
|
12
15
|
@max_queue = 30
|
16
|
+
@shutdown_timeout = 1
|
13
17
|
@number_of_threads = configuration.background_worker_threads
|
14
18
|
@logger = configuration.logger
|
19
|
+
@debug = configuration.debug
|
20
|
+
@shutdown_callback = nil
|
15
21
|
|
16
22
|
@executor =
|
17
23
|
if configuration.async
|
@@ -23,19 +29,41 @@ module Sentry
|
|
23
29
|
else
|
24
30
|
log_debug("initialized a background worker with #{@number_of_threads} threads")
|
25
31
|
|
26
|
-
Concurrent::ThreadPoolExecutor.new(
|
32
|
+
executor = Concurrent::ThreadPoolExecutor.new(
|
27
33
|
min_threads: 0,
|
28
34
|
max_threads: @number_of_threads,
|
29
35
|
max_queue: @max_queue,
|
30
36
|
fallback_policy: :discard
|
31
37
|
)
|
38
|
+
|
39
|
+
@shutdown_callback = proc do
|
40
|
+
executor.shutdown
|
41
|
+
executor.wait_for_termination(@shutdown_timeout)
|
42
|
+
end
|
43
|
+
|
44
|
+
executor
|
32
45
|
end
|
33
46
|
end
|
34
47
|
|
48
|
+
# if you want to monkey-patch this method, please override `_perform` instead
|
35
49
|
def perform(&block)
|
36
50
|
@executor.post do
|
37
|
-
|
51
|
+
begin
|
52
|
+
_perform(&block)
|
53
|
+
rescue Exception => e
|
54
|
+
log_error("exception happened in background worker", e, debug: @debug)
|
55
|
+
end
|
38
56
|
end
|
39
57
|
end
|
58
|
+
|
59
|
+
def shutdown
|
60
|
+
@shutdown_callback&.call
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def _perform(&block)
|
66
|
+
block.call
|
67
|
+
end
|
40
68
|
end
|
41
69
|
end
|
data/lib/sentry/breadcrumb.rb
CHANGED
data/lib/sentry/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/transport"
|
2
4
|
|
3
5
|
module Sentry
|
@@ -26,17 +28,25 @@ module Sentry
|
|
26
28
|
def capture_event(event, scope, hint = {})
|
27
29
|
return unless configuration.sending_allowed?
|
28
30
|
|
31
|
+
unless event.is_a?(TransactionEvent) || configuration.sample_allowed?
|
32
|
+
transport.record_lost_event(:sample_rate, 'event')
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
event_type = event.is_a?(Event) ? event.type : event["type"]
|
29
37
|
event = scope.apply_to_event(event, hint)
|
30
38
|
|
31
39
|
if event.nil?
|
32
40
|
log_info("Discarded event because one of the event processors returned nil")
|
41
|
+
transport.record_lost_event(:event_processor, event_type)
|
33
42
|
return
|
34
43
|
end
|
35
44
|
|
36
45
|
if async_block = configuration.async
|
37
46
|
dispatch_async_event(async_block, event, hint)
|
38
47
|
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
39
|
-
dispatch_background_event(event, hint)
|
48
|
+
queued = dispatch_background_event(event, hint)
|
49
|
+
transport.record_lost_event(:queue_overflow, event_type) unless queued
|
40
50
|
else
|
41
51
|
send_event(event, hint)
|
42
52
|
end
|
@@ -84,6 +94,7 @@ module Sentry
|
|
84
94
|
|
85
95
|
if event.nil?
|
86
96
|
log_info("Discarded event because before_send returned nil")
|
97
|
+
transport.record_lost_event(:before_send, 'event')
|
87
98
|
return
|
88
99
|
end
|
89
100
|
end
|
@@ -97,6 +108,7 @@ module Sentry
|
|
97
108
|
|
98
109
|
event_info = Event.get_log_message(event.to_hash)
|
99
110
|
log_info("Unreported #{loggable_event_type}: #{event_info}")
|
111
|
+
transport.record_lost_event(:network_error, event_type)
|
100
112
|
raise
|
101
113
|
end
|
102
114
|
|
data/lib/sentry/configuration.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/utility/processor_counter"
|
2
4
|
|
3
5
|
require "sentry/utils/exception_cause_chain"
|
6
|
+
require 'sentry/utils/custom_inspection'
|
4
7
|
require "sentry/dsn"
|
8
|
+
require "sentry/release_detector"
|
5
9
|
require "sentry/transport/configuration"
|
6
10
|
require "sentry/linecache"
|
7
11
|
require "sentry/interfaces/stacktrace_builder"
|
8
12
|
|
9
13
|
module Sentry
|
10
14
|
class Configuration
|
15
|
+
include CustomInspection
|
11
16
|
include LoggingHelper
|
12
17
|
# Directories to be recognized as part of your app. e.g. if you
|
13
18
|
# have an `engines` dir at the root of your project, you may want
|
@@ -63,6 +68,9 @@ module Sentry
|
|
63
68
|
# - :active_support_logger
|
64
69
|
attr_reader :breadcrumbs_logger
|
65
70
|
|
71
|
+
# Whether to capture local variables from the raised exception's frame. Default is false.
|
72
|
+
attr_accessor :capture_exception_frame_locals
|
73
|
+
|
66
74
|
# Max number of breadcrumbs a breadcrumb buffer can hold
|
67
75
|
attr_accessor :max_breadcrumbs
|
68
76
|
|
@@ -104,7 +112,7 @@ module Sentry
|
|
104
112
|
|
105
113
|
# Project directory root for in_app detection. Could be Rails root, etc.
|
106
114
|
# Set automatically for Rails.
|
107
|
-
|
115
|
+
attr_accessor :project_root
|
108
116
|
|
109
117
|
# Insert sentry-trace to outgoing requests' headers
|
110
118
|
attr_accessor :propagate_traces
|
@@ -154,6 +162,10 @@ module Sentry
|
|
154
162
|
# ```
|
155
163
|
attr_accessor :traces_sampler
|
156
164
|
|
165
|
+
# Send diagnostic client reports about dropped events, true by default
|
166
|
+
# tries to attach to an existing envelope max once every 30s
|
167
|
+
attr_accessor :send_client_reports
|
168
|
+
|
157
169
|
# these are not config options
|
158
170
|
attr_reader :errors, :gem_specs
|
159
171
|
|
@@ -177,17 +189,21 @@ module Sentry
|
|
177
189
|
|
178
190
|
LOG_PREFIX = "** [Sentry] ".freeze
|
179
191
|
MODULE_SEPARATOR = "::".freeze
|
192
|
+
SKIP_INSPECTION_ATTRIBUTES = [:@linecache, :@stacktrace_builder]
|
180
193
|
|
181
194
|
# Post initialization callbacks are called at the end of initialization process
|
182
195
|
# allowing extending the configuration of sentry-ruby by multiple extensions
|
183
196
|
@@post_initialization_callbacks = []
|
184
197
|
|
185
198
|
def initialize
|
199
|
+
self.app_dirs_pattern = nil
|
186
200
|
self.debug = false
|
187
201
|
self.background_worker_threads = Concurrent.processor_count
|
202
|
+
self.backtrace_cleanup_callback = nil
|
188
203
|
self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
|
189
204
|
self.breadcrumbs_logger = []
|
190
205
|
self.context_lines = 3
|
206
|
+
self.capture_exception_frame_locals = false
|
191
207
|
self.environment = environment_from_env
|
192
208
|
self.enabled_environments = []
|
193
209
|
self.exclude_loggers = []
|
@@ -202,12 +218,15 @@ module Sentry
|
|
202
218
|
self.send_modules = true
|
203
219
|
self.send_default_pii = false
|
204
220
|
self.skip_rake_integration = false
|
221
|
+
self.send_client_reports = true
|
205
222
|
self.trusted_proxies = []
|
206
223
|
self.dsn = ENV['SENTRY_DSN']
|
207
224
|
self.server_name = server_name_from_env
|
208
225
|
|
209
|
-
self.before_send =
|
226
|
+
self.before_send = nil
|
210
227
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
228
|
+
self.traces_sample_rate = nil
|
229
|
+
self.traces_sampler = nil
|
211
230
|
|
212
231
|
@transport = Transport::Configuration.new
|
213
232
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
@@ -216,18 +235,13 @@ module Sentry
|
|
216
235
|
end
|
217
236
|
|
218
237
|
def dsn=(value)
|
219
|
-
|
220
|
-
|
221
|
-
@dsn = DSN.new(value)
|
238
|
+
@dsn = init_dsn(value)
|
222
239
|
end
|
223
240
|
|
224
241
|
alias server= dsn=
|
225
242
|
|
226
|
-
|
227
243
|
def async=(value)
|
228
|
-
|
229
|
-
raise(ArgumentError, "async must be callable")
|
230
|
-
end
|
244
|
+
check_callable!("async", value)
|
231
245
|
|
232
246
|
@async = value
|
233
247
|
end
|
@@ -246,17 +260,13 @@ module Sentry
|
|
246
260
|
end
|
247
261
|
|
248
262
|
def before_send=(value)
|
249
|
-
|
250
|
-
raise ArgumentError, "before_send must be callable (or false to disable)"
|
251
|
-
end
|
263
|
+
check_callable!("before_send", value)
|
252
264
|
|
253
265
|
@before_send = value
|
254
266
|
end
|
255
267
|
|
256
268
|
def before_breadcrumb=(value)
|
257
|
-
|
258
|
-
raise ArgumentError, "before_breadcrumb must be callable (or nil to disable)"
|
259
|
-
end
|
269
|
+
check_callable!("before_breadcrumb", value)
|
260
270
|
|
261
271
|
@before_breadcrumb = value
|
262
272
|
end
|
@@ -268,9 +278,13 @@ module Sentry
|
|
268
278
|
def sending_allowed?
|
269
279
|
@errors = []
|
270
280
|
|
271
|
-
valid? &&
|
272
|
-
|
273
|
-
|
281
|
+
valid? && capture_in_environment?
|
282
|
+
end
|
283
|
+
|
284
|
+
def sample_allowed?
|
285
|
+
return true if sample_rate == 1.0
|
286
|
+
|
287
|
+
Random.rand < sample_rate
|
274
288
|
end
|
275
289
|
|
276
290
|
def error_messages
|
@@ -278,10 +292,6 @@ module Sentry
|
|
278
292
|
@errors.join(", ")
|
279
293
|
end
|
280
294
|
|
281
|
-
def project_root=(root_dir)
|
282
|
-
@project_root = root_dir
|
283
|
-
end
|
284
|
-
|
285
295
|
def exception_class_allowed?(exc)
|
286
296
|
if exc.is_a?(Sentry::Error)
|
287
297
|
# Try to prevent error reporting loops
|
@@ -316,10 +326,11 @@ module Sentry
|
|
316
326
|
def detect_release
|
317
327
|
return unless sending_allowed?
|
318
328
|
|
319
|
-
self.release ||=
|
320
|
-
|
321
|
-
|
322
|
-
|
329
|
+
self.release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
|
330
|
+
|
331
|
+
if running_on_heroku? && release.nil?
|
332
|
+
log_warn(HEROKU_DYNO_METADATA_MESSAGE)
|
333
|
+
end
|
323
334
|
rescue => e
|
324
335
|
log_error("Error detecting release", e, debug: debug)
|
325
336
|
end
|
@@ -335,6 +346,18 @@ module Sentry
|
|
335
346
|
|
336
347
|
private
|
337
348
|
|
349
|
+
def check_callable!(name, value)
|
350
|
+
unless value == nil || value.respond_to?(:call)
|
351
|
+
raise ArgumentError, "#{name} must be callable (or nil to disable)"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def init_dsn(dsn_string)
|
356
|
+
return if dsn_string.nil? || dsn_string.empty?
|
357
|
+
|
358
|
+
DSN.new(dsn_string)
|
359
|
+
end
|
360
|
+
|
338
361
|
def excluded_exception?(incoming_exception)
|
339
362
|
excluded_exception_classes.any? do |excluded_exception|
|
340
363
|
matches_exception?(excluded_exception, incoming_exception)
|
@@ -364,37 +387,6 @@ module Sentry
|
|
364
387
|
nil
|
365
388
|
end
|
366
389
|
|
367
|
-
def detect_release_from_heroku
|
368
|
-
return unless running_on_heroku?
|
369
|
-
return if ENV['CI']
|
370
|
-
log_warn(HEROKU_DYNO_METADATA_MESSAGE) && return unless ENV['HEROKU_SLUG_COMMIT']
|
371
|
-
|
372
|
-
ENV['HEROKU_SLUG_COMMIT']
|
373
|
-
end
|
374
|
-
|
375
|
-
def running_on_heroku?
|
376
|
-
File.directory?("/etc/heroku")
|
377
|
-
end
|
378
|
-
|
379
|
-
def detect_release_from_capistrano
|
380
|
-
revision_file = File.join(project_root, 'REVISION')
|
381
|
-
revision_log = File.join(project_root, '..', 'revisions.log')
|
382
|
-
|
383
|
-
if File.exist?(revision_file)
|
384
|
-
File.read(revision_file).strip
|
385
|
-
elsif File.exist?(revision_log)
|
386
|
-
File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
def detect_release_from_git
|
391
|
-
Sentry.sys_command("git rev-parse --short HEAD") if File.directory?(".git")
|
392
|
-
end
|
393
|
-
|
394
|
-
def detect_release_from_env
|
395
|
-
ENV['SENTRY_RELEASE']
|
396
|
-
end
|
397
|
-
|
398
390
|
def capture_in_environment?
|
399
391
|
return true if enabled_in_current_env?
|
400
392
|
|
@@ -411,36 +403,24 @@ module Sentry
|
|
411
403
|
end
|
412
404
|
end
|
413
405
|
|
414
|
-
def sample_allowed?
|
415
|
-
return true if sample_rate == 1.0
|
416
|
-
|
417
|
-
if Random.rand >= sample_rate
|
418
|
-
@errors << "Excluded by random sample"
|
419
|
-
false
|
420
|
-
else
|
421
|
-
true
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
# Try to resolve the hostname to an FQDN, but fall back to whatever
|
426
|
-
# the load name is.
|
427
|
-
def resolve_hostname
|
428
|
-
Socket.gethostname ||
|
429
|
-
Socket.gethostbyname(hostname).first rescue server_name
|
430
|
-
end
|
431
|
-
|
432
406
|
def environment_from_env
|
433
|
-
ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || '
|
407
|
+
ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
434
408
|
end
|
435
409
|
|
436
410
|
def server_name_from_env
|
437
411
|
if running_on_heroku?
|
438
412
|
ENV['DYNO']
|
439
413
|
else
|
440
|
-
|
414
|
+
# Try to resolve the hostname to an FQDN, but fall back to whatever
|
415
|
+
# the load name is.
|
416
|
+
Socket.gethostname || Socket.gethostbyname(hostname).first rescue server_name
|
441
417
|
end
|
442
418
|
end
|
443
419
|
|
420
|
+
def running_on_heroku?
|
421
|
+
File.directory?("/etc/heroku") && !ENV["CI"]
|
422
|
+
end
|
423
|
+
|
444
424
|
def run_post_initialization_callbacks
|
445
425
|
self.class.post_initialization_callbacks.each do |hook|
|
446
426
|
instance_eval(&hook)
|
data/lib/sentry/dsn.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
class Envelope
|
5
|
+
def initialize(headers)
|
6
|
+
@headers = headers
|
7
|
+
@items = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_item(headers, payload)
|
11
|
+
@items << [headers, payload]
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
payload = @items.map do |item_headers, item_payload|
|
16
|
+
<<~ENVELOPE
|
17
|
+
#{JSON.generate(item_headers)}
|
18
|
+
#{JSON.generate(item_payload)}
|
19
|
+
ENVELOPE
|
20
|
+
end.join("\n")
|
21
|
+
|
22
|
+
"#{JSON.generate(@headers)}\n#{payload}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sentry/event.rb
CHANGED
@@ -6,6 +6,7 @@ require 'sentry/interface'
|
|
6
6
|
require 'sentry/backtrace'
|
7
7
|
require 'sentry/utils/real_ip'
|
8
8
|
require 'sentry/utils/request_id'
|
9
|
+
require 'sentry/utils/custom_inspection'
|
9
10
|
|
10
11
|
module Sentry
|
11
12
|
class Event
|
@@ -21,6 +22,10 @@ module Sentry
|
|
21
22
|
|
22
23
|
MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8
|
23
24
|
|
25
|
+
SKIP_INSPECTION_ATTRIBUTES = [:@configuration, :@modules, :@backtrace]
|
26
|
+
|
27
|
+
include CustomInspection
|
28
|
+
|
24
29
|
attr_writer(*WRITER_ATTRIBUTES)
|
25
30
|
attr_reader(*SERIALIZEABLE_ATTRIBUTES)
|
26
31
|
|
data/lib/sentry/exceptions.rb
CHANGED
data/lib/sentry/hub.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/scope"
|
2
4
|
require "sentry/client"
|
3
5
|
|
@@ -90,10 +92,10 @@ module Sentry
|
|
90
92
|
end
|
91
93
|
|
92
94
|
def capture_exception(exception, **options, &block)
|
93
|
-
return unless current_client
|
94
|
-
|
95
95
|
check_argument_type!(exception, ::Exception)
|
96
96
|
|
97
|
+
return unless current_client
|
98
|
+
|
97
99
|
options[:hint] ||= {}
|
98
100
|
options[:hint][:exception] = exception
|
99
101
|
event = current_client.event_from_exception(exception, options[:hint])
|
@@ -104,6 +106,8 @@ module Sentry
|
|
104
106
|
end
|
105
107
|
|
106
108
|
def capture_message(message, **options, &block)
|
109
|
+
check_argument_type!(message, ::String)
|
110
|
+
|
107
111
|
return unless current_client
|
108
112
|
|
109
113
|
options[:hint] ||= {}
|
@@ -114,10 +118,10 @@ module Sentry
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def capture_event(event, **options, &block)
|
117
|
-
return unless current_client
|
118
|
-
|
119
121
|
check_argument_type!(event, Sentry::Event)
|
120
122
|
|
123
|
+
return unless current_client
|
124
|
+
|
121
125
|
hint = options.delete(:hint) || {}
|
122
126
|
scope = current_scope.dup
|
123
127
|
|
@@ -131,6 +135,11 @@ module Sentry
|
|
131
135
|
|
132
136
|
event = current_client.capture_event(event, scope, hint)
|
133
137
|
|
138
|
+
|
139
|
+
if event && configuration.debug
|
140
|
+
configuration.log_debug(event.to_json_compatible)
|
141
|
+
end
|
142
|
+
|
134
143
|
@last_event_id = event&.event_id
|
135
144
|
event
|
136
145
|
end
|
data/lib/sentry/integrable.rb
CHANGED
data/lib/sentry/interface.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sentry/utils/exception_cause_chain"
|
4
|
+
|
1
5
|
module Sentry
|
2
6
|
class SingleExceptionInterface < Interface
|
7
|
+
include CustomInspection
|
8
|
+
|
9
|
+
SKIP_INSPECTION_ATTRIBUTES = [:@stacktrace]
|
10
|
+
PROBLEMATIC_LOCAL_VALUE_REPLACEMENT = "[ignored due to error]".freeze
|
11
|
+
OMISSION_MARK = "...".freeze
|
12
|
+
MAX_LOCAL_BYTES = 1024
|
13
|
+
|
3
14
|
attr_reader :type, :value, :module, :thread_id, :stacktrace
|
4
15
|
|
5
16
|
def initialize(exception:, stacktrace: nil)
|
@@ -20,6 +31,26 @@ module Sentry
|
|
20
31
|
# also see `StacktraceBuilder.build`.
|
21
32
|
def self.build_with_stacktrace(exception:, stacktrace_builder:)
|
22
33
|
stacktrace = stacktrace_builder.build(backtrace: exception.backtrace)
|
34
|
+
|
35
|
+
if locals = exception.instance_variable_get(:@sentry_locals)
|
36
|
+
locals.each do |k, v|
|
37
|
+
locals[k] =
|
38
|
+
begin
|
39
|
+
v = v.inspect unless v.is_a?(String)
|
40
|
+
|
41
|
+
if v.length >= MAX_LOCAL_BYTES
|
42
|
+
v = v.byteslice(0..MAX_LOCAL_BYTES - 1) + OMISSION_MARK
|
43
|
+
end
|
44
|
+
|
45
|
+
v
|
46
|
+
rescue StandardError
|
47
|
+
PROBLEMATIC_LOCAL_VALUE_REPLACEMENT
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
stacktrace.frames.last.vars = locals
|
52
|
+
end
|
53
|
+
|
23
54
|
new(exception: exception, stacktrace: stacktrace)
|
24
55
|
end
|
25
56
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
class StacktraceInterface
|
3
5
|
attr_reader :frames
|
@@ -10,6 +12,10 @@ module Sentry
|
|
10
12
|
{ frames: @frames.map(&:to_hash) }
|
11
13
|
end
|
12
14
|
|
15
|
+
def inspect
|
16
|
+
@frames.map(&:to_s)
|
17
|
+
end
|
18
|
+
|
13
19
|
private
|
14
20
|
|
15
21
|
# Not actually an interface, but I want to use the same style
|
@@ -28,6 +34,10 @@ module Sentry
|
|
28
34
|
@filename = compute_filename
|
29
35
|
end
|
30
36
|
|
37
|
+
def to_s
|
38
|
+
"#{@filename}:#{@lineno}"
|
39
|
+
end
|
40
|
+
|
31
41
|
def compute_filename
|
32
42
|
return if abs_path.nil?
|
33
43
|
|
data/lib/sentry/linecache.rb
CHANGED
data/lib/sentry/net/http.rb
CHANGED
data/lib/sentry/rack.rb
CHANGED
data/lib/sentry/rake.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rake"
|
2
4
|
require "rake/task"
|
3
5
|
|
@@ -5,7 +7,7 @@ module Sentry
|
|
5
7
|
module Rake
|
6
8
|
module Application
|
7
9
|
def display_error_message(ex)
|
8
|
-
Sentry.capture_exception(ex
|
10
|
+
Sentry.capture_exception(ex) do |scope|
|
9
11
|
task_name = top_level_tasks.join(' ')
|
10
12
|
scope.set_transaction_name(task_name)
|
11
13
|
scope.set_tag("rake_task", task_name)
|
@@ -19,9 +21,7 @@ module Sentry
|
|
19
21
|
def execute(args=nil)
|
20
22
|
return super unless Sentry.initialized? && Sentry.get_current_hub
|
21
23
|
|
22
|
-
|
23
|
-
super
|
24
|
-
end
|
24
|
+
super
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
class ReleaseDetector
|
5
|
+
class << self
|
6
|
+
def detect_release(project_root:, running_on_heroku:)
|
7
|
+
detect_release_from_env ||
|
8
|
+
detect_release_from_git ||
|
9
|
+
detect_release_from_capistrano(project_root) ||
|
10
|
+
detect_release_from_heroku(running_on_heroku)
|
11
|
+
end
|
12
|
+
|
13
|
+
def detect_release_from_heroku(running_on_heroku)
|
14
|
+
return unless running_on_heroku
|
15
|
+
ENV['HEROKU_SLUG_COMMIT']
|
16
|
+
end
|
17
|
+
|
18
|
+
def detect_release_from_capistrano(project_root)
|
19
|
+
revision_file = File.join(project_root, 'REVISION')
|
20
|
+
revision_log = File.join(project_root, '..', 'revisions.log')
|
21
|
+
|
22
|
+
if File.exist?(revision_file)
|
23
|
+
File.read(revision_file).strip
|
24
|
+
elsif File.exist?(revision_log)
|
25
|
+
File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def detect_release_from_git
|
30
|
+
Sentry.sys_command("git rev-parse --short HEAD") if File.directory?(".git")
|
31
|
+
end
|
32
|
+
|
33
|
+
def detect_release_from_env
|
34
|
+
ENV['SENTRY_RELEASE']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/breadcrumb_buffer"
|
2
4
|
require "etc"
|
3
5
|
|
@@ -112,7 +114,7 @@ module Sentry
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def set_extra(key, value)
|
115
|
-
|
117
|
+
set_extras(key => value)
|
116
118
|
end
|
117
119
|
|
118
120
|
def set_tags(tags_hash)
|
@@ -121,17 +123,19 @@ module Sentry
|
|
121
123
|
end
|
122
124
|
|
123
125
|
def set_tag(key, value)
|
124
|
-
|
126
|
+
set_tags(key => value)
|
125
127
|
end
|
126
128
|
|
127
129
|
def set_contexts(contexts_hash)
|
128
130
|
check_argument_type!(contexts_hash, Hash)
|
129
|
-
@contexts.merge!(contexts_hash)
|
131
|
+
@contexts.merge!(contexts_hash) do |key, old, new|
|
132
|
+
new.merge(old)
|
133
|
+
end
|
130
134
|
end
|
131
135
|
|
132
136
|
def set_context(key, value)
|
133
137
|
check_argument_type!(value, Hash)
|
134
|
-
|
138
|
+
set_contexts(key => value)
|
135
139
|
end
|
136
140
|
|
137
141
|
def set_level(level)
|
data/lib/sentry/span.rb
CHANGED
data/lib/sentry/transaction.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
class Transaction < Span
|
3
5
|
SENTRY_TRACE_REGEXP = Regexp.new(
|
@@ -129,7 +131,10 @@ module Sentry
|
|
129
131
|
@name = UNLABELD_NAME
|
130
132
|
end
|
131
133
|
|
132
|
-
|
134
|
+
unless @sampled || @parent_sampled
|
135
|
+
hub.current_client.transport.record_lost_event(:sample_rate, 'transaction')
|
136
|
+
return
|
137
|
+
end
|
133
138
|
|
134
139
|
event = hub.current_client.event_from_transaction(self)
|
135
140
|
hub.capture_event(event)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'zlib'
|
3
5
|
|
@@ -139,10 +141,10 @@ module Sentry
|
|
139
141
|
end
|
140
142
|
|
141
143
|
def ssl_configuration
|
142
|
-
|
143
|
-
:
|
144
|
-
:
|
145
|
-
)
|
144
|
+
{
|
145
|
+
verify: @transport_configuration.ssl_verification,
|
146
|
+
ca_file: @transport_configuration.ssl_ca_file
|
147
|
+
}.merge(@transport_configuration.ssl || {})
|
146
148
|
end
|
147
149
|
end
|
148
150
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -1,22 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
require "base64"
|
5
|
+
require "sentry/envelope"
|
3
6
|
|
4
7
|
module Sentry
|
5
8
|
class Transport
|
6
9
|
PROTOCOL_VERSION = '7'
|
7
10
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
11
|
+
CLIENT_REPORT_INTERVAL = 30
|
12
|
+
|
13
|
+
# https://develop.sentry.dev/sdk/client-reports/#envelope-item-payload
|
14
|
+
CLIENT_REPORT_REASONS = [
|
15
|
+
:ratelimit_backoff,
|
16
|
+
:queue_overflow,
|
17
|
+
:cache_overflow, # NA
|
18
|
+
:network_error,
|
19
|
+
:sample_rate,
|
20
|
+
:before_send,
|
21
|
+
:event_processor
|
22
|
+
]
|
8
23
|
|
9
24
|
include LoggingHelper
|
10
25
|
|
11
|
-
|
12
|
-
attr_reader :logger, :rate_limits
|
26
|
+
attr_reader :logger, :rate_limits, :discarded_events, :last_client_report_sent
|
13
27
|
|
14
28
|
def initialize(configuration)
|
15
|
-
@configuration = configuration
|
16
29
|
@logger = configuration.logger
|
17
30
|
@transport_configuration = configuration.transport
|
18
31
|
@dsn = configuration.dsn
|
19
32
|
@rate_limits = {}
|
33
|
+
@send_client_reports = configuration.send_client_reports
|
34
|
+
|
35
|
+
if @send_client_reports
|
36
|
+
@discarded_events = Hash.new(0)
|
37
|
+
@last_client_report_sent = Time.now
|
38
|
+
end
|
20
39
|
end
|
21
40
|
|
22
41
|
def send_data(data, options = {})
|
@@ -27,14 +46,9 @@ module Sentry
|
|
27
46
|
event_hash = event.to_hash
|
28
47
|
item_type = get_item_type(event_hash)
|
29
48
|
|
30
|
-
unless configuration.sending_allowed?
|
31
|
-
log_debug("Envelope [#{item_type}] not sent: #{configuration.error_messages}")
|
32
|
-
|
33
|
-
return
|
34
|
-
end
|
35
|
-
|
36
49
|
if is_rate_limited?(item_type)
|
37
50
|
log_info("Envelope [#{item_type}] not sent: rate limiting")
|
51
|
+
record_lost_event(:ratelimit_backoff, item_type)
|
38
52
|
|
39
53
|
return
|
40
54
|
end
|
@@ -91,20 +105,38 @@ module Sentry
|
|
91
105
|
|
92
106
|
def encode(event)
|
93
107
|
# Convert to hash
|
94
|
-
|
108
|
+
event_payload = event.to_hash
|
109
|
+
event_id = event_payload[:event_id] || event_payload["event_id"]
|
110
|
+
item_type = get_item_type(event_payload)
|
111
|
+
|
112
|
+
envelope = Envelope.new(
|
113
|
+
{
|
114
|
+
event_id: event_id,
|
115
|
+
dsn: @dsn.to_s,
|
116
|
+
sdk: Sentry.sdk_meta,
|
117
|
+
sent_at: Sentry.utc_now.iso8601
|
118
|
+
}
|
119
|
+
)
|
120
|
+
|
121
|
+
envelope.add_item(
|
122
|
+
{ type: item_type, content_type: 'application/json' },
|
123
|
+
event_payload
|
124
|
+
)
|
125
|
+
|
126
|
+
client_report_headers, client_report_payload = fetch_pending_client_report
|
127
|
+
envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
|
95
128
|
|
96
|
-
|
97
|
-
item_type = get_item_type(event_hash)
|
129
|
+
log_info("Sending envelope [#{item_type}] #{event_id} to Sentry")
|
98
130
|
|
99
|
-
envelope
|
100
|
-
|
101
|
-
{"type":"#{item_type}","content_type":"application/json"}
|
102
|
-
#{JSON.generate(event_hash)}
|
103
|
-
ENVELOPE
|
131
|
+
envelope.to_s
|
132
|
+
end
|
104
133
|
|
105
|
-
|
134
|
+
def record_lost_event(reason, item_type)
|
135
|
+
return unless @send_client_reports
|
136
|
+
return unless CLIENT_REPORT_REASONS.include?(reason)
|
106
137
|
|
107
|
-
|
138
|
+
item_type ||= 'event'
|
139
|
+
@discarded_events[[reason, item_type]] += 1
|
108
140
|
end
|
109
141
|
|
110
142
|
private
|
@@ -112,6 +144,32 @@ module Sentry
|
|
112
144
|
def get_item_type(event_hash)
|
113
145
|
event_hash[:type] || event_hash["type"] || "event"
|
114
146
|
end
|
147
|
+
|
148
|
+
def fetch_pending_client_report
|
149
|
+
return nil unless @send_client_reports
|
150
|
+
return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
151
|
+
return nil if @discarded_events.empty?
|
152
|
+
|
153
|
+
discarded_events_hash = @discarded_events.map do |key, val|
|
154
|
+
reason, type = key
|
155
|
+
|
156
|
+
# 'event' has to be mapped to 'error'
|
157
|
+
category = type == 'transaction' ? 'transaction' : 'error'
|
158
|
+
|
159
|
+
{ reason: reason, category: category, quantity: val }
|
160
|
+
end
|
161
|
+
|
162
|
+
item_header = { type: 'client_report' }
|
163
|
+
item_payload = {
|
164
|
+
timestamp: Sentry.utc_now.iso8601,
|
165
|
+
discarded_events: discarded_events_hash
|
166
|
+
}
|
167
|
+
|
168
|
+
@discarded_events = Hash.new(0)
|
169
|
+
@last_client_report_sent = Time.now
|
170
|
+
|
171
|
+
[item_header, item_payload]
|
172
|
+
end
|
115
173
|
end
|
116
174
|
end
|
117
175
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module CustomInspection
|
5
|
+
def inspect
|
6
|
+
attr_strings = (instance_variables - self.class::SKIP_INSPECTION_ATTRIBUTES).each_with_object([]) do |attr, result|
|
7
|
+
value = instance_variable_get(attr)
|
8
|
+
result << "#{attr}=#{value.inspect}" if value
|
9
|
+
end
|
10
|
+
|
11
|
+
"#<#{self.class.name} #{attr_strings.join(", ")}>"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Utils
|
3
5
|
module ExceptionCauseChain
|
4
6
|
def self.exception_to_array(exception)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
exceptions = [exception]
|
8
|
+
|
9
|
+
while exception.cause
|
10
|
+
exception = exception.cause
|
11
|
+
break if exceptions.any? { |e| e.object_id == exception.object_id }
|
10
12
|
|
11
|
-
|
12
|
-
end
|
13
|
-
exceptions
|
14
|
-
else
|
15
|
-
[exception]
|
13
|
+
exceptions << exception
|
16
14
|
end
|
15
|
+
|
16
|
+
exceptions
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/lib/sentry/utils/real_ip.rb
CHANGED
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "English"
|
2
4
|
require "forwardable"
|
3
5
|
require "time"
|
@@ -37,6 +39,22 @@ module Sentry
|
|
37
39
|
THREAD_LOCAL = :sentry_hub
|
38
40
|
|
39
41
|
class << self
|
42
|
+
def exception_locals_tp
|
43
|
+
@exception_locals_tp ||= TracePoint.new(:raise) do |tp|
|
44
|
+
exception = tp.raised_exception
|
45
|
+
|
46
|
+
# don't collect locals again if the exception is re-raised
|
47
|
+
next if exception.instance_variable_get(:@sentry_locals)
|
48
|
+
next unless tp.binding
|
49
|
+
|
50
|
+
locals = tp.binding.local_variables.each_with_object({}) do |local, result|
|
51
|
+
result[local] = tp.binding.local_variable_get(local)
|
52
|
+
end
|
53
|
+
|
54
|
+
exception.instance_variable_set(:@sentry_locals, locals)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
40
58
|
attr_accessor :background_worker
|
41
59
|
|
42
60
|
##### Patch Registration #####
|
@@ -88,6 +106,14 @@ module Sentry
|
|
88
106
|
Thread.current.thread_variable_set(THREAD_LOCAL, hub)
|
89
107
|
@main_hub = hub
|
90
108
|
@background_worker = Sentry::BackgroundWorker.new(config)
|
109
|
+
|
110
|
+
if config.capture_exception_frame_locals
|
111
|
+
exception_locals_tp.enable
|
112
|
+
end
|
113
|
+
|
114
|
+
at_exit do
|
115
|
+
@background_worker.shutdown
|
116
|
+
end
|
91
117
|
end
|
92
118
|
|
93
119
|
# Returns an uri for security policy reporting that's generated from the given DSN
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.8.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: 2021-
|
11
|
+
date: 2021-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- lib/sentry/core_ext/object/deep_dup.rb
|
69
69
|
- lib/sentry/core_ext/object/duplicable.rb
|
70
70
|
- lib/sentry/dsn.rb
|
71
|
+
- lib/sentry/envelope.rb
|
71
72
|
- lib/sentry/event.rb
|
72
73
|
- lib/sentry/exceptions.rb
|
73
74
|
- lib/sentry/hub.rb
|
@@ -85,6 +86,7 @@ files:
|
|
85
86
|
- lib/sentry/rack.rb
|
86
87
|
- lib/sentry/rack/capture_exceptions.rb
|
87
88
|
- lib/sentry/rake.rb
|
89
|
+
- lib/sentry/release_detector.rb
|
88
90
|
- lib/sentry/scope.rb
|
89
91
|
- lib/sentry/span.rb
|
90
92
|
- lib/sentry/transaction.rb
|
@@ -94,6 +96,7 @@ files:
|
|
94
96
|
- lib/sentry/transport/dummy_transport.rb
|
95
97
|
- lib/sentry/transport/http_transport.rb
|
96
98
|
- lib/sentry/utils/argument_checking_helper.rb
|
99
|
+
- lib/sentry/utils/custom_inspection.rb
|
97
100
|
- lib/sentry/utils/exception_cause_chain.rb
|
98
101
|
- lib/sentry/utils/logging_helper.rb
|
99
102
|
- lib/sentry/utils/real_ip.rb
|