sentry-ruby 5.4.2 → 5.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 310e7ac901b3da90fb400710f95be183627b1e35587f059810669469deb27763
4
- data.tar.gz: 75cff84d0f7238ac444b5f6ce0a67f0150daefa38d9bac9e2b083a6f98ecff6e
3
+ metadata.gz: 2373a9b8990fd62763c4d1b26001f953f95efdd8b51f803e5d59bdb1ba984e3e
4
+ data.tar.gz: d09371eb4bf3aaff6e7735f74cd5887b2e99f636a60f1dca3cf653bbb8ba9bb4
5
5
  SHA512:
6
- metadata.gz: 76251bc9b7499bc40b30c1e20c3b638a3cc5bf0a3c5df9f5210fa2b2293a3ee7e6c8c7a1d3073b1055c8788855531c36ece0517ea38e203367c0c8bf6842e130
7
- data.tar.gz: cc3b7a551b8d8c798c5843b895710244857bcf110e57cc4dd1de345e7fe6e09201bf3adf3e4645d9101df201cab8ce4cda0b547b88d137ef1faab8e7a6f1693f
6
+ metadata.gz: 4799b727ddaab0622be00e73b58a2e3f723779e1b46c7d5007d5711a8897022190ff9f87cc90df7411f32fd6b59d4f4637bcf26cc7eba8484cb04429871e9242
7
+ data.tar.gz: d97d9272ee815447ebdcbb72adb4e2255584475547e7878ed6c7af4f312d170bd37f3029acaaa6866eb04f2d89c1581c4854b849c2d57a1a51eb4b67e4ebeb0e
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --format documentation
2
2
  --color
3
- --require spec_helper
data/Gemfile CHANGED
@@ -3,20 +3,29 @@ git_source(:github) { |name| "https://github.com/#{name}.git" }
3
3
 
4
4
  gem "sentry-ruby", path: "./"
5
5
 
6
- gem "rack" unless ENV["WITHOUT_RACK"] == "1"
6
+ rack_version = ENV["RACK_VERSION"]
7
+ rack_version = "3.0.0" if rack_version.nil?
8
+ gem "rack", "~> #{Gem::Version.new(rack_version)}" unless rack_version == "0"
9
+
10
+ redis_rb_version = ENV.fetch("REDIS_RB_VERSION", "5.0")
11
+ gem "redis", "~> #{redis_rb_version}"
12
+
13
+ gem "puma"
7
14
 
8
15
  gem "rake", "~> 12.0"
9
16
  gem "rspec", "~> 3.0"
10
17
  gem "rspec-retry"
11
- gem "webmock"
12
- gem "fakeredis"
13
18
  gem "timecop"
14
- gem 'simplecov'
19
+ gem "simplecov"
15
20
  gem "simplecov-cobertura", "~> 1.4"
16
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
17
28
 
18
- gem "object_tracer"
19
- gem "debug", github: "ruby/debug", platform: :ruby if RUBY_VERSION.to_f >= 2.6
20
29
  gem "pry"
21
30
 
22
31
  gem "benchmark-ips"
@@ -24,4 +33,5 @@ gem "benchmark_driver"
24
33
  gem "benchmark-ipsa"
25
34
  gem "benchmark-memory"
26
35
 
