sentry-ruby 5.5.0 → 5.10.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/.rspec +0 -1
- data/Gemfile +14 -5
- data/README.md +3 -0
- data/Rakefile +8 -1
- data/lib/sentry/backtrace.rb +1 -1
- data/lib/sentry/baggage.rb +1 -12
- data/lib/sentry/client.rb +14 -1
- data/lib/sentry/configuration.rb +128 -26
- data/lib/sentry/envelope.rb +1 -4
- data/lib/sentry/hub.rb +31 -3
- data/lib/sentry/interfaces/request.rb +2 -14
- data/lib/sentry/interfaces/single_exception.rb +9 -1
- data/lib/sentry/net/http.rb +20 -37
- data/lib/sentry/profiler.rb +222 -0
- data/lib/sentry/puma.rb +25 -0
- data/lib/sentry/rack/capture_exceptions.rb +1 -1
- data/lib/sentry/redis.rb +36 -23
- data/lib/sentry/scope.rb +26 -3
- data/lib/sentry/span.rb +14 -11
- data/lib/sentry/test_helper.rb +1 -1
- data/lib/sentry/transaction.rb +73 -15
- data/lib/sentry/transaction_event.rb +36 -0
- data/lib/sentry/transport.rb +7 -0
- data/lib/sentry/utils/argument_checking_helper.rb +3 -3
- data/lib/sentry/utils/encoding_helper.rb +22 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +35 -20
- metadata +5 -3
- data/CODE_OF_CONDUCT.md +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2373a9b8990fd62763c4d1b26001f953f95efdd8b51f803e5d59bdb1ba984e3e
|
4
|
+
data.tar.gz: d09371eb4bf3aaff6e7735f74cd5887b2e99f636a60f1dca3cf653bbb8ba9bb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4799b727ddaab0622be00e73b58a2e3f723779e1b46c7d5007d5711a8897022190ff9f87cc90df7411f32fd6b59d4f4637bcf26cc7eba8484cb04429871e9242
|
7
|
+
data.tar.gz: d97d9272ee815447ebdcbb72adb4e2255584475547e7878ed6c7af4f312d170bd37f3029acaaa6866eb04f2d89c1581c4854b849c2d57a1a51eb4b67e4ebeb0e
|
data/.rspec
CHANGED
data/Gemfile
CHANGED
@@ -7,17 +7,25 @@ rack_version = ENV["RACK_VERSION"]
|
|
7
7
|
rack_version = "3.0.0" if rack_version.nil?
|
8
8
|
gem "rack", "~> #{Gem::Version.new(rack_version)}" unless rack_version == "0"
|
9
9
|
|
10
|
+
redis_rb_version = ENV.fetch("REDIS_RB_VERSION", "5.0")
|
11
|
+
gem "redis", "~> #{redis_rb_version}"
|
12
|
+
|
13
|
+
gem "puma"
|
14
|
+
|
10
15
|
gem "rake", "~> 12.0"
|
11
16
|
gem "rspec", "~> 3.0"
|
12
17
|
gem "rspec-retry"
|
13
|
-
gem "fakeredis"
|
14
18
|
gem "timecop"
|
15
|
-
gem
|
19
|
+
gem "simplecov"
|
16
20
|
gem "simplecov-cobertura", "~> 1.4"
|
17
21
|
gem "rexml"
|
22
|
+
gem "stackprof" unless RUBY_PLATFORM == "java"
|
23
|
+
|
24
|
+
if RUBY_VERSION.to_f >= 2.6
|
25
|
+
gem "debug", github: "ruby/debug", platform: :ruby
|
26
|
+
gem "irb"
|
27
|
+
end
|
18
28
|
|
19
|
-
gem "object_tracer"
|
20
|
-
gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
|
21
29
|
gem "pry"
|
22
30
|
|
23
31
|
gem "benchmark-ips"
|
@@ -25,4 +33,5 @@ gem "benchmark_driver"
|
|
25
33
|
gem "benchmark-ipsa"
|
26
34
|
gem "benchmark-memory"
|
27
35
|
|
28
|
-
gem "yard",
|
36
|
+
gem "yard", github: "lsegal/yard"
|
37
|
+
gem "webrick"
|
data/README.md
CHANGED
@@ -20,6 +20,7 @@ Sentry SDK for Ruby
|
|
20
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
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
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/) |
|
23
24
|
|
24
25
|
|
25
26
|
|
@@ -51,6 +52,7 @@ gem "sentry-rails"
|
|
51
52
|
gem "sentry-sidekiq"
|
52
53
|
gem "sentry-delayed_job"
|
53
54
|
gem "sentry-resque"
|
55
|
+
gem "sentry-opentelemetry"
|
54
56
|
```
|
55
57
|
|
56
58
|
### Configuration
|
@@ -88,6 +90,7 @@ To learn more about sampling transactions, please visit the [official documentat
|
|
88
90
|
- [Sidekiq](https://docs.sentry.io/platforms/ruby/guides/sidekiq/)
|
89
91
|
- [DelayedJob](https://docs.sentry.io/platforms/ruby/guides/delayed_job/)
|
90
92
|
- [Resque](https://docs.sentry.io/platforms/ruby/guides/resque/)
|
93
|
+
- [OpenTemeletry](https://docs.sentry.io/platforms/ruby/performance/instrumentation/opentelemetry/)
|
91
94
|
|
92
95
|
### Enriching Events
|
93
96
|
|
data/Rakefile
CHANGED
@@ -8,6 +8,13 @@ require "rspec/core/rake_task"
|
|
8
8
|
|
9
9
|
RSpec::Core::RakeTask.new(:spec).tap do |task|
|
10
10
|
task.rspec_opts = "--order rand"
|
11
|
+
task.exclude_pattern = "spec/isolated/**/*_spec.rb"
|
11
12
|
end
|
12
13
|
|
13
|
-
task :
|
14
|
+
task :isolated_specs do
|
15
|
+
Dir["spec/isolated/*"].each do |file|
|
16
|
+
sh "bundle exec rspec #{file}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => [:spec, :isolated_specs]
|
data/lib/sentry/backtrace.rb
CHANGED
data/lib/sentry/baggage.rb
CHANGED
@@ -8,17 +8,6 @@ module Sentry
|
|
8
8
|
SENTRY_PREFIX = 'sentry-'
|
9
9
|
SENTRY_PREFIX_REGEX = /^sentry-/.freeze
|
10
10
|
|
11
|
-
DSC_KEYS = %w(
|
12
|
-
trace_id
|
13
|
-
public_key
|
14
|
-
sample_rate
|
15
|
-
release
|
16
|
-
environment
|
17
|
-
transaction
|
18
|
-
user_id
|
19
|
-
user_segment
|
20
|
-
).freeze
|
21
|
-
|
22
11
|
# @return [Hash]
|
23
12
|
attr_reader :items
|
24
13
|
|
@@ -68,7 +57,7 @@ module Sentry
|
|
68
57
|
# hash to be used in the trace envelope header.
|
69
58
|
# @return [Hash]
|
70
59
|
def dynamic_sampling_context
|
71
|
-
@items
|
60
|
+
@items
|
72
61
|
end
|
73
62
|
|
74
63
|
# Serialize the Baggage object back to a string.
|
data/lib/sentry/client.rb
CHANGED
@@ -76,7 +76,10 @@ module Sentry
|
|
76
76
|
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
77
77
|
# @return [Event, nil]
|
78
78
|
def event_from_exception(exception, hint = {})
|
79
|
-
return unless @configuration.sending_allowed?
|
79
|
+
return unless @configuration.sending_allowed?
|
80
|
+
|
81
|
+
ignore_exclusions = hint.delete(:ignore_exclusions) { false }
|
82
|
+
return if !ignore_exclusions && !@configuration.exception_class_allowed?(exception)
|
80
83
|
|
81
84
|
integration_meta = Sentry.integrations[hint[:integration]]
|
82
85
|
|
@@ -122,6 +125,16 @@ module Sentry
|
|
122
125
|
end
|
123
126
|
end
|
124
127
|
|
128
|
+
if event_type == TransactionEvent::TYPE && configuration.before_send_transaction
|
129
|
+
event = configuration.before_send_transaction.call(event, hint)
|
130
|
+
|
131
|
+
if event.nil?
|
132
|
+
log_info("Discarded event because before_send_transaction returned nil")
|
133
|
+
transport.record_lost_event(:before_send, 'transaction')
|
134
|
+
return
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
125
138
|
transport.send_event(event)
|
126
139
|
|
127
140
|
event
|
data/lib/sentry/configuration.rb
CHANGED
@@ -14,6 +14,8 @@ module Sentry
|
|
14
14
|
class Configuration
|
15
15
|
include CustomInspection
|
16
16
|
include LoggingHelper
|
17
|
+
include ArgumentCheckingHelper
|
18
|
+
|
17
19
|
# Directories to be recognized as part of your app. e.g. if you
|
18
20
|
# have an `engines` dir at the root of your project, you may want
|
19
21
|
# to set this to something like /(app|config|engines|lib)/
|
@@ -72,6 +74,19 @@ module Sentry
|
|
72
74
|
# @return [Proc]
|
73
75
|
attr_reader :before_send
|
74
76
|
|
77
|
+
# Optional Proc, called before sending an event to the server
|
78
|
+
# @example
|
79
|
+
# config.before_send_transaction = lambda do |event, hint|
|
80
|
+
# # skip unimportant transactions or strip sensitive data
|
81
|
+
# if event.transaction == "/healthcheck/route"
|
82
|
+
# nil
|
83
|
+
# else
|
84
|
+
# event
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
# @return [Proc]
|
88
|
+
attr_reader :before_send_transaction
|
89
|
+
|
75
90
|
# An array of breadcrumbs loggers to be used. Available options are:
|
76
91
|
# - :sentry_logger
|
77
92
|
# - :http_logger
|
@@ -84,10 +99,6 @@ module Sentry
|
|
84
99
|
# @return [Array<Symbol>]
|
85
100
|
attr_reader :breadcrumbs_logger
|
86
101
|
|
87
|
-
# Whether to capture local variables from the raised exception's frame. Default is false.
|
88
|
-
# @return [Boolean]
|
89
|
-
attr_accessor :capture_exception_frame_locals
|
90
|
-
|
91
102
|
# Max number of breadcrumbs a breadcrumb buffer can hold
|
92
103
|
# @return [Integer]
|
93
104
|
attr_accessor :max_breadcrumbs
|
@@ -127,6 +138,22 @@ module Sentry
|
|
127
138
|
attr_accessor :inspect_exception_causes_for_exclusion
|
128
139
|
alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
|
129
140
|
|
141
|
+
# Whether to capture local variables from the raised exception's frame. Default is false.
|
142
|
+
# @return [Boolean]
|
143
|
+
attr_accessor :include_local_variables
|
144
|
+
|
145
|
+
# @deprecated Use {#include_local_variables} instead.
|
146
|
+
alias_method :capture_exception_frame_locals, :include_local_variables
|
147
|
+
|
148
|
+
# @deprecated Use {#include_local_variables=} instead.
|
149
|
+
def capture_exception_frame_locals=(value)
|
150
|
+
log_warn <<~MSG
|
151
|
+
`capture_exception_frame_locals` is now deprecated in favor of `include_local_variables`.
|
152
|
+
MSG
|
153
|
+
|
154
|
+
self.include_local_variables = value
|
155
|
+
end
|
156
|
+
|
130
157
|
# You may provide your own LineCache for matching paths with source files.
|
131
158
|
# This may be useful if you need to get source code from places other than the disk.
|
132
159
|
# @see LineCache
|
@@ -154,7 +181,7 @@ module Sentry
|
|
154
181
|
# Release tag to be passed with every event sent to Sentry.
|
155
182
|
# We automatically try to set this to a git SHA or Capistrano release.
|
156
183
|
# @return [String]
|
157
|
-
|
184
|
+
attr_reader :release
|
158
185
|
|
159
186
|
# The sampling factor to apply to events. A value of 0.0 will not send
|
160
187
|
# any events, and a value of 1.0 will send 100% of events.
|
@@ -189,8 +216,8 @@ module Sentry
|
|
189
216
|
attr_reader :transport
|
190
217
|
|
191
218
|
# Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
|
192
|
-
# @return [Float]
|
193
|
-
|
219
|
+
# @return [Float, nil]
|
220
|
+
attr_reader :traces_sample_rate
|
194
221
|
|
195
222
|
# Take a Proc that controls the sample rate for every tracing event, e.g.
|
196
223
|
# @example
|
@@ -202,6 +229,11 @@ module Sentry
|
|
202
229
|
# @return [Proc]
|
203
230
|
attr_accessor :traces_sampler
|
204
231
|
|
232
|
+
# Easier way to use performance tracing
|
233
|
+
# If set to true, will set traces_sample_rate to 1.0
|
234
|
+
# @return [Boolean, nil]
|
235
|
+
attr_reader :enable_tracing
|
236
|
+
|
205
237
|
# Send diagnostic client reports about dropped events, true by default
|
206
238
|
# tries to attach to an existing envelope max once every 30s
|
207
239
|
# @return [Boolean]
|
@@ -211,10 +243,29 @@ module Sentry
|
|
211
243
|
# @return [Boolean]
|
212
244
|
attr_accessor :auto_session_tracking
|
213
245
|
|
246
|
+
# The instrumenter to use, :sentry or :otel
|
247
|
+
# @return [Symbol]
|
248
|
+
attr_reader :instrumenter
|
249
|
+
|
250
|
+
# Take a float between 0.0 and 1.0 as the sample rate for capturing profiles.
|
251
|
+
# Note that this rate is relative to traces_sample_rate / traces_sampler,
|
252
|
+
# i.e. the profile is sampled by this rate after the transaction is sampled.
|
253
|
+
# @return [Float, nil]
|
254
|
+
attr_reader :profiles_sample_rate
|
255
|
+
|
214
256
|
# these are not config options
|
215
257
|
# @!visibility private
|
216
258
|
attr_reader :errors, :gem_specs
|
217
259
|
|
260
|
+
# These exceptions could enter Puma's `lowlevel_error_handler` callback and the SDK's Puma integration
|
261
|
+
# But they are mostly considered as noise and should be ignored by default
|
262
|
+
# Please see https://github.com/getsentry/sentry-ruby/pull/2026 for more information
|
263
|
+
PUMA_IGNORE_DEFAULT = [
|
264
|
+
'Puma::MiniSSL::SSLError',
|
265
|
+
'Puma::HttpParserError',
|
266
|
+
'Puma::HttpParserError501'
|
267
|
+
].freeze
|
268
|
+
|
218
269
|
# Most of these errors generate 4XX responses. In general, Sentry clients
|
219
270
|
# only automatically report 5xx responses.
|
220
271
|
IGNORE_DEFAULT = [
|
@@ -237,9 +288,20 @@ module Sentry
|
|
237
288
|
MODULE_SEPARATOR = "::".freeze
|
238
289
|
SKIP_INSPECTION_ATTRIBUTES = [:@linecache, :@stacktrace_builder]
|
239
290
|
|
240
|
-
|
241
|
-
|
242
|
-
|
291
|
+
INSTRUMENTERS = [:sentry, :otel]
|
292
|
+
|
293
|
+
class << self
|
294
|
+
# Post initialization callbacks are called at the end of initialization process
|
295
|
+
# allowing extending the configuration of sentry-ruby by multiple extensions
|
296
|
+
def post_initialization_callbacks
|
297
|
+
@post_initialization_callbacks ||= []
|
298
|
+
end
|
299
|
+
|
300
|
+
# allow extensions to add their hooks to the Configuration class
|
301
|
+
def add_post_initialization_callback(&block)
|
302
|
+
post_initialization_callbacks << block
|
303
|
+
end
|
304
|
+
end
|
243
305
|
|
244
306
|
def initialize
|
245
307
|
self.app_dirs_pattern = nil
|
@@ -249,11 +311,11 @@ module Sentry
|
|
249
311
|
self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
|
250
312
|
self.breadcrumbs_logger = []
|
251
313
|
self.context_lines = 3
|
252
|
-
self.
|
314
|
+
self.include_local_variables = false
|
253
315
|
self.environment = environment_from_env
|
254
316
|
self.enabled_environments = []
|
255
317
|
self.exclude_loggers = []
|
256
|
-
self.excluded_exceptions = IGNORE_DEFAULT
|
318
|
+
self.excluded_exceptions = IGNORE_DEFAULT + PUMA_IGNORE_DEFAULT
|
257
319
|
self.inspect_exception_causes_for_exclusion = true
|
258
320
|
self.linecache = ::Sentry::LineCache.new
|
259
321
|
self.logger = ::Sentry::Logger.new(STDOUT)
|
@@ -269,11 +331,13 @@ module Sentry
|
|
269
331
|
self.trusted_proxies = []
|
270
332
|
self.dsn = ENV['SENTRY_DSN']
|
271
333
|
self.server_name = server_name_from_env
|
334
|
+
self.instrumenter = :sentry
|
272
335
|
|
273
336
|
self.before_send = nil
|
337
|
+
self.before_send_transaction = nil
|
274
338
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
275
|
-
self.traces_sample_rate = nil
|
276
339
|
self.traces_sampler = nil
|
340
|
+
self.enable_tracing = nil
|
277
341
|
|
278
342
|
@transport = Transport::Configuration.new
|
279
343
|
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
@@ -287,6 +351,12 @@ module Sentry
|
|
287
351
|
|
288
352
|
alias server= dsn=
|
289
353
|
|
354
|
+
def release=(value)
|
355
|
+
check_argument_type!(value, String, NilClass)
|
356
|
+
|
357
|
+
@release = value
|
358
|
+
end
|
359
|
+
|
290
360
|
def async=(value)
|
291
361
|
check_callable!("async", value)
|
292
362
|
|
@@ -322,6 +392,12 @@ module Sentry
|
|
322
392
|
@before_send = value
|
323
393
|
end
|
324
394
|
|
395
|
+
def before_send_transaction=(value)
|
396
|
+
check_callable!("before_send_transaction", value)
|
397
|
+
|
398
|
+
@before_send_transaction = value
|
399
|
+
end
|
400
|
+
|
325
401
|
def before_breadcrumb=(value)
|
326
402
|
check_callable!("before_breadcrumb", value)
|
327
403
|
|
@@ -332,6 +408,30 @@ module Sentry
|
|
332
408
|
@environment = environment.to_s
|
333
409
|
end
|
334
410
|
|
411
|
+
def instrumenter=(instrumenter)
|
412
|
+
@instrumenter = INSTRUMENTERS.include?(instrumenter) ? instrumenter : :sentry
|
413
|
+
end
|
414
|
+
|
415
|
+
def enable_tracing=(enable_tracing)
|
416
|
+
@enable_tracing = enable_tracing
|
417
|
+
@traces_sample_rate ||= 1.0 if enable_tracing
|
418
|
+
end
|
419
|
+
|
420
|
+
def is_numeric_or_nil?(value)
|
421
|
+
value.is_a?(Numeric) || value.nil?
|
422
|
+
end
|
423
|
+
|
424
|
+
def traces_sample_rate=(traces_sample_rate)
|
425
|
+
raise ArgumentError, "traces_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(traces_sample_rate)
|
426
|
+
@traces_sample_rate = traces_sample_rate
|
427
|
+
end
|
428
|
+
|
429
|
+
def profiles_sample_rate=(profiles_sample_rate)
|
430
|
+
raise ArgumentError, "profiles_sample_rate must be a Numeric or nil" unless is_numeric_or_nil?(profiles_sample_rate)
|
431
|
+
log_info("Please make sure to include the 'stackprof' gem in your Gemfile to use Profiling with Sentry.") unless defined?(StackProf)
|
432
|
+
@profiles_sample_rate = profiles_sample_rate
|
433
|
+
end
|
434
|
+
|
335
435
|
def sending_allowed?
|
336
436
|
@errors = []
|
337
437
|
|
@@ -361,8 +461,21 @@ module Sentry
|
|
361
461
|
enabled_environments.empty? || enabled_environments.include?(environment)
|
362
462
|
end
|
363
463
|
|
464
|
+
def valid_sample_rate?(sample_rate)
|
465
|
+
return false unless sample_rate.is_a?(Numeric)
|
466
|
+
sample_rate >= 0.0 && sample_rate <= 1.0
|
467
|
+
end
|
468
|
+
|
364
469
|
def tracing_enabled?
|
365
|
-
!!((@traces_sample_rate
|
470
|
+
valid_sampler = !!((valid_sample_rate?(@traces_sample_rate)) || @traces_sampler)
|
471
|
+
|
472
|
+
(@enable_tracing != false) && valid_sampler && sending_allowed?
|
473
|
+
end
|
474
|
+
|
475
|
+
def profiling_enabled?
|
476
|
+
valid_sampler = !!(valid_sample_rate?(@profiles_sample_rate))
|
477
|
+
|
478
|
+
tracing_enabled? && valid_sampler && sending_allowed?
|
366
479
|
end
|
367
480
|
|
368
481
|
# @return [String, nil]
|
@@ -390,7 +503,7 @@ module Sentry
|
|
390
503
|
def detect_release
|
391
504
|
return unless sending_allowed?
|
392
505
|
|
393
|
-
|
506
|
+
@release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
|
394
507
|
|
395
508
|
if running_on_heroku? && release.nil?
|
396
509
|
log_warn(HEROKU_DYNO_METADATA_MESSAGE)
|
@@ -487,16 +600,5 @@ module Sentry
|
|
487
600
|
instance_eval(&hook)
|
488
601
|
end
|
489
602
|
end
|
490
|
-
|
491
|
-
# allow extensions to add their hooks to the Configuration class
|
492
|
-
def self.add_post_initialization_callback(&block)
|
493
|
-
self.post_initialization_callbacks << block
|
494
|
-
end
|
495
|
-
|
496
|
-
protected
|
497
|
-
|
498
|
-
def self.post_initialization_callbacks
|
499
|
-
@@post_initialization_callbacks
|
500
|
-
end
|
501
603
|
end
|
502
604
|
end
|
data/lib/sentry/envelope.rb
CHANGED
data/lib/sentry/hub.rb
CHANGED
@@ -76,8 +76,9 @@ module Sentry
|
|
76
76
|
@stack.pop
|
77
77
|
end
|
78
78
|
|
79
|
-
def start_transaction(transaction: nil, custom_sampling_context: {}, **options)
|
79
|
+
def start_transaction(transaction: nil, custom_sampling_context: {}, instrumenter: :sentry, **options)
|
80
80
|
return unless configuration.tracing_enabled?
|
81
|
+
return unless instrumenter == configuration.instrumenter
|
81
82
|
|
82
83
|
transaction ||= Transaction.new(**options.merge(hub: self))
|
83
84
|
|
@@ -87,13 +88,39 @@ module Sentry
|
|
87
88
|
}
|
88
89
|
|
89
90
|
sampling_context.merge!(custom_sampling_context)
|
90
|
-
|
91
91
|
transaction.set_initial_sample_decision(sampling_context: sampling_context)
|
92
|
+
|
93
|
+
transaction.start_profiler!
|
94
|
+
|
92
95
|
transaction
|
93
96
|
end
|
94
97
|
|
98
|
+
def with_child_span(instrumenter: :sentry, **attributes, &block)
|
99
|
+
return yield(nil) unless instrumenter == configuration.instrumenter
|
100
|
+
|
101
|
+
current_span = current_scope.get_span
|
102
|
+
return yield(nil) unless current_span
|
103
|
+
|
104
|
+
result = nil
|
105
|
+
|
106
|
+
begin
|
107
|
+
current_span.with_child_span(**attributes) do |child_span|
|
108
|
+
current_scope.set_span(child_span)
|
109
|
+
result = yield(child_span)
|
110
|
+
end
|
111
|
+
ensure
|
112
|
+
current_scope.set_span(current_span)
|
113
|
+
end
|
114
|
+
|
115
|
+
result
|
116
|
+
end
|
117
|
+
|
95
118
|
def capture_exception(exception, **options, &block)
|
96
|
-
|
119
|
+
if RUBY_PLATFORM == "java"
|
120
|
+
check_argument_type!(exception, ::Exception, ::Java::JavaLang::Throwable)
|
121
|
+
else
|
122
|
+
check_argument_type!(exception, ::Exception)
|
123
|
+
end
|
97
124
|
|
98
125
|
return if Sentry.exception_captured?(exception)
|
99
126
|
|
@@ -101,6 +128,7 @@ module Sentry
|
|
101
128
|
|
102
129
|
options[:hint] ||= {}
|
103
130
|
options[:hint][:exception] = exception
|
131
|
+
|
104
132
|
event = current_client.event_from_exception(exception, options[:hint])
|
105
133
|
|
106
134
|
return unless event
|
@@ -73,7 +73,7 @@ module Sentry
|
|
73
73
|
request.POST
|
74
74
|
elsif request.body # JSON requests, etc
|
75
75
|
data = request.body.read(MAX_BODY_LIMIT)
|
76
|
-
data = encode_to_utf_8(data.to_s)
|
76
|
+
data = Utils::EncodingHelper.encode_to_utf_8(data.to_s)
|
77
77
|
request.body.rewind
|
78
78
|
data
|
79
79
|
end
|
@@ -94,7 +94,7 @@ module Sentry
|
|
94
94
|
key = key.sub(/^HTTP_/, "")
|
95
95
|
key = key.split('_').map(&:capitalize).join('-')
|
96
96
|
|
97
|
-
memo[key] = encode_to_utf_8(value.to_s)
|
97
|
+
memo[key] = Utils::EncodingHelper.encode_to_utf_8(value.to_s)
|
98
98
|
rescue StandardError => e
|
99
99
|
# Rails adds objects to the Rack env that can sometimes raise exceptions
|
100
100
|
# when `to_s` is called.
|
@@ -105,18 +105,6 @@ module Sentry
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
def encode_to_utf_8(value)
|
109
|
-
if value.encoding != Encoding::UTF_8 && value.respond_to?(:force_encoding)
|
110
|
-
value = value.dup.force_encoding(Encoding::UTF_8)
|
111
|
-
end
|
112
|
-
|
113
|
-
if !value.valid_encoding?
|
114
|
-
value = value.scrub
|
115
|
-
end
|
116
|
-
|
117
|
-
value
|
118
|
-
end
|
119
|
-
|
120
108
|
def is_skippable_header?(key)
|
121
109
|
key.upcase != key || # lower-case envs aren't real http headers
|
122
110
|
key == "HTTP_COOKIE" || # Cookies don't go here, they go somewhere else
|
@@ -15,7 +15,15 @@ module Sentry
|
|
15
15
|
|
16
16
|
def initialize(exception:, stacktrace: nil)
|
17
17
|
@type = exception.class.to_s
|
18
|
-
|
18
|
+
exception_message =
|
19
|
+
if exception.respond_to?(:detailed_message)
|
20
|
+
exception.detailed_message(highlight: false)
|
21
|
+
else
|
22
|
+
exception.message || ""
|
23
|
+
end
|
24
|
+
|
25
|
+
@value = exception_message.byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
|
26
|
+
|
19
27
|
@module = exception.class.to_s.split('::')[0...-1].join('::')
|
20
28
|
@thread_id = Thread.current.object_id
|
21
29
|
@stacktrace = stacktrace
|
data/lib/sentry/net/http.rb
CHANGED
@@ -26,14 +26,24 @@ module Sentry
|
|
26
26
|
#
|
27
27
|
# So we're only instrumenting request when `Net::HTTP` is already started
|
28
28
|
def request(req, body = nil, &block)
|
29
|
-
return super unless started?
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
return super unless started? && Sentry.initialized?
|
30
|
+
return super if from_sentry_sdk?
|
31
|
+
|
32
|
+
Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span|
|
33
|
+
set_sentry_trace_header(req, sentry_span)
|
34
|
+
|
35
|
+
super.tap do |res|
|
36
|
+
record_sentry_breadcrumb(req, res)
|
37
|
+
|
38
|
+
if sentry_span
|
39
|
+
request_info = extract_request_info(req)
|
40
|
+
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
41
|
+
sentry_span.set_data('url', request_info[:url])
|
42
|
+
sentry_span.set_data('http.method', request_info[:method])
|
43
|
+
sentry_span.set_data('http.query', request_info[:query]) if request_info[:query]
|
44
|
+
sentry_span.set_data('status', res.code.to_i)
|
45
|
+
end
|
46
|
+
end
|
37
47
|
end
|
38
48
|
end
|
39
49
|
|
@@ -53,7 +63,6 @@ module Sentry
|
|
53
63
|
|
54
64
|
def record_sentry_breadcrumb(req, res)
|
55
65
|
return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
|
56
|
-
return if from_sentry_sdk?
|
57
66
|
|
58
67
|
request_info = extract_request_info(req)
|
59
68
|
|
@@ -69,29 +78,6 @@ module Sentry
|
|
69
78
|
Sentry.add_breadcrumb(crumb)
|
70
79
|
end
|
71
80
|
|
72
|
-
def record_sentry_span(req, res, sentry_span)
|
73
|
-
return unless Sentry.initialized? && sentry_span
|
74
|
-
|
75
|
-
request_info = extract_request_info(req)
|
76
|
-
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
77
|
-
sentry_span.set_data(:status, res.code.to_i)
|
78
|
-
finish_sentry_span(sentry_span)
|
79
|
-
end
|
80
|
-
|
81
|
-
def start_sentry_span
|
82
|
-
return unless Sentry.initialized? && span = Sentry.get_current_scope.get_span
|
83
|
-
return if from_sentry_sdk?
|
84
|
-
return if span.sampled == false
|
85
|
-
|
86
|
-
span.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
|
87
|
-
end
|
88
|
-
|
89
|
-
def finish_sentry_span(sentry_span)
|
90
|
-
return unless Sentry.initialized? && sentry_span
|
91
|
-
|
92
|
-
sentry_span.set_timestamp(Sentry.utc_now.to_f)
|
93
|
-
end
|
94
|
-
|
95
81
|
def from_sentry_sdk?
|
96
82
|
dsn = Sentry.configuration.dsn
|
97
83
|
dsn && dsn.host == self.address
|
@@ -104,7 +90,7 @@ module Sentry
|
|
104
90
|
result = { method: req.method, url: url }
|
105
91
|
|
106
92
|
if Sentry.configuration.send_default_pii
|
107
|
-
result[:
|
93
|
+
result[:query] = uri.query
|
108
94
|
result[:body] = req.body
|
109
95
|
end
|
110
96
|
|
@@ -114,7 +100,4 @@ module Sentry
|
|
114
100
|
end
|
115
101
|
end
|
116
102
|
|
117
|
-
Sentry.register_patch
|
118
|
-
patch = Sentry::Net::HTTP
|
119
|
-
Net::HTTP.send(:prepend, patch) unless Net::HTTP.ancestors.include?(patch)
|
120
|
-
end
|
103
|
+
Sentry.register_patch(Sentry::Net::HTTP, Net::HTTP)
|