sentry-ruby 5.10.0 → 5.14.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 +7 -1
- data/README.md +9 -9
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +36 -1
- data/lib/sentry/configuration.rb +16 -0
- data/lib/sentry/cron/monitor_check_ins.rb +66 -0
- data/lib/sentry/cron/monitor_config.rb +53 -0
- data/lib/sentry/cron/monitor_schedule.rb +42 -0
- data/lib/sentry/envelope.rb +1 -1
- data/lib/sentry/event.rb +6 -0
- data/lib/sentry/hub.rb +69 -1
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/single_exception.rb +5 -3
- data/lib/sentry/net/http.rb +25 -22
- data/lib/sentry/profiler.rb +18 -7
- data/lib/sentry/propagation_context.rb +134 -0
- data/lib/sentry/puma.rb +11 -4
- data/lib/sentry/rack/capture_exceptions.rb +1 -4
- data/lib/sentry/redis.rb +8 -3
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/scope.rb +17 -2
- data/lib/sentry/span.rb +39 -2
- data/lib/sentry/test_helper.rb +18 -12
- data/lib/sentry/transaction.rb +9 -17
- data/lib/sentry/transaction_event.rb +0 -3
- data/lib/sentry/transport/configuration.rb +74 -1
- data/lib/sentry/transport/http_transport.rb +8 -2
- data/lib/sentry/transport.rb +4 -3
- data/lib/sentry/utils/argument_checking_helper.rb +6 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +62 -6
- metadata +7 -2
data/lib/sentry/net/http.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "net/http"
|
4
|
+
require "resolv"
|
4
5
|
|
5
6
|
module Sentry
|
6
7
|
# @api private
|
@@ -30,18 +31,21 @@ module Sentry
|
|
30
31
|
return super if from_sentry_sdk?
|
31
32
|
|
32
33
|
Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span|
|
33
|
-
|
34
|
+
request_info = extract_request_info(req)
|
35
|
+
|
36
|
+
if propagate_trace?(request_info[:url], Sentry.configuration)
|
37
|
+
set_propagation_headers(req)
|
38
|
+
end
|
34
39
|
|
35
40
|
super.tap do |res|
|
36
|
-
record_sentry_breadcrumb(
|
41
|
+
record_sentry_breadcrumb(request_info, res)
|
37
42
|
|
38
43
|
if sentry_span
|
39
|
-
request_info = extract_request_info(req)
|
40
44
|
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
41
|
-
sentry_span.set_data(
|
42
|
-
sentry_span.set_data(
|
43
|
-
sentry_span.set_data(
|
44
|
-
sentry_span.set_data(
|
45
|
+
sentry_span.set_data(Span::DataConventions::URL, request_info[:url])
|
46
|
+
sentry_span.set_data(Span::DataConventions::HTTP_METHOD, request_info[:method])
|
47
|
+
sentry_span.set_data(Span::DataConventions::HTTP_QUERY, request_info[:query]) if request_info[:query]
|
48
|
+
sentry_span.set_data(Span::DataConventions::HTTP_STATUS_CODE, res.code.to_i)
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
@@ -49,23 +53,13 @@ module Sentry
|
|
49
53
|
|
50
54
|
private
|
51
55
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
client = Sentry.get_current_client
|
56
|
-
|
57
|
-
trace = client.generate_sentry_trace(sentry_span)
|
58
|
-
req[SENTRY_TRACE_HEADER_NAME] = trace if trace
|
59
|
-
|
60
|
-
baggage = client.generate_baggage(sentry_span)
|
61
|
-
req[BAGGAGE_HEADER_NAME] = baggage if baggage && !baggage.empty?
|
56
|
+
def set_propagation_headers(req)
|
57
|
+
Sentry.get_trace_propagation_headers&.each { |k, v| req[k] = v }
|
62
58
|
end
|
63
59
|
|
64
|
-
def record_sentry_breadcrumb(
|
60
|
+
def record_sentry_breadcrumb(request_info, res)
|
65
61
|
return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
|
66
62
|
|
67
|
-
request_info = extract_request_info(req)
|
68
|
-
|
69
63
|
crumb = Sentry::Breadcrumb.new(
|
70
64
|
level: :info,
|
71
65
|
category: BREADCRUMB_CATEGORY,
|
@@ -84,7 +78,10 @@ module Sentry
|
|
84
78
|
end
|
85
79
|
|
86
80
|
def extract_request_info(req)
|
87
|
-
|
81
|
+
# IPv6 url could look like '::1/path', and that won't parse without
|
82
|
+
# wrapping it in square brackets.
|
83
|
+
hostname = address =~ Resolv::IPv6::Regex ? "[#{address}]" : address
|
84
|
+
uri = req.uri || URI.parse("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}")
|
88
85
|
url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s
|
89
86
|
|
90
87
|
result = { method: req.method, url: url }
|
@@ -96,8 +93,14 @@ module Sentry
|
|
96
93
|
|
97
94
|
result
|
98
95
|
end
|
96
|
+
|
97
|
+
def propagate_trace?(url, configuration)
|
98
|
+
url &&
|
99
|
+
configuration.propagate_traces &&
|
100
|
+
configuration.trace_propagation_targets.any? { |target| url.match?(target) }
|
101
|
+
end
|
99
102
|
end
|
100
103
|
end
|
101
104
|
end
|
102
105
|
|
103
|
-
Sentry.register_patch(Sentry::Net::HTTP, Net::HTTP)
|
106
|
+
Sentry.register_patch(:http, Sentry::Net::HTTP, Net::HTTP)
|
data/lib/sentry/profiler.rb
CHANGED
@@ -9,6 +9,7 @@ module Sentry
|
|
9
9
|
# 101 Hz in microseconds
|
10
10
|
DEFAULT_INTERVAL = 1e6 / 101
|
11
11
|
MICRO_TO_NANO_SECONDS = 1e3
|
12
|
+
MIN_SAMPLES_REQUIRED = 2
|
12
13
|
|
13
14
|
attr_reader :sampled, :started, :event_id
|
14
15
|
|
@@ -73,14 +74,19 @@ module Sentry
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def to_hash
|
76
|
-
|
77
|
+
unless @sampled
|
78
|
+
record_lost_event(:sample_rate)
|
79
|
+
return {}
|
80
|
+
end
|
81
|
+
|
77
82
|
return {} unless @started
|
78
83
|
|
79
84
|
results = StackProf.results
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
85
|
+
|
86
|
+
if !results || results.empty? || results[:samples] == 0 || !results[:raw]
|
87
|
+
record_lost_event(:insufficient_data)
|
88
|
+
return {}
|
89
|
+
end
|
84
90
|
|
85
91
|
frame_map = {}
|
86
92
|
|
@@ -103,7 +109,7 @@ module Sentry
|
|
103
109
|
}
|
104
110
|
|
105
111
|
frame_hash[:module] = mod if mod
|
106
|
-
frame_hash[:lineno] = frame_data[:line] if frame_data[:line]
|
112
|
+
frame_hash[:lineno] = frame_data[:line] if frame_data[:line] && frame_data[:line] >= 0
|
107
113
|
|
108
114
|
frame_hash
|
109
115
|
end
|
@@ -157,8 +163,9 @@ module Sentry
|
|
157
163
|
|
158
164
|
log('Some samples thrown away') if samples.size != results[:samples]
|
159
165
|
|
160
|
-
if samples.size <=
|
166
|
+
if samples.size <= MIN_SAMPLES_REQUIRED
|
161
167
|
log('Not enough samples, discarding profiler')
|
168
|
+
record_lost_event(:insufficient_data)
|
162
169
|
return {}
|
163
170
|
end
|
164
171
|
|
@@ -218,5 +225,9 @@ module Sentry
|
|
218
225
|
|
219
226
|
[function, mod]
|
220
227
|
end
|
228
|
+
|
229
|
+
def record_lost_event(reason)
|
230
|
+
Sentry.get_current_client&.transport&.record_lost_event(reason, 'profile')
|
231
|
+
end
|
221
232
|
end
|
222
233
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
require "sentry/baggage"
|
5
|
+
|
6
|
+
module Sentry
|
7
|
+
class PropagationContext
|
8
|
+
SENTRY_TRACE_REGEXP = Regexp.new(
|
9
|
+
"^[ \t]*" + # whitespace
|
10
|
+
"([0-9a-f]{32})?" + # trace_id
|
11
|
+
"-?([0-9a-f]{16})?" + # span_id
|
12
|
+
"-?([01])?" + # sampled
|
13
|
+
"[ \t]*$" # whitespace
|
14
|
+
)
|
15
|
+
|
16
|
+
# An uuid that can be used to identify a trace.
|
17
|
+
# @return [String]
|
18
|
+
attr_reader :trace_id
|
19
|
+
# An uuid that can be used to identify the span.
|
20
|
+
# @return [String]
|
21
|
+
attr_reader :span_id
|
22
|
+
# Span parent's span_id.
|
23
|
+
# @return [String, nil]
|
24
|
+
attr_reader :parent_span_id
|
25
|
+
# The sampling decision of the parent transaction.
|
26
|
+
# @return [Boolean, nil]
|
27
|
+
attr_reader :parent_sampled
|
28
|
+
# Is there an incoming trace or not?
|
29
|
+
# @return [Boolean]
|
30
|
+
attr_reader :incoming_trace
|
31
|
+
# This is only for accessing the current baggage variable.
|
32
|
+
# Please use the #get_baggage method for interfacing outside this class.
|
33
|
+
# @return [Baggage, nil]
|
34
|
+
attr_reader :baggage
|
35
|
+
|
36
|
+
def initialize(scope, env = nil)
|
37
|
+
@scope = scope
|
38
|
+
@parent_span_id = nil
|
39
|
+
@parent_sampled = nil
|
40
|
+
@baggage = nil
|
41
|
+
@incoming_trace = false
|
42
|
+
|
43
|
+
if env
|
44
|
+
sentry_trace_header = env["HTTP_SENTRY_TRACE"] || env[SENTRY_TRACE_HEADER_NAME]
|
45
|
+
baggage_header = env["HTTP_BAGGAGE"] || env[BAGGAGE_HEADER_NAME]
|
46
|
+
|
47
|
+
if sentry_trace_header
|
48
|
+
sentry_trace_data = self.class.extract_sentry_trace(sentry_trace_header)
|
49
|
+
|
50
|
+
if sentry_trace_data
|
51
|
+
@trace_id, @parent_span_id, @parent_sampled = sentry_trace_data
|
52
|
+
|
53
|
+
@baggage = if baggage_header && !baggage_header.empty?
|
54
|
+
Baggage.from_incoming_header(baggage_header)
|
55
|
+
else
|
56
|
+
# If there's an incoming sentry-trace but no incoming baggage header,
|
57
|
+
# for instance in traces coming from older SDKs,
|
58
|
+
# baggage will be empty and frozen and won't be populated as head SDK.
|
59
|
+
Baggage.new({})
|
60
|
+
end
|
61
|
+
|
62
|
+
@baggage.freeze!
|
63
|
+
@incoming_trace = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
@trace_id ||= SecureRandom.uuid.delete("-")
|
69
|
+
@span_id = SecureRandom.uuid.delete("-").slice(0, 16)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Extract the trace_id, parent_span_id and parent_sampled values from a sentry-trace header.
|
73
|
+
#
|
74
|
+
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
75
|
+
# @return [Array, nil]
|
76
|
+
def self.extract_sentry_trace(sentry_trace)
|
77
|
+
match = SENTRY_TRACE_REGEXP.match(sentry_trace)
|
78
|
+
return nil if match.nil?
|
79
|
+
|
80
|
+
trace_id, parent_span_id, sampled_flag = match[1..3]
|
81
|
+
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
82
|
+
|
83
|
+
[trace_id, parent_span_id, parent_sampled]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the trace context that can be used to embed in an Event.
|
87
|
+
# @return [Hash]
|
88
|
+
def get_trace_context
|
89
|
+
{
|
90
|
+
trace_id: trace_id,
|
91
|
+
span_id: span_id,
|
92
|
+
parent_span_id: parent_span_id
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the sentry-trace header from the propagation context.
|
97
|
+
# @return [String]
|
98
|
+
def get_traceparent
|
99
|
+
"#{trace_id}-#{span_id}"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns the Baggage from the propagation context or populates as head SDK if empty.
|
103
|
+
# @return [Baggage, nil]
|
104
|
+
def get_baggage
|
105
|
+
populate_head_baggage if @baggage.nil? || @baggage.mutable
|
106
|
+
@baggage
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns the Dynamic Sampling Context from the baggage.
|
110
|
+
# @return [String, nil]
|
111
|
+
def get_dynamic_sampling_context
|
112
|
+
get_baggage&.dynamic_sampling_context
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def populate_head_baggage
|
118
|
+
return unless Sentry.initialized?
|
119
|
+
|
120
|
+
configuration = Sentry.configuration
|
121
|
+
|
122
|
+
items = {
|
123
|
+
"trace_id" => trace_id,
|
124
|
+
"environment" => configuration.environment,
|
125
|
+
"release" => configuration.release,
|
126
|
+
"public_key" => configuration.dsn&.public_key,
|
127
|
+
"user_segment" => @scope.user && @scope.user["segment"]
|
128
|
+
}
|
129
|
+
|
130
|
+
items.compact!
|
131
|
+
@baggage = Baggage.new(items, mutable: false)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/sentry/puma.rb
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
return unless defined?(Puma::Server)
|
4
|
+
|
3
5
|
module Sentry
|
4
6
|
module Puma
|
5
7
|
module Server
|
8
|
+
PUMA_4_AND_PRIOR = Gem::Version.new(::Puma::Const::PUMA_VERSION) < Gem::Version.new("5.0.0")
|
9
|
+
|
6
10
|
def lowlevel_error(e, env, status=500)
|
7
|
-
result =
|
11
|
+
result =
|
12
|
+
if PUMA_4_AND_PRIOR
|
13
|
+
super(e, env)
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
8
17
|
|
9
18
|
begin
|
10
19
|
Sentry.capture_exception(e) do |scope|
|
@@ -20,6 +29,4 @@ module Sentry
|
|
20
29
|
end
|
21
30
|
end
|
22
31
|
|
23
|
-
|
24
|
-
Sentry.register_patch(Sentry::Puma::Server, Puma::Server)
|
25
|
-
end
|
32
|
+
Sentry.register_patch(:puma, Sentry::Puma::Server, Puma::Server)
|
@@ -62,11 +62,8 @@ module Sentry
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def start_transaction(env, scope)
|
65
|
-
sentry_trace = env["HTTP_SENTRY_TRACE"]
|
66
|
-
baggage = env["HTTP_BAGGAGE"]
|
67
|
-
|
68
65
|
options = { name: scope.transaction_name, source: scope.transaction_source, op: transaction_op }
|
69
|
-
transaction = Sentry
|
66
|
+
transaction = Sentry.continue_trace(env, **options)
|
70
67
|
Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
71
68
|
end
|
72
69
|
|
data/lib/sentry/redis.rb
CHANGED
@@ -19,7 +19,10 @@ module Sentry
|
|
19
19
|
|
20
20
|
if span
|
21
21
|
span.set_description(commands_description)
|
22
|
-
span.set_data(
|
22
|
+
span.set_data(Span::DataConventions::DB_SYSTEM, "redis")
|
23
|
+
span.set_data(Span::DataConventions::DB_NAME, db)
|
24
|
+
span.set_data(Span::DataConventions::SERVER_ADDRESS, host)
|
25
|
+
span.set_data(Span::DataConventions::SERVER_PORT, port)
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
@@ -96,8 +99,10 @@ end
|
|
96
99
|
|
97
100
|
if defined?(::Redis::Client)
|
98
101
|
if Gem::Version.new(::Redis::VERSION) < Gem::Version.new("5.0")
|
99
|
-
Sentry.register_patch(Sentry::Redis::OldClientPatch, ::Redis::Client)
|
102
|
+
Sentry.register_patch(:redis, Sentry::Redis::OldClientPatch, ::Redis::Client)
|
100
103
|
elsif defined?(RedisClient)
|
101
|
-
|
104
|
+
Sentry.register_patch(:redis) do
|
105
|
+
RedisClient.register(Sentry::Redis::GlobalRedisInstrumentation)
|
106
|
+
end
|
102
107
|
end
|
103
108
|
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sentry/breadcrumb_buffer"
|
4
|
+
require "sentry/propagation_context"
|
4
5
|
require "etc"
|
5
6
|
|
6
7
|
module Sentry
|
@@ -20,7 +21,8 @@ module Sentry
|
|
20
21
|
:event_processors,
|
21
22
|
:rack_env,
|
22
23
|
:span,
|
23
|
-
:session
|
24
|
+
:session,
|
25
|
+
:propagation_context
|
24
26
|
]
|
25
27
|
|
26
28
|
attr_reader(*ATTRIBUTES)
|
@@ -50,7 +52,10 @@ module Sentry
|
|
50
52
|
event.transaction_info = { source: transaction_source } if transaction_source
|
51
53
|
|
52
54
|
if span
|
53
|
-
event.contexts[:trace]
|
55
|
+
event.contexts[:trace] ||= span.get_trace_context
|
56
|
+
else
|
57
|
+
event.contexts[:trace] ||= propagation_context.get_trace_context
|
58
|
+
event.dynamic_sampling_context ||= propagation_context.get_dynamic_sampling_context
|
54
59
|
end
|
55
60
|
|
56
61
|
event.fingerprint = fingerprint
|
@@ -95,6 +100,7 @@ module Sentry
|
|
95
100
|
copy.fingerprint = fingerprint.deep_dup
|
96
101
|
copy.span = span.deep_dup
|
97
102
|
copy.session = session.deep_dup
|
103
|
+
copy.propagation_context = propagation_context.deep_dup
|
98
104
|
copy
|
99
105
|
end
|
100
106
|
|
@@ -111,6 +117,7 @@ module Sentry
|
|
111
117
|
self.transaction_sources = scope.transaction_sources
|
112
118
|
self.fingerprint = scope.fingerprint
|
113
119
|
self.span = scope.span
|
120
|
+
self.propagation_context = scope.propagation_context
|
114
121
|
end
|
115
122
|
|
116
123
|
# Updates the scope's data from the given options.
|
@@ -272,6 +279,13 @@ module Sentry
|
|
272
279
|
@event_processors << block
|
273
280
|
end
|
274
281
|
|
282
|
+
# Generate a new propagation context either from the incoming env headers or from scratch.
|
283
|
+
# @param env [Hash, nil]
|
284
|
+
# @return [void]
|
285
|
+
def generate_propagation_context(env = nil)
|
286
|
+
@propagation_context = PropagationContext.new(self, env)
|
287
|
+
end
|
288
|
+
|
275
289
|
protected
|
276
290
|
|
277
291
|
# for duplicating scopes internally
|
@@ -292,6 +306,7 @@ module Sentry
|
|
292
306
|
@rack_env = {}
|
293
307
|
@span = nil
|
294
308
|
@session = nil
|
309
|
+
generate_propagation_context
|
295
310
|
set_new_breadcrumb_buffer
|
296
311
|
end
|
297
312
|
|
data/lib/sentry/span.rb
CHANGED
@@ -4,6 +4,43 @@ require "securerandom"
|
|
4
4
|
|
5
5
|
module Sentry
|
6
6
|
class Span
|
7
|
+
|
8
|
+
# We will try to be consistent with OpenTelemetry on this front going forward.
|
9
|
+
# https://develop.sentry.dev/sdk/performance/span-data-conventions/
|
10
|
+
module DataConventions
|
11
|
+
URL = "url"
|
12
|
+
HTTP_STATUS_CODE = "http.response.status_code"
|
13
|
+
HTTP_QUERY = "http.query"
|
14
|
+
HTTP_METHOD = "http.request.method"
|
15
|
+
|
16
|
+
# An identifier for the database management system (DBMS) product being used.
|
17
|
+
# Example: postgresql
|
18
|
+
DB_SYSTEM = "db.system"
|
19
|
+
|
20
|
+
# The name of the database being accessed.
|
21
|
+
# For commands that switch the database, this should be set to the target database
|
22
|
+
# (even if the command fails).
|
23
|
+
# Example: myDatabase
|
24
|
+
DB_NAME = "db.name"
|
25
|
+
|
26
|
+
# Name of the database host.
|
27
|
+
# Example: example.com
|
28
|
+
SERVER_ADDRESS = "server.address"
|
29
|
+
|
30
|
+
# Logical server port number
|
31
|
+
# Example: 80; 8080; 443
|
32
|
+
SERVER_PORT = "server.port"
|
33
|
+
|
34
|
+
# Physical server IP address or Unix socket address.
|
35
|
+
# Example: 10.5.3.2
|
36
|
+
SERVER_SOCKET_ADDRESS = "server.socket.address"
|
37
|
+
|
38
|
+
# Physical server port.
|
39
|
+
# Recommended: If different than server.port.
|
40
|
+
# Example: 16456
|
41
|
+
SERVER_SOCKET_PORT = "server.socket.port"
|
42
|
+
end
|
43
|
+
|
7
44
|
STATUS_MAP = {
|
8
45
|
400 => "invalid_argument",
|
9
46
|
401 => "unauthenticated",
|
@@ -75,7 +112,7 @@ module Sentry
|
|
75
112
|
timestamp: nil
|
76
113
|
)
|
77
114
|
@trace_id = trace_id || SecureRandom.uuid.delete("-")
|
78
|
-
@span_id = span_id || SecureRandom.
|
115
|
+
@span_id = span_id || SecureRandom.uuid.delete("-").slice(0, 16)
|
79
116
|
@parent_span_id = parent_span_id
|
80
117
|
@sampled = sampled
|
81
118
|
@start_timestamp = start_timestamp || Sentry.utc_now.to_f
|
@@ -208,7 +245,7 @@ module Sentry
|
|
208
245
|
# @param status_code [String] example: "500".
|
209
246
|
def set_http_status(status_code)
|
210
247
|
status_code = status_code.to_i
|
211
|
-
set_data(
|
248
|
+
set_data(DataConventions::HTTP_STATUS_CODE, status_code)
|
212
249
|
|
213
250
|
status =
|
214
251
|
if status_code >= 200 && status_code < 299
|
data/lib/sentry/test_helper.rb
CHANGED
@@ -14,24 +14,28 @@ module Sentry
|
|
14
14
|
# @return [void]
|
15
15
|
def setup_sentry_test(&block)
|
16
16
|
raise "please make sure the SDK is initialized for testing" unless Sentry.initialized?
|
17
|
-
|
17
|
+
dummy_config = Sentry.configuration.dup
|
18
18
|
# configure dummy DSN, so the events will not be sent to the actual service
|
19
|
-
|
19
|
+
dummy_config.dsn = DUMMY_DSN
|
20
20
|
# set transport to DummyTransport, so we can easily intercept the captured events
|
21
|
-
|
21
|
+
dummy_config.transport.transport_class = Sentry::DummyTransport
|
22
22
|
# make sure SDK allows sending under the current environment
|
23
|
-
|
23
|
+
dummy_config.enabled_environments << dummy_config.environment unless dummy_config.enabled_environments.include?(dummy_config.environment)
|
24
24
|
# disble async event sending
|
25
|
-
|
25
|
+
dummy_config.background_worker_threads = 0
|
26
26
|
|
27
27
|
# user can overwrite some of the configs, with a few exceptions like:
|
28
28
|
# - include_local_variables
|
29
29
|
# - auto_session_tracking
|
30
|
-
block&.call(
|
30
|
+
block&.call(dummy_config)
|
31
31
|
|
32
|
-
|
32
|
+
# the base layer's client should already use the dummy config so nothing will be sent by accident
|
33
|
+
base_client = Sentry::Client.new(dummy_config)
|
34
|
+
Sentry.get_current_hub.bind_client(base_client)
|
35
|
+
# create a new layer so mutations made to the testing scope or configuration could be simply popped later
|
36
|
+
Sentry.get_current_hub.push_scope
|
37
|
+
test_client = Sentry::Client.new(dummy_config.dup)
|
33
38
|
Sentry.get_current_hub.bind_client(test_client)
|
34
|
-
Sentry.get_current_scope.clear
|
35
39
|
end
|
36
40
|
|
37
41
|
# Clears all stored events and envelopes.
|
@@ -40,9 +44,12 @@ module Sentry
|
|
40
44
|
def teardown_sentry_test
|
41
45
|
return unless Sentry.initialized?
|
42
46
|
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
# pop testing layer created by `setup_sentry_test`
|
48
|
+
# but keep the base layer to avoid nil-pointer errors
|
49
|
+
# TODO: find a way to notify users if they somehow popped the test layer before calling this method
|
50
|
+
if Sentry.get_current_hub.instance_variable_get(:@stack).size > 1
|
51
|
+
Sentry.get_current_hub.pop_scope
|
52
|
+
end
|
46
53
|
end
|
47
54
|
|
48
55
|
# @return [Transport]
|
@@ -75,4 +82,3 @@ module Sentry
|
|
75
82
|
end
|
76
83
|
end
|
77
84
|
end
|
78
|
-
|
data/lib/sentry/transaction.rb
CHANGED
@@ -2,16 +2,13 @@
|
|
2
2
|
|
3
3
|
require "sentry/baggage"
|
4
4
|
require "sentry/profiler"
|
5
|
+
require "sentry/propagation_context"
|
5
6
|
|
6
7
|
module Sentry
|
7
8
|
class Transaction < Span
|
8
|
-
SENTRY_TRACE_REGEXP
|
9
|
-
|
10
|
-
|
11
|
-
"-?([0-9a-f]{16})?" + # span_id
|
12
|
-
"-?([01])?" + # sampled
|
13
|
-
"[ \t]*$" # whitespace
|
14
|
-
)
|
9
|
+
# @deprecated Use Sentry::PropagationContext::SENTRY_TRACE_REGEXP instead.
|
10
|
+
SENTRY_TRACE_REGEXP = PropagationContext::SENTRY_TRACE_REGEXP
|
11
|
+
|
15
12
|
UNLABELD_NAME = "<unlabeled transaction>".freeze
|
16
13
|
MESSAGE_PREFIX = "[Tracing]"
|
17
14
|
|
@@ -92,6 +89,8 @@ module Sentry
|
|
92
89
|
init_span_recorder
|
93
90
|
end
|
94
91
|
|
92
|
+
# @deprecated use Sentry.continue_trace instead.
|
93
|
+
#
|
95
94
|
# Initalizes a Transaction instance with a Sentry trace string from another transaction (usually from an external request).
|
96
95
|
#
|
97
96
|
# The original transaction will become the parent of the new Transaction instance. And they will share the same `trace_id`.
|
@@ -132,18 +131,10 @@ module Sentry
|
|
132
131
|
)
|
133
132
|
end
|
134
133
|
|
135
|
-
#
|
136
|
-
#
|
137
|
-
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
134
|
+
# @deprecated Use Sentry::PropagationContext.extract_sentry_trace instead.
|
138
135
|
# @return [Array, nil]
|
139
136
|
def self.extract_sentry_trace(sentry_trace)
|
140
|
-
|
141
|
-
return nil if match.nil?
|
142
|
-
|
143
|
-
trace_id, parent_span_id, sampled_flag = match[1..3]
|
144
|
-
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
145
|
-
|
146
|
-
[trace_id, parent_span_id, parent_sampled]
|
137
|
+
PropagationContext.extract_sentry_trace(sentry_trace)
|
147
138
|
end
|
148
139
|
|
149
140
|
# @return [Hash]
|
@@ -323,6 +314,7 @@ module Sentry
|
|
323
314
|
items = {
|
324
315
|
"trace_id" => trace_id,
|
325
316
|
"sample_rate" => effective_sample_rate&.to_s,
|
317
|
+
"sampled" => sampled&.to_s,
|
326
318
|
"environment" => @environment,
|
327
319
|
"release" => @release,
|
328
320
|
"public_key" => @dsn&.public_key
|