sentry-ruby 5.4.2 → 5.16.1
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/.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
|