sentry-ruby 5.8.0 → 5.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +14 -2
- data/README.md +9 -9
- data/Rakefile +8 -1
- data/lib/sentry/backtrace.rb +1 -1
- data/lib/sentry/baggage.rb +1 -12
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +40 -2
- data/lib/sentry/configuration.rb +84 -7
- data/lib/sentry/cron/monitor_check_ins.rb +61 -0
- data/lib/sentry/cron/monitor_config.rb +53 -0
- data/lib/sentry/cron/monitor_schedule.rb +42 -0
- data/lib/sentry/envelope.rb +2 -5
- data/lib/sentry/event.rb +6 -0
- data/lib/sentry/hub.rb +78 -3
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/single_exception.rb +4 -3
- data/lib/sentry/net/http.rb +21 -22
- data/lib/sentry/profiler.rb +233 -0
- data/lib/sentry/propagation_context.rb +134 -0
- data/lib/sentry/puma.rb +32 -0
- data/lib/sentry/rack/capture_exceptions.rb +1 -4
- data/lib/sentry/redis.rb +9 -8
- data/lib/sentry/scope.rb +23 -3
- data/lib/sentry/span.rb +39 -2
- data/lib/sentry/test_helper.rb +18 -12
- data/lib/sentry/transaction.rb +24 -17
- data/lib/sentry/transaction_event.rb +30 -3
- data/lib/sentry/transport.rb +11 -3
- data/lib/sentry/utils/argument_checking_helper.rb +9 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +72 -5
- metadata +9 -3
- data/CODE_OF_CONDUCT.md +0 -74
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
|
@@ -30,6 +33,7 @@ module Sentry
|
|
30
33
|
attr_reader :commands, :host, :port, :db
|
31
34
|
|
32
35
|
def record_breadcrumb
|
36
|
+
return unless Sentry.initialized?
|
33
37
|
return unless Sentry.configuration.breadcrumbs_logger.include?(LOGGER_NAME)
|
34
38
|
|
35
39
|
Sentry.add_breadcrumb(
|
@@ -95,13 +99,10 @@ end
|
|
95
99
|
|
96
100
|
if defined?(::Redis::Client)
|
97
101
|
if Gem::Version.new(::Redis::VERSION) < Gem::Version.new("5.0")
|
98
|
-
Sentry.register_patch
|
99
|
-
patch = Sentry::Redis::OldClientPatch
|
100
|
-
unless Redis::Client.ancestors.include?(patch)
|
101
|
-
Redis::Client.prepend(patch)
|
102
|
-
end
|
103
|
-
end
|
102
|
+
Sentry.register_patch(:redis, Sentry::Redis::OldClientPatch, ::Redis::Client)
|
104
103
|
elsif defined?(RedisClient)
|
105
|
-
|
104
|
+
Sentry.register_patch(:redis) do
|
105
|
+
RedisClient.register(Sentry::Redis::GlobalRedisInstrumentation)
|
106
|
+
end
|
106
107
|
end
|
107
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.
|
@@ -192,6 +199,10 @@ module Sentry
|
|
192
199
|
# @return [Hash]
|
193
200
|
def set_contexts(contexts_hash)
|
194
201
|
check_argument_type!(contexts_hash, Hash)
|
202
|
+
contexts_hash.values.each do |val|
|
203
|
+
check_argument_type!(val, Hash)
|
204
|
+
end
|
205
|
+
|
195
206
|
@contexts.merge!(contexts_hash) do |key, old, new|
|
196
207
|
old.merge(new)
|
197
208
|
end
|
@@ -268,6 +279,13 @@ module Sentry
|
|
268
279
|
@event_processors << block
|
269
280
|
end
|
270
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
|
+
|
271
289
|
protected
|
272
290
|
|
273
291
|
# for duplicating scopes internally
|
@@ -288,6 +306,7 @@ module Sentry
|
|
288
306
|
@rack_env = {}
|
289
307
|
@span = nil
|
290
308
|
@session = nil
|
309
|
+
generate_propagation_context
|
291
310
|
set_new_breadcrumb_buffer
|
292
311
|
end
|
293
312
|
|
@@ -305,7 +324,8 @@ module Sentry
|
|
305
324
|
name: uname[:sysname] || RbConfig::CONFIG["host_os"],
|
306
325
|
version: uname[:version],
|
307
326
|
build: uname[:release],
|
308
|
-
kernel_version: uname[:version]
|
327
|
+
kernel_version: uname[:version],
|
328
|
+
machine: uname[:machine]
|
309
329
|
}
|
310
330
|
end
|
311
331
|
end
|
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
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sentry/baggage"
|
4
|
+
require "sentry/profiler"
|
5
|
+
require "sentry/propagation_context"
|
4
6
|
|
5
7
|
module Sentry
|
6
8
|
class Transaction < Span
|
7
|
-
SENTRY_TRACE_REGEXP
|
8
|
-
|
9
|
-
|
10
|
-
"-?([0-9a-f]{16})?" + # span_id
|
11
|
-
"-?([01])?" + # sampled
|
12
|
-
"[ \t]*$" # whitespace
|
13
|
-
)
|
9
|
+
# @deprecated Use Sentry::PropagationContext::SENTRY_TRACE_REGEXP instead.
|
10
|
+
SENTRY_TRACE_REGEXP = PropagationContext::SENTRY_TRACE_REGEXP
|
11
|
+
|
14
12
|
UNLABELD_NAME = "<unlabeled transaction>".freeze
|
15
13
|
MESSAGE_PREFIX = "[Tracing]"
|
16
14
|
|
@@ -58,6 +56,10 @@ module Sentry
|
|
58
56
|
# @return [Hash]
|
59
57
|
attr_reader :contexts
|
60
58
|
|
59
|
+
# The Profiler instance for this transaction.
|
60
|
+
# @return [Profiler]
|
61
|
+
attr_reader :profiler
|
62
|
+
|
61
63
|
def initialize(
|
62
64
|
hub:,
|
63
65
|
name: nil,
|
@@ -83,9 +85,12 @@ module Sentry
|
|
83
85
|
@effective_sample_rate = nil
|
84
86
|
@contexts = {}
|
85
87
|
@measurements = {}
|
88
|
+
@profiler = Profiler.new(@configuration)
|
86
89
|
init_span_recorder
|
87
90
|
end
|
88
91
|
|
92
|
+
# @deprecated use Sentry.continue_trace instead.
|
93
|
+
#
|
89
94
|
# Initalizes a Transaction instance with a Sentry trace string from another transaction (usually from an external request).
|
90
95
|
#
|
91
96
|
# The original transaction will become the parent of the new Transaction instance. And they will share the same `trace_id`.
|
@@ -126,18 +131,10 @@ module Sentry
|
|
126
131
|
)
|
127
132
|
end
|
128
133
|
|
129
|
-
#
|
130
|
-
#
|
131
|
-
# @param sentry_trace [String] the sentry-trace header value from the previous transaction.
|
134
|
+
# @deprecated Use Sentry::PropagationContext.extract_sentry_trace instead.
|
132
135
|
# @return [Array, nil]
|
133
136
|
def self.extract_sentry_trace(sentry_trace)
|
134
|
-
|
135
|
-
return nil if match.nil?
|
136
|
-
|
137
|
-
trace_id, parent_span_id, sampled_flag = match[1..3]
|
138
|
-
parent_sampled = sampled_flag.nil? ? nil : sampled_flag != "0"
|
139
|
-
|
140
|
-
[trace_id, parent_span_id, parent_sampled]
|
137
|
+
PropagationContext.extract_sentry_trace(sentry_trace)
|
141
138
|
end
|
142
139
|
|
143
140
|
# @return [Hash]
|
@@ -254,6 +251,8 @@ module Sentry
|
|
254
251
|
@name = UNLABELD_NAME
|
255
252
|
end
|
256
253
|
|
254
|
+
@profiler.stop
|
255
|
+
|
257
256
|
if @sampled
|
258
257
|
event = hub.current_client.event_from_transaction(self)
|
259
258
|
hub.capture_event(event)
|
@@ -288,6 +287,13 @@ module Sentry
|
|
288
287
|
@contexts[key] = value
|
289
288
|
end
|
290
289
|
|
290
|
+
# Start the profiler.
|
291
|
+
# @return [void]
|
292
|
+
def start_profiler!
|
293
|
+
profiler.set_initial_sample_decision(sampled)
|
294
|
+
profiler.start
|
295
|
+
end
|
296
|
+
|
291
297
|
protected
|
292
298
|
|
293
299
|
def init_span_recorder(limit = 1000)
|
@@ -308,6 +314,7 @@ module Sentry
|
|
308
314
|
items = {
|
309
315
|
"trace_id" => trace_id,
|
310
316
|
"sample_rate" => effective_sample_rate&.to_s,
|
317
|
+
"sampled" => sampled&.to_s,
|
311
318
|
"environment" => @environment,
|
312
319
|
"release" => @release,
|
313
320
|
"public_key" => @dsn&.public_key
|
@@ -8,15 +8,15 @@ 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
|
-
|
14
11
|
# @return [Hash]
|
15
12
|
attr_accessor :measurements
|
16
13
|
|
17
14
|
# @return [Float, nil]
|
18
15
|
attr_reader :start_timestamp
|
19
16
|
|
17
|
+
# @return [Hash, nil]
|
18
|
+
attr_accessor :profile
|
19
|
+
|
20
20
|
def initialize(transaction:, **options)
|
21
21
|
super(**options)
|
22
22
|
|
@@ -32,6 +32,8 @@ module Sentry
|
|
32
32
|
|
33
33
|
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
|
34
34
|
self.spans = finished_spans.map(&:to_hash)
|
35
|
+
|
36
|
+
populate_profile(transaction)
|
35
37
|
end
|
36
38
|
|
37
39
|
# Sets the event's start_timestamp.
|
@@ -49,5 +51,30 @@ module Sentry
|
|
49
51
|
data[:measurements] = @measurements
|
50
52
|
data
|
51
53
|
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def populate_profile(transaction)
|
58
|
+
profile_hash = transaction.profiler.to_hash
|
59
|
+
return if profile_hash.empty?
|
60
|
+
|
61
|
+
profile_hash.merge!(
|
62
|
+
environment: environment,
|
63
|
+
release: release,
|
64
|
+
timestamp: Time.at(start_timestamp).iso8601,
|
65
|
+
device: { architecture: Scope.os_context[:machine] },
|
66
|
+
os: { name: Scope.os_context[:name], version: Scope.os_context[:version] },
|
67
|
+
runtime: Scope.runtime_context,
|
68
|
+
transaction: {
|
69
|
+
id: event_id,
|
70
|
+
name: transaction.name,
|
71
|
+
trace_id: transaction.trace_id,
|
72
|
+
# TODO-neel-profiler stubbed for now, see thread_id note in profiler.rb
|
73
|
+
active_thead_id: '0'
|
74
|
+
}
|
75
|
+
)
|
76
|
+
|
77
|
+
self.profile = profile_hash
|
78
|
+
end
|
52
79
|
end
|
53
80
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -18,7 +18,8 @@ module Sentry
|
|
18
18
|
:network_error,
|
19
19
|
:sample_rate,
|
20
20
|
:before_send,
|
21
|
-
:event_processor
|
21
|
+
:event_processor,
|
22
|
+
:insufficient_data
|
22
23
|
]
|
23
24
|
|
24
25
|
include LoggingHelper
|
@@ -143,7 +144,7 @@ module Sentry
|
|
143
144
|
sent_at: Sentry.utc_now.iso8601
|
144
145
|
}
|
145
146
|
|
146
|
-
if event.is_a?(
|
147
|
+
if event.is_a?(Event) && event.dynamic_sampling_context
|
147
148
|
envelope_headers[:trace] = event.dynamic_sampling_context
|
148
149
|
end
|
149
150
|
|
@@ -154,6 +155,13 @@ module Sentry
|
|
154
155
|
event_payload
|
155
156
|
)
|
156
157
|
|
158
|
+
if event.is_a?(TransactionEvent) && event.profile
|
159
|
+
envelope.add_item(
|
160
|
+
{ type: 'profile', content_type: 'application/json' },
|
161
|
+
event.profile
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
157
165
|
client_report_headers, client_report_payload = fetch_pending_client_report
|
158
166
|
envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
|
159
167
|
|
@@ -178,7 +186,7 @@ module Sentry
|
|
178
186
|
reason, type = key
|
179
187
|
|
180
188
|
# 'event' has to be mapped to 'error'
|
181
|
-
category = type == '
|
189
|
+
category = type == 'event' ? 'error' : type
|
182
190
|
|
183
191
|
{ reason: reason, category: category, quantity: val }
|
184
192
|
end
|
@@ -4,9 +4,15 @@ module Sentry
|
|
4
4
|
module ArgumentCheckingHelper
|
5
5
|
private
|
6
6
|
|
7
|
-
def check_argument_type!(argument,
|
8
|
-
unless argument.is_a?(
|
9
|
-
raise ArgumentError, "expect the argument to be a #{
|
7
|
+
def check_argument_type!(argument, *expected_types)
|
8
|
+
unless expected_types.any? { |t| argument.is_a?(t) }
|
9
|
+
raise ArgumentError, "expect the argument to be a #{expected_types.join(' or ')}, got #{argument.class} (#{argument.inspect})"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_argument_includes!(argument, values)
|
14
|
+
unless values.include?(argument)
|
15
|
+
raise ArgumentError, "expect the argument to be one of #{values.map(&:inspect).join(' or ')}, got #{argument.inspect}"
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -15,11 +15,13 @@ require "sentry/logger"
|
|
15
15
|
require "sentry/event"
|
16
16
|
require "sentry/error_event"
|
17
17
|
require "sentry/transaction_event"
|
18
|
+
require "sentry/check_in_event"
|
18
19
|
require "sentry/span"
|
19
20
|
require "sentry/transaction"
|
20
21
|
require "sentry/hub"
|
21
22
|
require "sentry/background_worker"
|
22
23
|
require "sentry/session_flusher"
|
24
|
+
require "sentry/cron/monitor_check_ins"
|
23
25
|
|
24
26
|
[
|
25
27
|
"sentry/rake",
|
@@ -73,20 +75,30 @@ module Sentry
|
|
73
75
|
##### Patch Registration #####
|
74
76
|
|
75
77
|
# @!visibility private
|
76
|
-
def register_patch(&block)
|
77
|
-
|
78
|
+
def register_patch(key, patch = nil, target = nil, &block)
|
79
|
+
if patch && block
|
80
|
+
raise ArgumentError.new("Please provide either a patch and its target OR a block, but not both")
|
81
|
+
end
|
82
|
+
|
83
|
+
if block
|
84
|
+
registered_patches[key] = block
|
85
|
+
else
|
86
|
+
registered_patches[key] = proc do
|
87
|
+
target.send(:prepend, patch) unless target.ancestors.include?(patch)
|
88
|
+
end
|
89
|
+
end
|
78
90
|
end
|
79
91
|
|
80
92
|
# @!visibility private
|
81
93
|
def apply_patches(config)
|
82
|
-
registered_patches.each do |patch|
|
83
|
-
patch.call(config)
|
94
|
+
registered_patches.each do |key, patch|
|
95
|
+
patch.call(config) if config.enabled_patches.include?(key)
|
84
96
|
end
|
85
97
|
end
|
86
98
|
|
87
99
|
# @!visibility private
|
88
100
|
def registered_patches
|
89
|
-
@registered_patches ||=
|
101
|
+
@registered_patches ||= {}
|
90
102
|
end
|
91
103
|
|
92
104
|
##### Integrations #####
|
@@ -420,6 +432,24 @@ module Sentry
|
|
420
432
|
get_current_hub.capture_event(event)
|
421
433
|
end
|
422
434
|
|
435
|
+
# Captures a check-in and sends it to Sentry via the currently active hub.
|
436
|
+
#
|
437
|
+
# @param slug [String] identifier of this monitor
|
438
|
+
# @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
|
439
|
+
#
|
440
|
+
# @param [Hash] options extra check-in options
|
441
|
+
# @option options [String] check_in_id for updating the status of an existing monitor
|
442
|
+
# @option options [Integer] duration seconds elapsed since this monitor started
|
443
|
+
# @option options [Cron::MonitorConfig] monitor_config configuration for this monitor
|
444
|
+
#
|
445
|
+
# @yieldparam scope [Scope]
|
446
|
+
#
|
447
|
+
# @return [String, nil] The {CheckInEvent#check_in_id} to use for later updates on the same slug
|
448
|
+
def capture_check_in(slug, status, **options, &block)
|
449
|
+
return unless initialized?
|
450
|
+
get_current_hub.capture_check_in(slug, status, **options, &block)
|
451
|
+
end
|
452
|
+
|
423
453
|
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
424
454
|
#
|
425
455
|
# @return [Transaction, nil]
|
@@ -479,6 +509,42 @@ module Sentry
|
|
479
509
|
Scope.add_global_event_processor(&block)
|
480
510
|
end
|
481
511
|
|
512
|
+
# Returns the traceparent (sentry-trace) header for distributed tracing.
|
513
|
+
# Can be either from the currently active span or the propagation context.
|
514
|
+
#
|
515
|
+
# @return [String, nil]
|
516
|
+
def get_traceparent
|
517
|
+
return nil unless initialized?
|
518
|
+
get_current_hub.get_traceparent
|
519
|
+
end
|
520
|
+
|
521
|
+
# Returns the baggage header for distributed tracing.
|
522
|
+
# Can be either from the currently active span or the propagation context.
|
523
|
+
#
|
524
|
+
# @return [String, nil]
|
525
|
+
def get_baggage
|
526
|
+
return nil unless initialized?
|
527
|
+
get_current_hub.get_baggage
|
528
|
+
end
|
529
|
+
|
530
|
+
# Returns the a Hash containing sentry-trace and baggage.
|
531
|
+
# Can be either from the currently active span or the propagation context.
|
532
|
+
#
|
533
|
+
# @return [Hash, nil]
|
534
|
+
def get_trace_propagation_headers
|
535
|
+
return nil unless initialized?
|
536
|
+
get_current_hub.get_trace_propagation_headers
|
537
|
+
end
|
538
|
+
|
539
|
+
# Continue an incoming trace from a rack env like hash.
|
540
|
+
#
|
541
|
+
# @param env [Hash]
|
542
|
+
# @return [Transaction, nil]
|
543
|
+
def continue_trace(env, **options)
|
544
|
+
return nil unless initialized?
|
545
|
+
get_current_hub.continue_trace(env, **options)
|
546
|
+
end
|
547
|
+
|
482
548
|
##### Helpers #####
|
483
549
|
|
484
550
|
# @!visibility private
|
@@ -509,3 +575,4 @@ end
|
|
509
575
|
# patches
|
510
576
|
require "sentry/net/http"
|
511
577
|
require "sentry/redis"
|
578
|
+
require "sentry/puma"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.13.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: 2023-
|
11
|
+
date: 2023-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -42,7 +42,6 @@ files:
|
|
42
42
|
- ".rspec"
|
43
43
|
- ".yardopts"
|
44
44
|
- CHANGELOG.md
|
45
|
-
- CODE_OF_CONDUCT.md
|
46
45
|
- Gemfile
|
47
46
|
- LICENSE.txt
|
48
47
|
- Makefile
|
@@ -57,10 +56,14 @@ files:
|
|
57
56
|
- lib/sentry/breadcrumb.rb
|
58
57
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
59
58
|
- lib/sentry/breadcrumb_buffer.rb
|
59
|
+
- lib/sentry/check_in_event.rb
|
60
60
|
- lib/sentry/client.rb
|
61
61
|
- lib/sentry/configuration.rb
|
62
62
|
- lib/sentry/core_ext/object/deep_dup.rb
|
63
63
|
- lib/sentry/core_ext/object/duplicable.rb
|
64
|
+
- lib/sentry/cron/monitor_check_ins.rb
|
65
|
+
- lib/sentry/cron/monitor_config.rb
|
66
|
+
- lib/sentry/cron/monitor_schedule.rb
|
64
67
|
- lib/sentry/dsn.rb
|
65
68
|
- lib/sentry/envelope.rb
|
66
69
|
- lib/sentry/error_event.rb
|
@@ -78,6 +81,9 @@ files:
|
|
78
81
|
- lib/sentry/linecache.rb
|
79
82
|
- lib/sentry/logger.rb
|
80
83
|
- lib/sentry/net/http.rb
|
84
|
+
- lib/sentry/profiler.rb
|
85
|
+
- lib/sentry/propagation_context.rb
|
86
|
+
- lib/sentry/puma.rb
|
81
87
|
- lib/sentry/rack.rb
|
82
88
|
- lib/sentry/rack/capture_exceptions.rb
|
83
89
|
- lib/sentry/rake.rb
|