27
- gem "yard", "~> 0.9.27"
36
+ gem "yard", github: "lsegal/yard"
37
+ gem "webrick"
data/README.md CHANGED
@@ -20,6 +20,7 @@ Sentry SDK for Ruby
20
20
  | [![Gem Version](https://img.shields.io/gem/v/sentry-sidekiq?label=sentry-sidekiq)](https://rubygems.org/gems/sentry-sidekiq) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-sidekiq%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_sidekiq_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-sidekiq.svg)](https://rubygems.org/gems/sentry-sidekiq/) |
21
21
  | [![Gem Version](https://img.shields.io/gem/v/sentry-delayed_job?label=sentry-delayed_job)](https://rubygems.org/gems/sentry-delayed_job) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-delayed_job%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_delayed_job_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-delayed_job.svg)](https://rubygems.org/gems/sentry-delayed_job/) |
22
22
  | [![Gem Version](https://img.shields.io/gem/v/sentry-resque?label=sentry-resque)](https://rubygems.org/gems/sentry-resque) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-resque%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_resque_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-resque.svg)](https://rubygems.org/gems/sentry-resque/) |
23
+ | [![Gem Version](https://img.shields.io/gem/v/sentry-opentelemetry?label=sentry-opentelemetry)](https://rubygems.org/gems/sentry-opentelemetry) | [![Build Status](https://github.com/getsentry/sentry-ruby/workflows/sentry-opentelemetry%20Test/badge.svg)](https://github.com/getsentry/sentry-ruby/actions/workflows/sentry_opentelemetry_test.yml) | [![Coverage Status](https://img.shields.io/codecov/c/github/getsentry/sentry-ruby/master?logo=codecov)](https://codecov.io/gh/getsentry/sentry-ruby/branch/master) | [![Downloads](https://img.shields.io/gem/dt/sentry-opentelemetry.svg)](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 :default => :spec
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]
@@ -76,7 +76,7 @@ module Sentry
76
76
  end
77
77
  end
78
78
 
79
- APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
79
+ APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test|spec)/.freeze
80
80
 
81
81
  # holder for an Array of Backtrace::Line instances
82
82
  attr_reader :lines
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ module Sentry
6
+ # A {https://www.w3.org/TR/baggage W3C Baggage Header} implementation.
7
+ class Baggage
8
+ SENTRY_PREFIX = 'sentry-'
9
+ SENTRY_PREFIX_REGEX = /^sentry-/.freeze
10
+
11
+ # @return [Hash]
12
+ attr_reader :items
13
+
14
+ # @return [Boolean]
15
+ attr_reader :mutable
16
+
17
+ def initialize(items, mutable: true)
18
+ @items = items
19
+ @mutable = mutable
20
+ end
21
+
22
+ # Creates a Baggage object from an incoming W3C Baggage header string.
23
+ #
24
+ # Sentry items are identified with the 'sentry-' prefix and stored in a hash.
25
+ # The presence of a Sentry item makes the baggage object immutable.
26
+ #
27
+ # @param header [String] The incoming Baggage header string.
28
+ # @return [Baggage, nil]
29
+ def self.from_incoming_header(header)
30
+ items = {}
31
+ mutable = true
32
+
33
+ header.split(',').each do |item|
34
+ item = item.strip
35
+ key, val = item.split('=')
36
+
37
+ next unless key && val
38
+ next unless key =~ SENTRY_PREFIX_REGEX
39
+
40
+ baggage_key = key.split('-')[1]
41
+ next unless baggage_key
42
+
43
+ items[CGI.unescape(baggage_key)] = CGI.unescape(val)
44
+ mutable = false
45
+ end
46
+
47
+ new(items, mutable: mutable)
48
+ end
49
+
50
+ # Make the Baggage immutable.
51
+ # @return [void]
52
+ def freeze!
53
+ @mutable = false
54
+ end
55
+
56
+ # A {https://develop.sentry.dev/sdk/performance/dynamic-sampling-context/#envelope-header Dynamic Sampling Context}
57
+ # hash to be used in the trace envelope header.
58
+ # @return [Hash]
59
+ def dynamic_sampling_context
60
+ @items
61
+ end
62
+
63
+ # Serialize the Baggage object back to a string.
64
+ # @return [String]
65
+ def serialize
66
+ items = @items.map { |k, v| "#{SENTRY_PREFIX}#{CGI.escape(k)}=#{CGI.escape(v)}" }
67
+ items.join(',')
68
+ end
69
+ end
70
+ end
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? && @configuration.exception_class_allowed?(exception)
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
 
@@ -105,16 +108,7 @@ module Sentry
105
108
  # @param transaction [Transaction] the transaction to be recorded.
106
109
  # @return [TransactionEvent]
107
110
  def event_from_transaction(transaction)
108
- TransactionEvent.new(configuration: configuration).tap do |event|
109
- event.transaction = transaction.name
110
- event.contexts.merge!(trace: transaction.get_trace_context)
111
- event.timestamp = transaction.timestamp
112
- event.start_timestamp = transaction.start_timestamp
113
- event.tags = transaction.tags
114
-
115
- finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
116
- event.spans = finished_spans.map(&:to_hash)
117
- end
111
+ TransactionEvent.new(configuration: configuration, transaction: transaction)
118
112
  end
119
113
 
120
114
  # @!macro send_event
@@ -131,6 +125,16 @@ module Sentry
131
125
  end
132
126
  end
133
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
+
134
138
  transport.send_event(event)
135
139
 
136
140
  event
@@ -156,6 +160,22 @@ module Sentry
156
160
  trace
157
161
  end
158
162
 
163
+ # Generates a W3C Baggage header for distribted tracing from the given Span.
164
+ # Returns `nil` if `config.propagate_traces` is `false`.
165
+ # @param span [Span] the span to generate trace from.
166
+ # @return [String, nil]
167
+ def generate_baggage(span)
168
+ return unless configuration.propagate_traces
169
+
170
+ baggage = span.to_baggage
171
+
172
+ if baggage && !baggage.empty?
173
+ log_debug("[Tracing] Adding #{BAGGAGE_HEADER_NAME} header to outgoing request: #{baggage}")
174
+ end
175
+
176
+ baggage
177
+ end
178
+
159
179
  private
160
180
 
161
181
  def dispatch_background_event(event, hint)
@@ -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
- attr_accessor :release
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
- attr_accessor :traces_sample_rate
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
- # Post initialization callbacks are called at the end of initialization process
241
- # allowing extending the configuration of sentry-ruby by multiple extensions
242
- @@post_initialization_callbacks = []
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.capture_exception_frame_locals = false
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.dup
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 && @traces_sample_rate >= 0.0 && @traces_sample_rate <= 1.0) || @traces_sampler) && sending_allowed?
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
- self.release ||= ReleaseDetector.detect_release(project_root: project_root, running_on_heroku: running_on_heroku?)
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
@@ -19,10 +19,7 @@ module Sentry
19
19
  end
20
20
 
21
21
  def to_s
22
- <<~ITEM
23
- #{JSON.generate(@headers)}
24
- #{JSON.generate(@payload)}
25
- ITEM
22
+ [JSON.generate(@headers), JSON.generate(@payload)].join("\n")
26
23
  end
27
24
 
28
25
  def serialize
data/lib/sentry/event.rb CHANGED
@@ -18,7 +18,7 @@ module Sentry
18
18
  event_id level timestamp
19
19
  release environment server_name modules
20
20
  message user tags contexts extra
21
- fingerprint breadcrumbs transaction
21
+ fingerprint breadcrumbs transaction transaction_info
22
22
  platform sdk type
23
23
  )
24
24
 
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
- check_argument_type!(exception, ::Exception)
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,31 +105,21 @@ 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
123
111
  !(key.start_with?('HTTP_') || CONTENT_HEADERS.include?(key))
124
112
  end
125
113
 
126
- # Rack adds in an incorrect HTTP_VERSION key, which causes downstream
114
+ # In versions < 3, Rack adds in an incorrect HTTP_VERSION key, which causes downstream
127
115
  # to think this is a Version header. Instead, this is mapped to
128
116
  # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
129
117
  # if the request has legitimately sent a Version header themselves.
130
118
  # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
131
- # NOTE: This will be removed in version 3.0+
132
119
  def is_server_protocol?(key, value, protocol_version)
120
+ rack_version = Gem::Version.new(::Rack.release)
121
+ return false if rack_version >= Gem::Version.new("3.0")
122
+
133
123
  key == 'HTTP_VERSION' && value == protocol_version
134
124
  end
135
125