sentry-ruby-core 4.7.2 → 5.0.2
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/.yardopts +2 -0
- data/Gemfile +6 -2
- data/README.md +9 -7
- data/bin/console +5 -1
- data/lib/sentry/background_worker.rb +33 -3
- data/lib/sentry/backtrace.rb +1 -3
- data/lib/sentry/breadcrumb/sentry_logger.rb +2 -0
- data/lib/sentry/breadcrumb.rb +24 -3
- data/lib/sentry/breadcrumb_buffer.rb +16 -0
- data/lib/sentry/client.rb +49 -3
- data/lib/sentry/configuration.rb +139 -114
- 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 +26 -0
- data/lib/sentry/event.rb +58 -17
- data/lib/sentry/exceptions.rb +2 -0
- data/lib/sentry/hub.rb +16 -4
- data/lib/sentry/integrable.rb +2 -0
- data/lib/sentry/interface.rb +3 -10
- data/lib/sentry/interfaces/exception.rb +13 -3
- data/lib/sentry/interfaces/request.rb +34 -18
- data/lib/sentry/interfaces/single_exception.rb +31 -0
- data/lib/sentry/interfaces/stacktrace.rb +14 -0
- data/lib/sentry/interfaces/stacktrace_builder.rb +39 -10
- data/lib/sentry/interfaces/threads.rb +12 -2
- data/lib/sentry/linecache.rb +3 -0
- data/lib/sentry/net/http.rb +52 -64
- data/lib/sentry/rack/capture_exceptions.rb +2 -0
- data/lib/sentry/rack.rb +2 -0
- data/lib/sentry/rake.rb +16 -6
- data/lib/sentry/release_detector.rb +39 -0
- data/lib/sentry/scope.rb +75 -5
- data/lib/sentry/span.rb +84 -8
- data/lib/sentry/transaction.rb +48 -10
- data/lib/sentry/transaction_event.rb +8 -0
- data/lib/sentry/transport/configuration.rb +3 -2
- data/lib/sentry/transport/dummy_transport.rb +2 -0
- data/lib/sentry/transport/http_transport.rb +55 -42
- data/lib/sentry/transport.rb +80 -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 +6 -4
- 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 +142 -29
- data/sentry-ruby-core.gemspec +0 -1
- data/sentry-ruby.gemspec +0 -1
- metadata +6 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f6a137330d349e7d0cfa5535bdf80f940266df9e01b4f134df6a49c475724fa
|
4
|
+
data.tar.gz: 27d2fd1c95d69dc1cf6b01a2ca6c9c6e58fcaf2cba2a76706b6a26fe323f4599
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6f8a78bd9bdb89ca6f710a036e1e4917891968e1de929da024dbebc12a5d86642a51e367b329b6a1c9f6c670af47d5bad0a8fd15804c3511f33edd5333ae789
|
7
|
+
data.tar.gz: '0559dd91dcdb831e132d5e74d0680cdedbb3e07c83b1f3129e635eb868bc8fb5a84e27813276058d436709543ec45f602f3f89ababec9295b1b0208292ee77c7'
|
data/.yardopts
ADDED
data/Gemfile
CHANGED
@@ -10,13 +10,17 @@ 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"
|
20
22
|
gem "benchmark_driver"
|
21
23
|
gem "benchmark-ipsa"
|
22
24
|
gem "benchmark-memory"
|
25
|
+
|
26
|
+
gem "yard", "~> 0.9.27"
|
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
|
|
@@ -78,6 +78,8 @@ end
|
|
78
78
|
|
79
79
|
To learn more about sampling transactions, please visit the [official documentation](https://docs.sentry.io/platforms/ruby/configuration/sampling/#configuring-the-transaction-sample-rate).
|
80
80
|
|
81
|
+
### [Migration Guide](https://docs.sentry.io/platforms/ruby/migration/)
|
82
|
+
|
81
83
|
### Integrations
|
82
84
|
|
83
85
|
- [Rack](https://docs.sentry.io/platforms/ruby/guides/rack/)
|
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"
|
@@ -6,12 +8,18 @@ module Sentry
|
|
6
8
|
class BackgroundWorker
|
7
9
|
include LoggingHelper
|
8
10
|
|
9
|
-
attr_reader :max_queue, :number_of_threads
|
11
|
+
attr_reader :max_queue, :number_of_threads
|
12
|
+
# @deprecated Use Sentry.logger to retrieve the current logger instead.
|
13
|
+
attr_reader :logger
|
14
|
+
attr_accessor :shutdown_timeout
|
10
15
|
|
11
16
|
def initialize(configuration)
|
12
17
|
@max_queue = 30
|
18
|
+
@shutdown_timeout = 1
|
13
19
|
@number_of_threads = configuration.background_worker_threads
|
14
20
|
@logger = configuration.logger
|
21
|
+
@debug = configuration.debug
|
22
|
+
@shutdown_callback = nil
|
15
23
|
|
16
24
|
@executor =
|
17
25
|
if configuration.async
|
@@ -23,19 +31,41 @@ module Sentry
|
|
23
31
|
else
|
24
32
|
log_debug("initialized a background worker with #{@number_of_threads} threads")
|
25
33
|
|
26
|
-
Concurrent::ThreadPoolExecutor.new(
|
34
|
+
executor = Concurrent::ThreadPoolExecutor.new(
|
27
35
|
min_threads: 0,
|
28
36
|
max_threads: @number_of_threads,
|
29
37
|
max_queue: @max_queue,
|
30
38
|
fallback_policy: :discard
|
31
39
|
)
|
40
|
+
|
41
|
+
@shutdown_callback = proc do
|
42
|
+
executor.shutdown
|
43
|
+
executor.wait_for_termination(@shutdown_timeout)
|
44
|
+
end
|
45
|
+
|
46
|
+
executor
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
50
|
+
# if you want to monkey-patch this method, please override `_perform` instead
|
35
51
|
def perform(&block)
|
36
52
|
@executor.post do
|
37
|
-
|
53
|
+
begin
|
54
|
+
_perform(&block)
|
55
|
+
rescue Exception => e
|
56
|
+
log_error("exception happened in background worker", e, debug: @debug)
|
57
|
+
end
|
38
58
|
end
|
39
59
|
end
|
60
|
+
|
61
|
+
def shutdown
|
62
|
+
@shutdown_callback&.call
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def _perform(&block)
|
68
|
+
block.call
|
69
|
+
end
|
40
70
|
end
|
41
71
|
end
|
data/lib/sentry/backtrace.rb
CHANGED
data/lib/sentry/breadcrumb.rb
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
class Breadcrumb
|
3
5
|
DATA_SERIALIZATION_ERROR_MESSAGE = "[data were removed due to serialization issues]"
|
4
6
|
|
5
|
-
|
7
|
+
# @return [String, nil]
|
8
|
+
attr_accessor :category
|
9
|
+
# @return [Hash, nil]
|
10
|
+
attr_accessor :data
|
11
|
+
# @return [String, nil]
|
12
|
+
attr_accessor :level
|
13
|
+
# @return [Time, Integer, nil]
|
14
|
+
attr_accessor :timestamp
|
15
|
+
# @return [String, nil]
|
16
|
+
attr_accessor :type
|
17
|
+
# @return [String, nil]
|
6
18
|
attr_reader :message
|
7
19
|
|
20
|
+
# @param category [String, nil]
|
21
|
+
# @param data [Hash, nil]
|
22
|
+
# @param message [String, nil]
|
23
|
+
# @param timestamp [Time, Integer, nil]
|
24
|
+
# @param level [String, nil]
|
25
|
+
# @param type [String, nil]
|
8
26
|
def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
|
9
27
|
@category = category
|
10
28
|
@data = data || {}
|
@@ -14,6 +32,7 @@ module Sentry
|
|
14
32
|
self.message = message
|
15
33
|
end
|
16
34
|
|
35
|
+
# @return [Hash]
|
17
36
|
def to_hash
|
18
37
|
{
|
19
38
|
category: @category,
|
@@ -25,8 +44,10 @@ module Sentry
|
|
25
44
|
}
|
26
45
|
end
|
27
46
|
|
28
|
-
|
29
|
-
|
47
|
+
# @param message [String]
|
48
|
+
# @return [void]
|
49
|
+
def message=(message)
|
50
|
+
@message = (message || "").byteslice(0..Event::MAX_MESSAGE_SIZE_IN_BYTES)
|
30
51
|
end
|
31
52
|
|
32
53
|
private
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/breadcrumb"
|
2
4
|
|
3
5
|
module Sentry
|
@@ -5,40 +7,54 @@ module Sentry
|
|
5
7
|
DEFAULT_SIZE = 100
|
6
8
|
include Enumerable
|
7
9
|
|
10
|
+
# @return [Array]
|
8
11
|
attr_accessor :buffer
|
9
12
|
|
13
|
+
# @param size [Integer, nil] If it's not provided, it'll fallback to DEFAULT_SIZE
|
10
14
|
def initialize(size = nil)
|
11
15
|
@buffer = Array.new(size || DEFAULT_SIZE)
|
12
16
|
end
|
13
17
|
|
18
|
+
# @param crumb [Breadcrumb]
|
19
|
+
# @return [void]
|
14
20
|
def record(crumb)
|
15
21
|
yield(crumb) if block_given?
|
16
22
|
@buffer.slice!(0)
|
17
23
|
@buffer << crumb
|
18
24
|
end
|
19
25
|
|
26
|
+
# @return [Array]
|
20
27
|
def members
|
21
28
|
@buffer.compact
|
22
29
|
end
|
23
30
|
|
31
|
+
# Returns the last breadcrumb stored in the buffer. If the buffer it's empty, it returns nil.
|
32
|
+
# @return [Breadcrumb, nil]
|
24
33
|
def peek
|
25
34
|
members.last
|
26
35
|
end
|
27
36
|
|
37
|
+
# Iterates through all breadcrumbs.
|
38
|
+
# @param block [Proc]
|
39
|
+
# @yieldparam crumb [Breadcrumb]
|
40
|
+
# @return [Array]
|
28
41
|
def each(&block)
|
29
42
|
members.each(&block)
|
30
43
|
end
|
31
44
|
|
45
|
+
# @return [Boolean]
|
32
46
|
def empty?
|
33
47
|
members.none?
|
34
48
|
end
|
35
49
|
|
50
|
+
# @return [Hash]
|
36
51
|
def to_hash
|
37
52
|
{
|
38
53
|
values: members.map(&:to_hash)
|
39
54
|
}
|
40
55
|
end
|
41
56
|
|
57
|
+
# @return [BreadcrumbBuffer]
|
42
58
|
def dup
|
43
59
|
copy = super
|
44
60
|
copy.buffer = buffer.deep_dup
|
data/lib/sentry/client.rb
CHANGED
@@ -1,11 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/transport"
|
2
4
|
|
3
5
|
module Sentry
|
4
6
|
class Client
|
5
7
|
include LoggingHelper
|
6
8
|
|
7
|
-
|
9
|
+
# The Transport object that'll send events for the client.
|
10
|
+
# @return [Transport]
|
11
|
+
attr_reader :transport
|
12
|
+
|
13
|
+
# @!macro configuration
|
14
|
+
attr_reader :configuration
|
15
|
+
|
16
|
+
# @deprecated Use Sentry.logger to retrieve the current logger instead.
|
17
|
+
attr_reader :logger
|
8
18
|
|
19
|
+
# @param configuration [Configuration]
|
9
20
|
def initialize(configuration)
|
10
21
|
@configuration = configuration
|
11
22
|
@logger = configuration.logger
|
@@ -23,20 +34,33 @@ module Sentry
|
|
23
34
|
end
|
24
35
|
end
|
25
36
|
|
37
|
+
# Applies the given scope's data to the event and sends it to Sentry.
|
38
|
+
# @param event [Event] the event to be sent.
|
39
|
+
# @param scope [Scope] the scope with contextual data that'll be applied to the event before it's sent.
|
40
|
+
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
41
|
+
# @return [Event, nil]
|
26
42
|
def capture_event(event, scope, hint = {})
|
27
43
|
return unless configuration.sending_allowed?
|
28
44
|
|
45
|
+
unless event.is_a?(TransactionEvent) || configuration.sample_allowed?
|
46
|
+
transport.record_lost_event(:sample_rate, 'event')
|
47
|
+
return
|
48
|
+
end
|
49
|
+
|
50
|
+
event_type = event.is_a?(Event) ? event.type : event["type"]
|
29
51
|
event = scope.apply_to_event(event, hint)
|
30
52
|
|
31
53
|
if event.nil?
|
32
54
|
log_info("Discarded event because one of the event processors returned nil")
|
55
|
+
transport.record_lost_event(:event_processor, event_type)
|
33
56
|
return
|
34
57
|
end
|
35
58
|
|
36
59
|
if async_block = configuration.async
|
37
60
|
dispatch_async_event(async_block, event, hint)
|
38
61
|
elsif configuration.background_worker_threads != 0 && hint.fetch(:background, true)
|
39
|
-
dispatch_background_event(event, hint)
|
62
|
+
queued = dispatch_background_event(event, hint)
|
63
|
+
transport.record_lost_event(:queue_overflow, event_type) unless queued
|
40
64
|
else
|
41
65
|
send_event(event, hint)
|
42
66
|
end
|
@@ -47,9 +71,14 @@ module Sentry
|
|
47
71
|
nil
|
48
72
|
end
|
49
73
|
|
74
|
+
# Initializes an Event object with the given exception. Returns `nil` if the exception's class is excluded from reporting.
|
75
|
+
# @param exception [Exception] the exception to be reported.
|
76
|
+
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
77
|
+
# @return [Event, nil]
|
50
78
|
def event_from_exception(exception, hint = {})
|
79
|
+
return unless @configuration.sending_allowed? && @configuration.exception_class_allowed?(exception)
|
80
|
+
|
51
81
|
integration_meta = Sentry.integrations[hint[:integration]]
|
52
|
-
return unless @configuration.exception_class_allowed?(exception)
|
53
82
|
|
54
83
|
Event.new(configuration: configuration, integration_meta: integration_meta).tap do |event|
|
55
84
|
event.add_exception_interface(exception)
|
@@ -57,25 +86,36 @@ module Sentry
|
|
57
86
|
end
|
58
87
|
end
|
59
88
|
|
89
|
+
# Initializes an Event object with the given message.
|
90
|
+
# @param message [String] the message to be reported.
|
91
|
+
# @param hint [Hash] the hint data that'll be passed to `before_send` callback and the scope's event processors.
|
92
|
+
# @return [Event]
|
60
93
|
def event_from_message(message, hint = {}, backtrace: nil)
|
94
|
+
return unless @configuration.sending_allowed?
|
95
|
+
|
61
96
|
integration_meta = Sentry.integrations[hint[:integration]]
|
62
97
|
event = Event.new(configuration: configuration, integration_meta: integration_meta, message: message)
|
63
98
|
event.add_threads_interface(backtrace: backtrace || caller)
|
64
99
|
event
|
65
100
|
end
|
66
101
|
|
102
|
+
# Initializes an Event object with the given Transaction object.
|
103
|
+
# @param transaction [Transaction] the transaction to be recorded.
|
104
|
+
# @return [TransactionEvent]
|
67
105
|
def event_from_transaction(transaction)
|
68
106
|
TransactionEvent.new(configuration: configuration).tap do |event|
|
69
107
|
event.transaction = transaction.name
|
70
108
|
event.contexts.merge!(trace: transaction.get_trace_context)
|
71
109
|
event.timestamp = transaction.timestamp
|
72
110
|
event.start_timestamp = transaction.start_timestamp
|
111
|
+
event.tags = transaction.tags
|
73
112
|
|
74
113
|
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
|
75
114
|
event.spans = finished_spans.map(&:to_hash)
|
76
115
|
end
|
77
116
|
end
|
78
117
|
|
118
|
+
# @!macro send_event
|
79
119
|
def send_event(event, hint = nil)
|
80
120
|
event_type = event.is_a?(Event) ? event.type : event["type"]
|
81
121
|
|
@@ -84,6 +124,7 @@ module Sentry
|
|
84
124
|
|
85
125
|
if event.nil?
|
86
126
|
log_info("Discarded event because before_send returned nil")
|
127
|
+
transport.record_lost_event(:before_send, 'event')
|
87
128
|
return
|
88
129
|
end
|
89
130
|
end
|
@@ -97,9 +138,14 @@ module Sentry
|
|
97
138
|
|
98
139
|
event_info = Event.get_log_message(event.to_hash)
|
99
140
|
log_info("Unreported #{loggable_event_type}: #{event_info}")
|
141
|
+
transport.record_lost_event(:network_error, event_type)
|
100
142
|
raise
|
101
143
|
end
|
102
144
|
|
145
|
+
# Generates a Sentry trace for distribted tracing from the given Span.
|
146
|
+
# Returns `nil` if `config.propagate_traces` is `false`.
|
147
|
+
# @param span [Span] the span to generate trace from.
|
148
|
+
# @return [String, nil]
|
103
149
|
def generate_sentry_trace(span)
|
104
150
|
return unless configuration.propagate_traces
|
105
151
|
|