sentry-ruby-core 5.4.2 → 5.5.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/Gemfile +3 -2
- data/lib/sentry/baggage.rb +81 -0
- data/lib/sentry/client.rb +17 -10
- data/lib/sentry/event.rb +1 -1
- data/lib/sentry/interfaces/request.rb +4 -2
- data/lib/sentry/net/http.rb +6 -1
- data/lib/sentry/rack/capture_exceptions.rb +5 -3
- data/lib/sentry/rake.rb +1 -1
- data/lib/sentry/scope.rb +29 -3
- data/lib/sentry/session.rb +5 -7
- data/lib/sentry/span.rb +7 -0
- data/lib/sentry/test_helper.rb +2 -0
- data/lib/sentry/transaction.rb +102 -6
- data/lib/sentry/transaction_event.rb +18 -0
- data/lib/sentry/transport.rb +12 -8
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +3 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db4ea8b565496ba29fe0e5eae4c3f86a68ac789ab05c036153183dc3638b0465
|
4
|
+
data.tar.gz: 5c11d4679189282fba1da3ae2a78744b25391a1f3f174ea29b51fbdbee994bf9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd0a1a54f07adb2ea7b5d029423b2bb9c44bb79342cb2b3c0fa367e0aec90c4b4cac822234223c947bfce783260b7e844957b16ab81a7db2ad1542be37cc6de8
|
7
|
+
data.tar.gz: 91b8e37e42991183ea66d8d7e71ce33b9051d094059327b0e972159052a580c05cccb553615ca76410b7bef3426fd8989af338478d6ab890f2648681f855a270
|
data/Gemfile
CHANGED
@@ -3,12 +3,13 @@ git_source(:github) { |name| "https://github.com/#{name}.git" }
|
|
3
3
|
|
4
4
|
gem "sentry-ruby", path: "./"
|
5
5
|
|
6
|
-
|
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"
|
7
9
|
|
8
10
|
gem "rake", "~> 12.0"
|
9
11
|
gem "rspec", "~> 3.0"
|
10
12
|
gem "rspec-retry"
|
11
|
-
gem "webmock"
|
12
13
|
gem "fakeredis"
|
13
14
|
gem "timecop"
|
14
15
|
gem 'simplecov'
|
@@ -0,0 +1,81 @@
|
|
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
|
+
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
|
+
# @return [Hash]
|
23
|
+
attr_reader :items
|
24
|
+
|
25
|
+
# @return [Boolean]
|
26
|
+
attr_reader :mutable
|
27
|
+
|
28
|
+
def initialize(items, mutable: true)
|
29
|
+
@items = items
|
30
|
+
@mutable = mutable
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates a Baggage object from an incoming W3C Baggage header string.
|
34
|
+
#
|
35
|
+
# Sentry items are identified with the 'sentry-' prefix and stored in a hash.
|
36
|
+
# The presence of a Sentry item makes the baggage object immutable.
|
37
|
+
#
|
38
|
+
# @param header [String] The incoming Baggage header string.
|
39
|
+
# @return [Baggage, nil]
|
40
|
+
def self.from_incoming_header(header)
|
41
|
+
items = {}
|
42
|
+
mutable = true
|
43
|
+
|
44
|
+
header.split(',').each do |item|
|
45
|
+
item = item.strip
|
46
|
+
key, val = item.split('=')
|
47
|
+
|
48
|
+
next unless key && val
|
49
|
+
next unless key =~ SENTRY_PREFIX_REGEX
|
50
|
+
|
51
|
+
baggage_key = key.split('-')[1]
|
52
|
+
next unless baggage_key
|
53
|
+
|
54
|
+
items[CGI.unescape(baggage_key)] = CGI.unescape(val)
|
55
|
+
mutable = false
|
56
|
+
end
|
57
|
+
|
58
|
+
new(items, mutable: mutable)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Make the Baggage immutable.
|
62
|
+
# @return [void]
|
63
|
+
def freeze!
|
64
|
+
@mutable = false
|
65
|
+
end
|
66
|
+
|
67
|
+
# A {https://develop.sentry.dev/sdk/performance/dynamic-sampling-context/#envelope-header Dynamic Sampling Context}
|
68
|
+
# hash to be used in the trace envelope header.
|
69
|
+
# @return [Hash]
|
70
|
+
def dynamic_sampling_context
|
71
|
+
@items.select { |k, _v| DSC_KEYS.include?(k) }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Serialize the Baggage object back to a string.
|
75
|
+
# @return [String]
|
76
|
+
def serialize
|
77
|
+
items = @items.map { |k, v| "#{SENTRY_PREFIX}#{CGI.escape(k)}=#{CGI.escape(v)}" }
|
78
|
+
items.join(',')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/sentry/client.rb
CHANGED
@@ -105,16 +105,7 @@ module Sentry
|
|
105
105
|
# @param transaction [Transaction] the transaction to be recorded.
|
106
106
|
# @return [TransactionEvent]
|
107
107
|
def event_from_transaction(transaction)
|
108
|
-
TransactionEvent.new(configuration: configuration
|
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
|
108
|
+
TransactionEvent.new(configuration: configuration, transaction: transaction)
|
118
109
|
end
|
119
110
|
|
120
111
|
# @!macro send_event
|
@@ -156,6 +147,22 @@ module Sentry
|
|
156
147
|
trace
|
157
148
|
end
|
158
149
|
|
150
|
+
# Generates a W3C Baggage header for distribted tracing from the given Span.
|
151
|
+
# Returns `nil` if `config.propagate_traces` is `false`.
|
152
|
+
# @param span [Span] the span to generate trace from.
|
153
|
+
# @return [String, nil]
|
154
|
+
def generate_baggage(span)
|
155
|
+
return unless configuration.propagate_traces
|
156
|
+
|
157
|
+
baggage = span.to_baggage
|
158
|
+
|
159
|
+
if baggage && !baggage.empty?
|
160
|
+
log_debug("[Tracing] Adding #{BAGGAGE_HEADER_NAME} header to outgoing request: #{baggage}")
|
161
|
+
end
|
162
|
+
|
163
|
+
baggage
|
164
|
+
end
|
165
|
+
|
159
166
|
private
|
160
167
|
|
161
168
|
def dispatch_background_event(event, hint)
|
data/lib/sentry/event.rb
CHANGED
@@ -123,13 +123,15 @@ module Sentry
|
|
123
123
|
!(key.start_with?('HTTP_') || CONTENT_HEADERS.include?(key))
|
124
124
|
end
|
125
125
|
|
126
|
-
# Rack adds in an incorrect HTTP_VERSION key, which causes downstream
|
126
|
+
# In versions < 3, Rack adds in an incorrect HTTP_VERSION key, which causes downstream
|
127
127
|
# to think this is a Version header. Instead, this is mapped to
|
128
128
|
# env['SERVER_PROTOCOL']. But we don't want to ignore a valid header
|
129
129
|
# if the request has legitimately sent a Version header themselves.
|
130
130
|
# 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
131
|
def is_server_protocol?(key, value, protocol_version)
|
132
|
+
rack_version = Gem::Version.new(::Rack.release)
|
133
|
+
return false if rack_version >= Gem::Version.new("3.0")
|
134
|
+
|
133
135
|
key == 'HTTP_VERSION' && value == protocol_version
|
134
136
|
end
|
135
137
|
|
data/lib/sentry/net/http.rb
CHANGED
@@ -42,8 +42,13 @@ module Sentry
|
|
42
42
|
def set_sentry_trace_header(req, sentry_span)
|
43
43
|
return unless sentry_span
|
44
44
|
|
45
|
-
|
45
|
+
client = Sentry.get_current_client
|
46
|
+
|
47
|
+
trace = client.generate_sentry_trace(sentry_span)
|
46
48
|
req[SENTRY_TRACE_HEADER_NAME] = trace if trace
|
49
|
+
|
50
|
+
baggage = client.generate_baggage(sentry_span)
|
51
|
+
req[BAGGAGE_HEADER_NAME] = baggage if baggage && !baggage.empty?
|
47
52
|
end
|
48
53
|
|
49
54
|
def record_sentry_breadcrumb(req, res)
|
@@ -18,7 +18,7 @@ module Sentry
|
|
18
18
|
Sentry.with_scope do |scope|
|
19
19
|
Sentry.with_session_tracking do
|
20
20
|
scope.clear_breadcrumbs
|
21
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
21
|
+
scope.set_transaction_name(env["PATH_INFO"], source: :url) if env["PATH_INFO"]
|
22
22
|
scope.set_rack_env(env)
|
23
23
|
|
24
24
|
transaction = start_transaction(env, scope)
|
@@ -63,8 +63,10 @@ module Sentry
|
|
63
63
|
|
64
64
|
def start_transaction(env, scope)
|
65
65
|
sentry_trace = env["HTTP_SENTRY_TRACE"]
|
66
|
-
|
67
|
-
|
66
|
+
baggage = env["HTTP_BAGGAGE"]
|
67
|
+
|
68
|
+
options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
|
69
|
+
transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, baggage: baggage, **options) if sentry_trace
|
68
70
|
Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
69
71
|
end
|
70
72
|
|
data/lib/sentry/rake.rb
CHANGED
@@ -10,7 +10,7 @@ module Sentry
|
|
10
10
|
def display_error_message(ex)
|
11
11
|
Sentry.capture_exception(ex) do |scope|
|
12
12
|
task_name = top_level_tasks.join(' ')
|
13
|
-
scope.set_transaction_name(task_name)
|
13
|
+
scope.set_transaction_name(task_name, source: :task)
|
14
14
|
scope.set_tag("rake_task", task_name)
|
15
15
|
end if Sentry.initialized? && !Sentry.configuration.skip_rake_integration
|
16
16
|
|
data/lib/sentry/scope.rb
CHANGED
@@ -7,7 +7,21 @@ module Sentry
|
|
7
7
|
class Scope
|
8
8
|
include ArgumentCheckingHelper
|
9
9
|
|
10
|
-
ATTRIBUTES = [
|
10
|
+
ATTRIBUTES = [
|
11
|
+
:transaction_names,
|
12
|
+
:transaction_sources,
|
13
|
+
:contexts,
|
14
|
+
:extra,
|
15
|
+
:tags,
|
16
|
+
:user,
|
17
|
+
:level,
|
18
|
+
:breadcrumbs,
|
19
|
+
:fingerprint,
|
20
|
+
:event_processors,
|
21
|
+
:rack_env,
|
22
|
+
:span,
|
23
|
+
:session
|
24
|
+
]
|
11
25
|
|
12
26
|
attr_reader(*ATTRIBUTES)
|
13
27
|
|
@@ -33,6 +47,7 @@ module Sentry
|
|
33
47
|
event.extra = extra.merge(event.extra)
|
34
48
|
event.contexts = contexts.merge(event.contexts)
|
35
49
|
event.transaction = transaction_name if transaction_name
|
50
|
+
event.transaction_info = { source: transaction_source } if transaction_source
|
36
51
|
|
37
52
|
if span
|
38
53
|
event.contexts[:trace] = span.get_trace_context
|
@@ -73,7 +88,8 @@ module Sentry
|
|
73
88
|
copy.extra = extra.deep_dup
|
74
89
|
copy.tags = tags.deep_dup
|
75
90
|
copy.user = user.deep_dup
|
76
|
-
copy.transaction_names = transaction_names.
|
91
|
+
copy.transaction_names = transaction_names.dup
|
92
|
+
copy.transaction_sources = transaction_sources.dup
|
77
93
|
copy.fingerprint = fingerprint.deep_dup
|
78
94
|
copy.span = span.deep_dup
|
79
95
|
copy.session = session.deep_dup
|
@@ -90,6 +106,7 @@ module Sentry
|
|
90
106
|
self.tags = scope.tags
|
91
107
|
self.user = scope.user
|
92
108
|
self.transaction_names = scope.transaction_names
|
109
|
+
self.transaction_sources = scope.transaction_sources
|
93
110
|
self.fingerprint = scope.fingerprint
|
94
111
|
self.span = scope.span
|
95
112
|
end
|
@@ -195,8 +212,9 @@ module Sentry
|
|
195
212
|
# The "transaction" here does not refer to `Transaction` objects.
|
196
213
|
# @param transaction_name [String]
|
197
214
|
# @return [void]
|
198
|
-
def set_transaction_name(transaction_name)
|
215
|
+
def set_transaction_name(transaction_name, source: :custom)
|
199
216
|
@transaction_names << transaction_name
|
217
|
+
@transaction_sources << source
|
200
218
|
end
|
201
219
|
|
202
220
|
# Sets the currently active session on the scope.
|
@@ -213,6 +231,13 @@ module Sentry
|
|
213
231
|
@transaction_names.last
|
214
232
|
end
|
215
233
|
|
234
|
+
# Returns current transaction source.
|
235
|
+
# The "transaction" here does not refer to `Transaction` objects.
|
236
|
+
# @return [String, nil]
|
237
|
+
def transaction_source
|
238
|
+
@transaction_sources.last
|
239
|
+
end
|
240
|
+
|
216
241
|
# Returns the associated Transaction object.
|
217
242
|
# @return [Transaction, nil]
|
218
243
|
def get_transaction
|
@@ -256,6 +281,7 @@ module Sentry
|
|
256
281
|
@level = :error
|
257
282
|
@fingerprint = []
|
258
283
|
@transaction_names = []
|
284
|
+
@transaction_sources = []
|
259
285
|
@event_processors = []
|
260
286
|
@rack_env = {}
|
261
287
|
@span = nil
|
data/lib/sentry/session.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class Session
|
5
|
-
attr_reader :started, :status
|
5
|
+
attr_reader :started, :status, :aggregation_key
|
6
6
|
|
7
7
|
# TODO-neel add :crashed after adding handled mechanism
|
8
8
|
STATUSES = %i(ok errored exited)
|
@@ -11,6 +11,10 @@ module Sentry
|
|
11
11
|
def initialize
|
12
12
|
@started = Sentry.utc_now
|
13
13
|
@status = :ok
|
14
|
+
|
15
|
+
# truncate seconds from the timestamp since we only care about
|
16
|
+
# minute level granularity for aggregation
|
17
|
+
@aggregation_key = Time.utc(@started.year, @started.month, @started.day, @started.hour, @started.min)
|
14
18
|
end
|
15
19
|
|
16
20
|
# TODO-neel add :crashed after adding handled mechanism
|
@@ -22,12 +26,6 @@ module Sentry
|
|
22
26
|
@status = :exited if @status == :ok
|
23
27
|
end
|
24
28
|
|
25
|
-
# truncate seconds from the timestamp since we only care about
|
26
|
-
# minute level granularity for aggregation
|
27
|
-
def aggregation_key
|
28
|
-
Time.utc(started.year, started.month, started.day, started.hour, started.min)
|
29
|
-
end
|
30
|
-
|
31
29
|
def deep_dup
|
32
30
|
dup
|
33
31
|
end
|
data/lib/sentry/span.rb
CHANGED
@@ -104,6 +104,13 @@ module Sentry
|
|
104
104
|
"#{@trace_id}-#{@span_id}-#{sampled_flag}"
|
105
105
|
end
|
106
106
|
|
107
|
+
# Generates a W3C Baggage header string for distributed tracing
|
108
|
+
# from the incoming baggage stored on the transation.
|
109
|
+
# @return [String, nil]
|
110
|
+
def to_baggage
|
111
|
+
transaction&.get_baggage&.serialize
|
112
|
+
end
|
113
|
+
|
107
114
|
# @return [Hash]
|
108
115
|
def to_hash
|
109
116
|
{
|
data/lib/sentry/test_helper.rb
CHANGED
@@ -31,6 +31,7 @@ module Sentry
|
|
31
31
|
|
32
32
|
test_client = Sentry::Client.new(copied_config)
|
33
33
|
Sentry.get_current_hub.bind_client(test_client)
|
34
|
+
Sentry.get_current_scope.clear
|
34
35
|
end
|
35
36
|
|
36
37
|
# Clears all stored events and envelopes.
|
@@ -41,6 +42,7 @@ module Sentry
|
|
41
42
|
|
42
43
|
sentry_transport.events = []
|
43
44
|
sentry_transport.envelopes = []
|
45
|
+
Sentry.get_current_scope.clear
|
44
46
|
end
|
45
47
|
|
46
48
|
# @return [Transport]
|
data/lib/sentry/transaction.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "sentry/baggage"
|
4
|
+
|
3
5
|
module Sentry
|
4
6
|
class Transaction < Span
|
5
7
|
SENTRY_TRACE_REGEXP = Regexp.new(
|
@@ -12,16 +14,29 @@ module Sentry
|
|
12
14
|
UNLABELD_NAME = "<unlabeled transaction>".freeze
|
13
15
|
MESSAGE_PREFIX = "[Tracing]"
|
14
16
|
|
17
|
+
# https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations
|
18
|
+
SOURCES = %i(custom url route view component task)
|
19
|
+
|
15
20
|
include LoggingHelper
|
16
21
|
|
17
22
|
# The name of the transaction.
|
18
23
|
# @return [String]
|
19
24
|
attr_reader :name
|
20
25
|
|
26
|
+
# The source of the transaction name.
|
27
|
+
# @return [Symbol]
|
28
|
+
attr_reader :source
|
29
|
+
|
21
30
|
# The sampling decision of the parent transaction, which will be considered when making the current transaction's sampling decision.
|
22
31
|
# @return [String]
|
23
32
|
attr_reader :parent_sampled
|
24
33
|
|
34
|
+
# The parsed incoming W3C baggage header.
|
35
|
+
# This is only for accessing the current baggage variable.
|
36
|
+
# Please use the #get_baggage method for interfacing outside this class.
|
37
|
+
# @return [Baggage, nil]
|
38
|
+
attr_reader :baggage
|
39
|
+
|
25
40
|
# @deprecated Use Sentry.get_current_hub instead.
|
26
41
|
attr_reader :hub
|
27
42
|
|
@@ -31,18 +46,35 @@ module Sentry
|
|
31
46
|
# @deprecated Use Sentry.logger instead.
|
32
47
|
attr_reader :logger
|
33
48
|
|
34
|
-
|
49
|
+
# The effective sample rate at which this transaction was sampled.
|
50
|
+
# @return [Float, nil]
|
51
|
+
attr_reader :effective_sample_rate
|
52
|
+
|
53
|
+
def initialize(
|
54
|
+
hub:,
|
55
|
+
name: nil,
|
56
|
+
source: :custom,
|
57
|
+
parent_sampled: nil,
|
58
|
+
baggage: nil,
|
59
|
+
**options
|
60
|
+
)
|
35
61
|
super(**options)
|
36
62
|
|
37
63
|
@name = name
|
64
|
+
@source = SOURCES.include?(source) ? source.to_sym : :custom
|
38
65
|
@parent_sampled = parent_sampled
|
39
66
|
@transaction = self
|
40
67
|
@hub = hub
|
68
|
+
@baggage = baggage
|
41
69
|
@configuration = hub.configuration # to be removed
|
42
70
|
@tracing_enabled = hub.configuration.tracing_enabled?
|
43
71
|
@traces_sampler = hub.configuration.traces_sampler
|
44
72
|
@traces_sample_rate = hub.configuration.traces_sample_rate
|
45
73
|
@logger = hub.configuration.logger
|
74
|
+
@release = hub.configuration.release
|
75
|
+
@environment = hub.configuration.environment
|
76
|
+
@dsn = hub.configuration.dsn
|
77
|
+
@effective_sample_rate = nil
|
46
78
|
init_span_recorder
|
47
79
|
end
|
48
80
|
|
@@ -52,10 +84,11 @@ module Sentry
|
|
52
84
|
#
|
53
85
|
# The child transaction will also store the parent's sampling decision in its `parent_sampled` attribute.
|
54
86
|
# @param sentry_trace [String] the trace string from the previous transaction.
|
87
|
+
# @param baggage [String, nil] the incoming baggage header string.
|
55
88
|
# @param hub [Hub] the hub that'll be responsible for sending this transaction when it's finished.
|
56
89
|
# @param options [Hash] the options you want to use to initialize a Transaction instance.
|
57
90
|
# @return [Transaction, nil]
|
58
|
-
def self.from_sentry_trace(sentry_trace, hub: Sentry.get_current_hub, **options)
|
91
|
+
def self.from_sentry_trace(sentry_trace, baggage: nil, hub: Sentry.get_current_hub, **options)
|
59
92
|
return unless hub.configuration.tracing_enabled?
|
60
93
|
return unless sentry_trace
|
61
94
|
|
@@ -70,13 +103,38 @@ module Sentry
|
|
70
103
|
sampled_flag != "0"
|
71
104
|
end
|
72
105
|
|
73
|
-
|
106
|
+
baggage = if baggage && !baggage.empty?
|
107
|
+
Baggage.from_incoming_header(baggage)
|
108
|
+
else
|
109
|
+
# If there's an incoming sentry-trace but no incoming baggage header,
|
110
|
+
# for instance in traces coming from older SDKs,
|
111
|
+
# baggage will be empty and frozen and won't be populated as head SDK.
|
112
|
+
Baggage.new({})
|
113
|
+
end
|
114
|
+
|
115
|
+
baggage.freeze!
|
116
|
+
|
117
|
+
new(
|
118
|
+
trace_id: trace_id,
|
119
|
+
parent_span_id: parent_span_id,
|
120
|
+
parent_sampled: parent_sampled,
|
121
|
+
hub: hub,
|
122
|
+
baggage: baggage,
|
123
|
+
**options
|
124
|
+
)
|
74
125
|
end
|
75
126
|
|
76
127
|
# @return [Hash]
|
77
128
|
def to_hash
|
78
129
|
hash = super
|
79
|
-
|
130
|
+
|
131
|
+
hash.merge!(
|
132
|
+
name: @name,
|
133
|
+
source: @source,
|
134
|
+
sampled: @sampled,
|
135
|
+
parent_sampled: @parent_sampled
|
136
|
+
)
|
137
|
+
|
80
138
|
hash
|
81
139
|
end
|
82
140
|
|
@@ -103,7 +161,10 @@ module Sentry
|
|
103
161
|
return
|
104
162
|
end
|
105
163
|
|
106
|
-
|
164
|
+
unless @sampled.nil?
|
165
|
+
@effective_sample_rate = @sampled ? 1.0 : 0.0
|
166
|
+
return
|
167
|
+
end
|
107
168
|
|
108
169
|
sample_rate =
|
109
170
|
if @traces_sampler.is_a?(Proc)
|
@@ -116,7 +177,11 @@ module Sentry
|
|
116
177
|
|
117
178
|
transaction_description = generate_transaction_description
|
118
179
|
|
119
|
-
|
180
|
+
if [true, false].include?(sample_rate)
|
181
|
+
@effective_sample_rate = sample_rate ? 1.0 : 0.0
|
182
|
+
elsif sample_rate.is_a?(Numeric) && sample_rate >= 0.0 && sample_rate <= 1.0
|
183
|
+
@effective_sample_rate = sample_rate.to_f
|
184
|
+
else
|
120
185
|
@sampled = false
|
121
186
|
log_warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
|
122
187
|
return
|
@@ -172,6 +237,14 @@ module Sentry
|
|
172
237
|
end
|
173
238
|
end
|
174
239
|
|
240
|
+
# Get the existing frozen incoming baggage
|
241
|
+
# or populate one with sentry- items as the head SDK.
|
242
|
+
# @return [Baggage]
|
243
|
+
def get_baggage
|
244
|
+
populate_head_baggage if @baggage.nil? || @baggage.mutable
|
245
|
+
@baggage
|
246
|
+
end
|
247
|
+
|
175
248
|
protected
|
176
249
|
|
177
250
|
def init_span_recorder(limit = 1000)
|
@@ -188,6 +261,29 @@ module Sentry
|
|
188
261
|
result
|
189
262
|
end
|
190
263
|
|
264
|
+
def populate_head_baggage
|
265
|
+
items = {
|
266
|
+
"trace_id" => trace_id,
|
267
|
+
"sample_rate" => effective_sample_rate&.to_s,
|
268
|
+
"environment" => @environment,
|
269
|
+
"release" => @release,
|
270
|
+
"public_key" => @dsn&.public_key
|
271
|
+
}
|
272
|
+
|
273
|
+
items["transaction"] = name unless source_low_quality?
|
274
|
+
|
275
|
+
user = @hub.current_scope&.user
|
276
|
+
items["user_segment"] = user["segment"] if user && user["segment"]
|
277
|
+
|
278
|
+
items.compact!
|
279
|
+
@baggage = Baggage.new(items, mutable: false)
|
280
|
+
end
|
281
|
+
|
282
|
+
# These are high cardinality and thus bad
|
283
|
+
def source_low_quality?
|
284
|
+
source == :url
|
285
|
+
end
|
286
|
+
|
191
287
|
class SpanRecorder
|
192
288
|
attr_reader :max_length, :spans
|
193
289
|
|
@@ -8,9 +8,27 @@ module Sentry
|
|
8
8
|
# @return [<Array[Span]>]
|
9
9
|
attr_accessor :spans
|
10
10
|
|
11
|
+
# @return [Hash, nil]
|
12
|
+
attr_accessor :dynamic_sampling_context
|
13
|
+
|
11
14
|
# @return [Float, nil]
|
12
15
|
attr_reader :start_timestamp
|
13
16
|
|
17
|
+
def initialize(transaction:, **options)
|
18
|
+
super(**options)
|
19
|
+
|
20
|
+
self.transaction = transaction.name
|
21
|
+
self.transaction_info = { source: transaction.source }
|
22
|
+
self.contexts.merge!(trace: transaction.get_trace_context)
|
23
|
+
self.timestamp = transaction.timestamp
|
24
|
+
self.start_timestamp = transaction.start_timestamp
|
25
|
+
self.tags = transaction.tags
|
26
|
+
self.dynamic_sampling_context = transaction.get_baggage.dynamic_sampling_context
|
27
|
+
|
28
|
+
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
|
29
|
+
self.spans = finished_spans.map(&:to_hash)
|
30
|
+
end
|
31
|
+
|
14
32
|
# Sets the event's start_timestamp.
|
15
33
|
# @param time [Time, Float]
|
16
34
|
# @return [void]
|
data/lib/sentry/transport.rb
CHANGED
@@ -136,14 +136,18 @@ module Sentry
|
|
136
136
|
event_id = event_payload[:event_id] || event_payload["event_id"]
|
137
137
|
item_type = event_payload[:type] || event_payload["type"]
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
)
|
139
|
+
envelope_headers = {
|
140
|
+
event_id: event_id,
|
141
|
+
dsn: @dsn.to_s,
|
142
|
+
sdk: Sentry.sdk_meta,
|
143
|
+
sent_at: Sentry.utc_now.iso8601
|
144
|
+
}
|
145
|
+
|
146
|
+
if event.is_a?(TransactionEvent) && event.dynamic_sampling_context
|
147
|
+
envelope_headers[:trace] = event.dynamic_sampling_context
|
148
|
+
end
|
149
|
+
|
150
|
+
envelope = Envelope.new(envelope_headers)
|
147
151
|
|
148
152
|
envelope.add_item(
|
149
153
|
{ type: item_type, content_type: 'application/json' },
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -39,6 +39,8 @@ module Sentry
|
|
39
39
|
|
40
40
|
SENTRY_TRACE_HEADER_NAME = "sentry-trace".freeze
|
41
41
|
|
42
|
+
BAGGAGE_HEADER_NAME = "baggage".freeze
|
43
|
+
|
42
44
|
THREAD_LOCAL = :sentry_hub
|
43
45
|
|
44
46
|
class << self
|
@@ -348,7 +350,7 @@ module Sentry
|
|
348
350
|
# @yieldparam scope [Scope]
|
349
351
|
# @return [void]
|
350
352
|
def with_scope(&block)
|
351
|
-
return unless initialized?
|
353
|
+
return yield unless initialized?
|
352
354
|
get_current_hub.with_scope(&block)
|
353
355
|
end
|
354
356
|
|
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: 5.
|
4
|
+
version: 5.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sentry-ruby
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
19
|
+
version: 5.5.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.
|
26
|
+
version: 5.5.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: concurrent-ruby
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- lib/sentry-ruby.rb
|
62
62
|
- lib/sentry/background_worker.rb
|
63
63
|
- lib/sentry/backtrace.rb
|
64
|
+
- lib/sentry/baggage.rb
|
64
65
|
- lib/sentry/breadcrumb.rb
|
65
66
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
66
67
|
- lib/sentry/breadcrumb_buffer.rb
|