sentry-ruby 5.4.2 → 5.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/Gemfile +13 -14
- data/README.md +11 -8
- data/Rakefile +8 -1
- data/lib/sentry/background_worker.rb +8 -1
- data/lib/sentry/backpressure_monitor.rb +75 -0
- data/lib/sentry/backtrace.rb +1 -1
- data/lib/sentry/baggage.rb +70 -0
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +77 -19
- data/lib/sentry/configuration.rb +177 -29
- data/lib/sentry/cron/configuration.rb +23 -0
- data/lib/sentry/cron/monitor_check_ins.rb +75 -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 +7 -29
- data/lib/sentry/hub.rb +100 -4
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/request.rb +6 -16
- data/lib/sentry/interfaces/single_exception.rb +13 -3
- data/lib/sentry/net/http.rb +37 -46
- 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 +4 -5
- data/lib/sentry/rake.rb +1 -14
- data/lib/sentry/redis.rb +41 -23
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/scope.rb +81 -16
- data/lib/sentry/session.rb +5 -7
- data/lib/sentry/span.rb +57 -10
- data/lib/sentry/test_helper.rb +19 -11
- data/lib/sentry/transaction.rb +183 -30
- data/lib/sentry/transaction_event.rb +51 -0
- data/lib/sentry/transport/configuration.rb +74 -1
- data/lib/sentry/transport/http_transport.rb +68 -37
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +39 -24
- data/lib/sentry/utils/argument_checking_helper.rb +9 -3
- data/lib/sentry/utils/encoding_helper.rb +22 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +116 -41
- metadata +14 -3
- data/CODE_OF_CONDUCT.md +0 -74
@@ -14,11 +14,19 @@ module Sentry
|
|
14
14
|
RATE_LIMIT_HEADER = "x-sentry-rate-limits"
|
15
15
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
16
16
|
|
17
|
+
# The list of errors ::Net::HTTP is known to raise
|
18
|
+
# See https://github.com/ruby/ruby/blob/b0c639f249165d759596f9579fa985cb30533de6/lib/bundler/fetcher.rb#L281-L286
|
19
|
+
HTTP_ERRORS = [
|
20
|
+
Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
|
21
|
+
Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
|
22
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
|
23
|
+
Zlib::BufError, Errno::EHOSTUNREACH, Errno::ECONNREFUSED
|
24
|
+
].freeze
|
25
|
+
|
26
|
+
|
17
27
|
def initialize(*args)
|
18
28
|
super
|
19
|
-
@
|
20
|
-
|
21
|
-
log_debug("Sentry HTTP Transport will connect to #{@dsn.server}")
|
29
|
+
log_debug("Sentry HTTP Transport will connect to #{@dsn.server}") if @dsn
|
22
30
|
end
|
23
31
|
|
24
32
|
def send_data(data)
|
@@ -32,34 +40,76 @@ module Sentry
|
|
32
40
|
headers = {
|
33
41
|
'Content-Type' => CONTENT_TYPE,
|
34
42
|
'Content-Encoding' => encoding,
|
35
|
-
'X-Sentry-Auth' => generate_auth_header,
|
36
43
|
'User-Agent' => USER_AGENT
|
37
44
|
}
|
38
45
|
|
46
|
+
auth_header = generate_auth_header
|
47
|
+
headers['X-Sentry-Auth'] = auth_header if auth_header
|
48
|
+
|
39
49
|
response = conn.start do |http|
|
40
|
-
request = ::Net::HTTP::Post.new(
|
50
|
+
request = ::Net::HTTP::Post.new(endpoint, headers)
|
41
51
|
request.body = data
|
42
52
|
http.request(request)
|
43
53
|
end
|
44
54
|
|
45
55
|
if response.code.match?(/\A2\d{2}/)
|
46
|
-
if has_rate_limited_header?(response)
|
47
|
-
|
48
|
-
|
56
|
+
handle_rate_limited_response(response) if has_rate_limited_header?(response)
|
57
|
+
elsif response.code == "429"
|
58
|
+
log_debug("the server responded with status 429")
|
59
|
+
handle_rate_limited_response(response)
|
49
60
|
else
|
50
61
|
error_info = "the server responded with status #{response.code}"
|
62
|
+
error_info += "\nbody: #{response.body}"
|
63
|
+
error_info += " Error in headers is: #{response['x-sentry-error']}" if response['x-sentry-error']
|
64
|
+
|
65
|
+
raise Sentry::ExternalError, error_info
|
66
|
+
end
|
67
|
+
rescue SocketError, *HTTP_ERRORS => e
|
68
|
+
on_error if respond_to?(:on_error)
|
69
|
+
raise Sentry::ExternalError.new(e&.message)
|
70
|
+
end
|
71
|
+
|
72
|
+
def endpoint
|
73
|
+
@dsn.envelope_endpoint
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate_auth_header
|
77
|
+
return nil unless @dsn
|
78
|
+
|
79
|
+
now = Sentry.utc_now.to_i
|
80
|
+
fields = {
|
81
|
+
'sentry_version' => PROTOCOL_VERSION,
|
82
|
+
'sentry_client' => USER_AGENT,
|
83
|
+
'sentry_timestamp' => now,
|
84
|
+
'sentry_key' => @dsn.public_key
|
85
|
+
}
|
86
|
+
fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
|
87
|
+
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
88
|
+
end
|
51
89
|
|
52
|
-
|
53
|
-
|
90
|
+
def conn
|
91
|
+
server = URI(@dsn.server)
|
92
|
+
|
93
|
+
# connection respects proxy setting from @transport_configuration, or environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)
|
94
|
+
# Net::HTTP will automatically read the env vars.
|
95
|
+
# See https://ruby-doc.org/3.2.2/stdlibs/net/Net/HTTP.html#class-Net::HTTP-label-Proxies
|
96
|
+
connection =
|
97
|
+
if proxy = normalize_proxy(@transport_configuration.proxy)
|
98
|
+
::Net::HTTP.new(server.hostname, server.port, proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
|
54
99
|
else
|
55
|
-
|
56
|
-
error_info += " Error in headers is: #{response['x-sentry-error']}" if response['x-sentry-error']
|
100
|
+
::Net::HTTP.new(server.hostname, server.port)
|
57
101
|
end
|
58
102
|
|
59
|
-
|
103
|
+
connection.use_ssl = server.scheme == "https"
|
104
|
+
connection.read_timeout = @transport_configuration.timeout
|
105
|
+
connection.write_timeout = @transport_configuration.timeout if connection.respond_to?(:write_timeout)
|
106
|
+
connection.open_timeout = @transport_configuration.open_timeout
|
107
|
+
|
108
|
+
ssl_configuration.each do |key, value|
|
109
|
+
connection.send("#{key}=", value)
|
60
110
|
end
|
61
|
-
|
62
|
-
|
111
|
+
|
112
|
+
connection
|
63
113
|
end
|
64
114
|
|
65
115
|
private
|
@@ -126,28 +176,9 @@ module Sentry
|
|
126
176
|
@transport_configuration.encoding == GZIP_ENCODING && data.bytesize >= GZIP_THRESHOLD
|
127
177
|
end
|
128
178
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
connection =
|
133
|
-
if proxy = normalize_proxy(@transport_configuration.proxy)
|
134
|
-
::Net::HTTP.new(server.hostname, server.port, proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
|
135
|
-
else
|
136
|
-
::Net::HTTP.new(server.hostname, server.port, nil)
|
137
|
-
end
|
138
|
-
|
139
|
-
connection.use_ssl = server.scheme == "https"
|
140
|
-
connection.read_timeout = @transport_configuration.timeout
|
141
|
-
connection.write_timeout = @transport_configuration.timeout if connection.respond_to?(:write_timeout)
|
142
|
-
connection.open_timeout = @transport_configuration.open_timeout
|
143
|
-
|
144
|
-
ssl_configuration.each do |key, value|
|
145
|
-
connection.send("#{key}=", value)
|
146
|
-
end
|
147
|
-
|
148
|
-
connection
|
149
|
-
end
|
150
|
-
|
179
|
+
# @param proxy [String, URI, Hash] Proxy config value passed into `config.transport`.
|
180
|
+
# Accepts either a URI formatted string, URI, or a hash with the `uri`, `user`, and `password` keys.
|
181
|
+
# @return [Hash] Normalized proxy config that will be passed into `Net::HTTP`
|
151
182
|
def normalize_proxy(proxy)
|
152
183
|
return proxy unless proxy
|
153
184
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "zlib"
|
5
|
+
|
6
|
+
module Sentry
|
7
|
+
# Designed to just report events to Spotlight in development.
|
8
|
+
class SpotlightTransport < HTTPTransport
|
9
|
+
DEFAULT_SIDECAR_URL = "http://localhost:8969/stream"
|
10
|
+
MAX_FAILED_REQUESTS = 3
|
11
|
+
|
12
|
+
def initialize(configuration)
|
13
|
+
super
|
14
|
+
@sidecar_url = configuration.spotlight.is_a?(String) ? configuration.spotlight : DEFAULT_SIDECAR_URL
|
15
|
+
@failed = 0
|
16
|
+
@logged = false
|
17
|
+
|
18
|
+
log_debug("[Spotlight] initialized for url #{@sidecar_url}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def endpoint
|
22
|
+
"/stream"
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_data(data)
|
26
|
+
if @failed >= MAX_FAILED_REQUESTS
|
27
|
+
unless @logged
|
28
|
+
log_debug("[Spotlight] disabling because of too many request failures")
|
29
|
+
@logged = true
|
30
|
+
end
|
31
|
+
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_error
|
39
|
+
@failed += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
# Similar to HTTPTransport connection, but does not support Proxy and SSL
|
43
|
+
def conn
|
44
|
+
sidecar = URI(@sidecar_url)
|
45
|
+
connection = ::Net::HTTP.new(sidecar.hostname, sidecar.port, nil)
|
46
|
+
connection.use_ssl = false
|
47
|
+
connection
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -18,7 +18,9 @@ module Sentry
|
|
18
18
|
:network_error,
|
19
19
|
:sample_rate,
|
20
20
|
:before_send,
|
21
|
-
:event_processor
|
21
|
+
:event_processor,
|
22
|
+
:insufficient_data,
|
23
|
+
:backpressure
|
22
24
|
]
|
23
25
|
|
24
26
|
include LoggingHelper
|
@@ -73,7 +75,7 @@ module Sentry
|
|
73
75
|
result, oversized = item.serialize
|
74
76
|
|
75
77
|
if oversized
|
76
|
-
|
78
|
+
log_debug("Envelope item [#{item.type}] is still oversized after size reduction: {#{item.size_breakdown}}")
|
77
79
|
|
78
80
|
next
|
79
81
|
end
|
@@ -118,16 +120,8 @@ module Sentry
|
|
118
120
|
!!delay && delay > Time.now
|
119
121
|
end
|
120
122
|
|
121
|
-
def
|
122
|
-
|
123
|
-
fields = {
|
124
|
-
'sentry_version' => PROTOCOL_VERSION,
|
125
|
-
'sentry_client' => USER_AGENT,
|
126
|
-
'sentry_timestamp' => now,
|
127
|
-
'sentry_key' => @dsn.public_key
|
128
|
-
}
|
129
|
-
fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
|
130
|
-
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
123
|
+
def any_rate_limited?
|
124
|
+
@rate_limits.values.any? { |t| t && t > Time.now }
|
131
125
|
end
|
132
126
|
|
133
127
|
def envelope_from_event(event)
|
@@ -136,20 +130,31 @@ module Sentry
|
|
136
130
|
event_id = event_payload[:event_id] || event_payload["event_id"]
|
137
131
|
item_type = event_payload[:type] || event_payload["type"]
|
138
132
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
)
|
133
|
+
envelope_headers = {
|
134
|
+
event_id: event_id,
|
135
|
+
dsn: @dsn.to_s,
|
136
|
+
sdk: Sentry.sdk_meta,
|
137
|
+
sent_at: Sentry.utc_now.iso8601
|
138
|
+
}
|
139
|
+
|
140
|
+
if event.is_a?(Event) && event.dynamic_sampling_context
|
141
|
+
envelope_headers[:trace] = event.dynamic_sampling_context
|
142
|
+
end
|
143
|
+
|
144
|
+
envelope = Envelope.new(envelope_headers)
|
147
145
|
|
148
146
|
envelope.add_item(
|
149
147
|
{ type: item_type, content_type: 'application/json' },
|
150
148
|
event_payload
|
151
149
|
)
|
152
150
|
|
151
|
+
if event.is_a?(TransactionEvent) && event.profile
|
152
|
+
envelope.add_item(
|
153
|
+
{ type: 'profile', content_type: 'application/json' },
|
154
|
+
event.profile
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
153
158
|
client_report_headers, client_report_payload = fetch_pending_client_report
|
154
159
|
envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
|
155
160
|
|
@@ -163,18 +168,27 @@ module Sentry
|
|
163
168
|
@discarded_events[[reason, item_type]] += 1
|
164
169
|
end
|
165
170
|
|
171
|
+
def flush
|
172
|
+
client_report_headers, client_report_payload = fetch_pending_client_report(force: true)
|
173
|
+
return unless client_report_headers
|
174
|
+
|
175
|
+
envelope = Envelope.new
|
176
|
+
envelope.add_item(client_report_headers, client_report_payload)
|
177
|
+
send_envelope(envelope)
|
178
|
+
end
|
179
|
+
|
166
180
|
private
|
167
181
|
|
168
|
-
def fetch_pending_client_report
|
182
|
+
def fetch_pending_client_report(force: false)
|
169
183
|
return nil unless @send_client_reports
|
170
|
-
return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
184
|
+
return nil if !force && @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
171
185
|
return nil if @discarded_events.empty?
|
172
186
|
|
173
187
|
discarded_events_hash = @discarded_events.map do |key, val|
|
174
188
|
reason, type = key
|
175
189
|
|
176
190
|
# 'event' has to be mapped to 'error'
|
177
|
-
category = type == '
|
191
|
+
category = type == 'event' ? 'error' : type
|
178
192
|
|
179
193
|
{ reason: reason, category: category, quantity: val }
|
180
194
|
end
|
@@ -194,7 +208,7 @@ module Sentry
|
|
194
208
|
def reject_rate_limited_items(envelope)
|
195
209
|
envelope.items.reject! do |item|
|
196
210
|
if is_rate_limited?(item.type)
|
197
|
-
|
211
|
+
log_debug("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
|
198
212
|
record_lost_event(:ratelimit_backoff, item.type)
|
199
213
|
|
200
214
|
true
|
@@ -208,3 +222,4 @@ end
|
|
208
222
|
|
209
223
|
require "sentry/transport/dummy_transport"
|
210
224
|
require "sentry/transport/http_transport"
|
225
|
+
require "sentry/transport/spotlight_transport"
|
@@ -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
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module Utils
|
5
|
+
module EncodingHelper
|
6
|
+
def self.encode_to_utf_8(value)
|
7
|
+
if value.encoding != Encoding::UTF_8 && value.respond_to?(:force_encoding)
|
8
|
+
value = value.dup.force_encoding(Encoding::UTF_8)
|
9
|
+
end
|
10
|
+
|
11
|
+
value = value.scrub unless value.valid_encoding?
|
12
|
+
value
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.valid_utf_8?(value)
|
16
|
+
return true unless value.respond_to?(:force_encoding)
|
17
|
+
|
18
|
+
value.dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -8,17 +8,21 @@ require "sentry/version"
|
|
8
8
|
require "sentry/exceptions"
|
9
9
|
require "sentry/core_ext/object/deep_dup"
|
10
10
|
require "sentry/utils/argument_checking_helper"
|
11
|
+
require "sentry/utils/encoding_helper"
|
11
12
|
require "sentry/utils/logging_helper"
|
12
13
|
require "sentry/configuration"
|
13
14
|
require "sentry/logger"
|
14
15
|
require "sentry/event"
|
15
16
|
require "sentry/error_event"
|
16
17
|
require "sentry/transaction_event"
|
18
|
+
require "sentry/check_in_event"
|
17
19
|
require "sentry/span"
|
18
20
|
require "sentry/transaction"
|
19
21
|
require "sentry/hub"
|
20
22
|
require "sentry/background_worker"
|
21
23
|
require "sentry/session_flusher"
|
24
|
+
require "sentry/backpressure_monitor"
|
25
|
+
require "sentry/cron/monitor_check_ins"
|
22
26
|
|
23
27
|
[
|
24
28
|
"sentry/rake",
|
@@ -39,6 +43,8 @@ module Sentry
|
|
39
43
|
|
40
44
|
SENTRY_TRACE_HEADER_NAME = "sentry-trace".freeze
|
41
45
|
|
46
|
+
BAGGAGE_HEADER_NAME = "baggage".freeze
|
47
|
+
|
42
48
|
THREAD_LOCAL = :sentry_hub
|
43
49
|
|
44
50
|
class << self
|
@@ -60,30 +66,44 @@ module Sentry
|
|
60
66
|
end
|
61
67
|
|
62
68
|
# @!attribute [rw] background_worker
|
63
|
-
# @return [BackgroundWorker
|
69
|
+
# @return [BackgroundWorker]
|
64
70
|
attr_accessor :background_worker
|
65
71
|
|
66
72
|
# @!attribute [r] session_flusher
|
67
73
|
# @return [SessionFlusher, nil]
|
68
74
|
attr_reader :session_flusher
|
69
75
|
|
76
|
+
# @!attribute [r] backpressure_monitor
|
77
|
+
# @return [BackpressureMonitor, nil]
|
78
|
+
attr_reader :backpressure_monitor
|
79
|
+
|
70
80
|
##### Patch Registration #####
|
71
81
|
|
72
82
|
# @!visibility private
|
73
|
-
def register_patch(&block)
|
74
|
-
|
83
|
+
def register_patch(key, patch = nil, target = nil, &block)
|
84
|
+
if patch && block
|
85
|
+
raise ArgumentError.new("Please provide either a patch and its target OR a block, but not both")
|
86
|
+
end
|
87
|
+
|
88
|
+
if block
|
89
|
+
registered_patches[key] = block
|
90
|
+
else
|
91
|
+
registered_patches[key] = proc do
|
92
|
+
target.send(:prepend, patch) unless target.ancestors.include?(patch)
|
93
|
+
end
|
94
|
+
end
|
75
95
|
end
|
76
96
|
|
77
97
|
# @!visibility private
|
78
98
|
def apply_patches(config)
|
79
|
-
registered_patches.each do |patch|
|
80
|
-
patch.call(config)
|
99
|
+
registered_patches.each do |key, patch|
|
100
|
+
patch.call(config) if config.enabled_patches.include?(key)
|
81
101
|
end
|
82
102
|
end
|
83
103
|
|
84
104
|
# @!visibility private
|
85
105
|
def registered_patches
|
86
|
-
@registered_patches ||=
|
106
|
+
@registered_patches ||= {}
|
87
107
|
end
|
88
108
|
|
89
109
|
##### Integrations #####
|
@@ -202,17 +222,9 @@ module Sentry
|
|
202
222
|
Thread.current.thread_variable_set(THREAD_LOCAL, hub)
|
203
223
|
@main_hub = hub
|
204
224
|
@background_worker = Sentry::BackgroundWorker.new(config)
|
205
|
-
|
206
|
-
@
|
207
|
-
|
208
|
-
else
|
209
|
-
nil
|
210
|
-
end
|
211
|
-
|
212
|
-
if config.capture_exception_frame_locals
|
213
|
-
exception_locals_tp.enable
|
214
|
-
end
|
215
|
-
|
225
|
+
@session_flusher = config.auto_session_tracking ? Sentry::SessionFlusher.new(config, client) : nil
|
226
|
+
@backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
|
227
|
+
exception_locals_tp.enable if config.include_local_variables
|
216
228
|
at_exit { close }
|
217
229
|
end
|
218
230
|
|
@@ -221,20 +233,27 @@ module Sentry
|
|
221
233
|
#
|
222
234
|
# @return [void]
|
223
235
|
def close
|
224
|
-
if @background_worker
|
225
|
-
@background_worker.shutdown
|
226
|
-
@background_worker = nil
|
227
|
-
end
|
228
|
-
|
229
236
|
if @session_flusher
|
237
|
+
@session_flusher.flush
|
230
238
|
@session_flusher.kill
|
231
239
|
@session_flusher = nil
|
232
240
|
end
|
233
241
|
|
234
|
-
if
|
235
|
-
|
242
|
+
if @backpressure_monitor
|
243
|
+
@backpressure_monitor.kill
|
244
|
+
@backpressure_monitor = nil
|
236
245
|
end
|
237
246
|
|
247
|
+
if client = get_current_client
|
248
|
+
client.transport.flush
|
249
|
+
|
250
|
+
if client.configuration.include_local_variables
|
251
|
+
exception_locals_tp.disable
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
@background_worker.shutdown
|
256
|
+
|
238
257
|
@main_hub = nil
|
239
258
|
Thread.current.thread_variable_set(THREAD_LOCAL, nil)
|
240
259
|
end
|
@@ -348,7 +367,7 @@ module Sentry
|
|
348
367
|
# @yieldparam scope [Scope]
|
349
368
|
# @return [void]
|
350
369
|
def with_scope(&block)
|
351
|
-
return unless initialized?
|
370
|
+
return yield unless initialized?
|
352
371
|
get_current_hub.with_scope(&block)
|
353
372
|
end
|
354
373
|
|
@@ -417,6 +436,22 @@ module Sentry
|
|
417
436
|
get_current_hub.capture_event(event)
|
418
437
|
end
|
419
438
|
|
439
|
+
# Captures a check-in and sends it to Sentry via the currently active hub.
|
440
|
+
#
|
441
|
+
# @param slug [String] identifier of this monitor
|
442
|
+
# @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
|
443
|
+
#
|
444
|
+
# @param [Hash] options extra check-in options
|
445
|
+
# @option options [String] check_in_id for updating the status of an existing monitor
|
446
|
+
# @option options [Integer] duration seconds elapsed since this monitor started
|
447
|
+
# @option options [Cron::MonitorConfig] monitor_config configuration for this monitor
|
448
|
+
#
|
449
|
+
# @return [String, nil] The {CheckInEvent#check_in_id} to use for later updates on the same slug
|
450
|
+
def capture_check_in(slug, status, **options)
|
451
|
+
return unless initialized?
|
452
|
+
get_current_hub.capture_check_in(slug, status, **options)
|
453
|
+
end
|
454
|
+
|
420
455
|
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
421
456
|
#
|
422
457
|
# @return [Transaction, nil]
|
@@ -439,22 +474,8 @@ module Sentry
|
|
439
474
|
# end
|
440
475
|
#
|
441
476
|
def with_child_span(**attributes, &block)
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
begin
|
446
|
-
current_span.with_child_span(**attributes) do |child_span|
|
447
|
-
get_current_scope.set_span(child_span)
|
448
|
-
result = yield(child_span)
|
449
|
-
end
|
450
|
-
ensure
|
451
|
-
get_current_scope.set_span(current_span)
|
452
|
-
end
|
453
|
-
|
454
|
-
result
|
455
|
-
else
|
456
|
-
yield(nil)
|
457
|
-
end
|
477
|
+
return yield(nil) unless Sentry.initialized?
|
478
|
+
get_current_hub.with_child_span(**attributes, &block)
|
458
479
|
end
|
459
480
|
|
460
481
|
# Returns the id of the lastly reported Sentry::Event.
|
@@ -473,6 +494,59 @@ module Sentry
|
|
473
494
|
!!exc.instance_variable_get(CAPTURED_SIGNATURE)
|
474
495
|
end
|
475
496
|
|
497
|
+
# Add a global event processor [Proc].
|
498
|
+
# These run before scope event processors.
|
499
|
+
#
|
500
|
+
# @yieldparam event [Event]
|
501
|
+
# @yieldparam hint [Hash, nil]
|
502
|
+
# @return [void]
|
503
|
+
#
|
504
|
+
# @example
|
505
|
+
# Sentry.add_global_event_processor do |event, hint|
|
506
|
+
# event.tags = { foo: 42 }
|
507
|
+
# event
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
def add_global_event_processor(&block)
|
511
|
+
Scope.add_global_event_processor(&block)
|
512
|
+
end
|
513
|
+
|
514
|
+
# Returns the traceparent (sentry-trace) header for distributed tracing.
|
515
|
+
# Can be either from the currently active span or the propagation context.
|
516
|
+
#
|
517
|
+
# @return [String, nil]
|
518
|
+
def get_traceparent
|
519
|
+
return nil unless initialized?
|
520
|
+
get_current_hub.get_traceparent
|
521
|
+
end
|
522
|
+
|
523
|
+
# Returns the baggage header for distributed tracing.
|
524
|
+
# Can be either from the currently active span or the propagation context.
|
525
|
+
#
|
526
|
+
# @return [String, nil]
|
527
|
+
def get_baggage
|
528
|
+
return nil unless initialized?
|
529
|
+
get_current_hub.get_baggage
|
530
|
+
end
|
531
|
+
|
532
|
+
# Returns the a Hash containing sentry-trace and baggage.
|
533
|
+
# Can be either from the currently active span or the propagation context.
|
534
|
+
#
|
535
|
+
# @return [Hash, nil]
|
536
|
+
def get_trace_propagation_headers
|
537
|
+
return nil unless initialized?
|
538
|
+
get_current_hub.get_trace_propagation_headers
|
539
|
+
end
|
540
|
+
|
541
|
+
# Continue an incoming trace from a rack env like hash.
|
542
|
+
#
|
543
|
+
# @param env [Hash]
|
544
|
+
# @return [Transaction, nil]
|
545
|
+
def continue_trace(env, **options)
|
546
|
+
return nil unless initialized?
|
547
|
+
get_current_hub.continue_trace(env, **options)
|
548
|
+
end
|
549
|
+
|
476
550
|
##### Helpers #####
|
477
551
|
|
478
552
|
# @!visibility private
|
@@ -503,3 +577,4 @@ end
|
|
503
577
|
# patches
|
504
578
|
require "sentry/net/http"
|
505
579
|
require "sentry/redis"
|
580
|
+
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.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-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
|
@@ -52,14 +51,21 @@ files:
|
|
52
51
|
- bin/setup
|
53
52
|
- lib/sentry-ruby.rb
|
54
53
|
- lib/sentry/background_worker.rb
|
54
|
+
- lib/sentry/backpressure_monitor.rb
|
55
55
|
- lib/sentry/backtrace.rb
|
56
|
+
- lib/sentry/baggage.rb
|
56
57
|
- lib/sentry/breadcrumb.rb
|
57
58
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
58
59
|
- lib/sentry/breadcrumb_buffer.rb
|
60
|
+
- lib/sentry/check_in_event.rb
|
59
61
|
- lib/sentry/client.rb
|
60
62
|
- lib/sentry/configuration.rb
|
61
63
|
- lib/sentry/core_ext/object/deep_dup.rb
|
62
64
|
- lib/sentry/core_ext/object/duplicable.rb
|
65
|
+
- lib/sentry/cron/configuration.rb
|
66
|
+
- lib/sentry/cron/monitor_check_ins.rb
|
67
|
+
- lib/sentry/cron/monitor_config.rb
|
68
|
+
- lib/sentry/cron/monitor_schedule.rb
|
63
69
|
- lib/sentry/dsn.rb
|
64
70
|
- lib/sentry/envelope.rb
|
65
71
|
- lib/sentry/error_event.rb
|
@@ -77,6 +83,9 @@ files:
|
|
77
83
|
- lib/sentry/linecache.rb
|
78
84
|
- lib/sentry/logger.rb
|
79
85
|
- lib/sentry/net/http.rb
|
86
|
+
- lib/sentry/profiler.rb
|
87
|
+
- lib/sentry/propagation_context.rb
|
88
|
+
- lib/sentry/puma.rb
|
80
89
|
- lib/sentry/rack.rb
|
81
90
|
- lib/sentry/rack/capture_exceptions.rb
|
82
91
|
- lib/sentry/rake.rb
|
@@ -93,8 +102,10 @@ files:
|
|
93
102
|
- lib/sentry/transport/configuration.rb
|
94
103
|
- lib/sentry/transport/dummy_transport.rb
|
95
104
|
- lib/sentry/transport/http_transport.rb
|
105
|
+
- lib/sentry/transport/spotlight_transport.rb
|
96
106
|
- lib/sentry/utils/argument_checking_helper.rb
|
97
107
|
- lib/sentry/utils/custom_inspection.rb
|
108
|
+
- lib/sentry/utils/encoding_helper.rb
|
98
109
|
- lib/sentry/utils/exception_cause_chain.rb
|
99
110
|
- lib/sentry/utils/logging_helper.rb
|
100
111
|
- lib/sentry/utils/real_ip.rb
|