sentry-ruby 5.14.0 → 5.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -19
- data/lib/sentry/background_worker.rb +3 -1
- data/lib/sentry/client.rb +7 -0
- data/lib/sentry/configuration.rb +18 -1
- data/lib/sentry/cron/monitor_check_ins.rb +4 -3
- data/lib/sentry/transport/http_transport.rb +61 -32
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +1 -12
- data/lib/sentry/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76add924de8ccd4132764766cf92d057a7e4ee9554790688e2c2597b569097c2
|
4
|
+
data.tar.gz: 856d0936cb2ad123b3ca632e63cb8cf951e13f90755386dcb67b3cc63760ee69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 245ee7955da8f38b12db8e2ed18802fbb63a74efd5853968a91fe5e45551f17aa0dd95e8dd07458e1374817b33b3cfc6ab752406fea9f16f55a4027d204d622b
|
7
|
+
data.tar.gz: 7fd7cadec651b7464409154ed26eb41852bb2cfbf89bb3f57cecc102058a9b8498bf9f29670ebcd6c25048a1a353878adaadc8a8c1b816baf5b08baf0c380e54
|
data/Gemfile
CHANGED
@@ -12,28 +12,9 @@ gem "redis", "~> #{redis_rb_version}"
|
|
12
12
|
|
13
13
|
gem "puma"
|
14
14
|
|
15
|
-
gem "rake", "~> 12.0"
|
16
|
-
gem "rspec", "~> 3.0"
|
17
|
-
gem "rspec-retry"
|
18
15
|
gem "timecop"
|
19
|
-
gem "simplecov"
|
20
|
-
gem "simplecov-cobertura", "~> 1.4"
|
21
|
-
gem "rexml"
|
22
16
|
gem "stackprof" unless RUBY_PLATFORM == "java"
|
23
17
|
|
24
|
-
ruby_version = Gem::Version.new(RUBY_VERSION)
|
25
|
-
|
26
|
-
if ruby_version >= Gem::Version.new("2.6.0")
|
27
|
-
gem "debug", github: "ruby/debug", platform: :ruby
|
28
|
-
gem "irb"
|
29
|
-
|
30
|
-
if ruby_version >= Gem::Version.new("3.0.0")
|
31
|
-
gem "ruby-lsp-rspec"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
gem "pry"
|
36
|
-
|
37
18
|
gem "benchmark-ips"
|
38
19
|
gem "benchmark_driver"
|
39
20
|
gem "benchmark-ipsa"
|
@@ -41,3 +22,5 @@ gem "benchmark-memory"
|
|
41
22
|
|
42
23
|
gem "yard", github: "lsegal/yard"
|
43
24
|
gem "webrick"
|
25
|
+
|
26
|
+
eval_gemfile File.expand_path("../Gemfile", __dir__)
|
@@ -13,10 +13,12 @@ module Sentry
|
|
13
13
|
attr_reader :logger
|
14
14
|
attr_accessor :shutdown_timeout
|
15
15
|
|
16
|
+
DEFAULT_MAX_QUEUE = 30
|
17
|
+
|
16
18
|
def initialize(configuration)
|
17
|
-
@max_queue = 30
|
18
19
|
@shutdown_timeout = 1
|
19
20
|
@number_of_threads = configuration.background_worker_threads
|
21
|
+
@max_queue = configuration.background_worker_max_queue
|
20
22
|
@logger = configuration.logger
|
21
23
|
@debug = configuration.debug
|
22
24
|
@shutdown_callback = nil
|
data/lib/sentry/client.rb
CHANGED
@@ -10,6 +10,10 @@ module Sentry
|
|
10
10
|
# @return [Transport]
|
11
11
|
attr_reader :transport
|
12
12
|
|
13
|
+
# The Transport object that'll send events for the client.
|
14
|
+
# @return [SpotlightTransport, nil]
|
15
|
+
attr_reader :spotlight_transport
|
16
|
+
|
13
17
|
# @!macro configuration
|
14
18
|
attr_reader :configuration
|
15
19
|
|
@@ -32,6 +36,8 @@ module Sentry
|
|
32
36
|
DummyTransport.new(configuration)
|
33
37
|
end
|
34
38
|
end
|
39
|
+
|
40
|
+
@spotlight_transport = SpotlightTransport.new(configuration) if configuration.spotlight
|
35
41
|
end
|
36
42
|
|
37
43
|
# Applies the given scope's data to the event and sends it to Sentry.
|
@@ -167,6 +173,7 @@ module Sentry
|
|
167
173
|
end
|
168
174
|
|
169
175
|
transport.send_event(event)
|
176
|
+
spotlight_transport&.send_event(event)
|
170
177
|
|
171
178
|
event
|
172
179
|
rescue => e
|
data/lib/sentry/configuration.rb
CHANGED
@@ -40,6 +40,13 @@ module Sentry
|
|
40
40
|
# @return [Integer]
|
41
41
|
attr_accessor :background_worker_threads
|
42
42
|
|
43
|
+
# The maximum queue size for the background worker.
|
44
|
+
# Jobs will be rejected above this limit.
|
45
|
+
#
|
46
|
+
# Default is {BackgroundWorker::DEFAULT_MAX_QUEUE}.
|
47
|
+
# @return [Integer]
|
48
|
+
attr_accessor :background_worker_max_queue
|
49
|
+
|
43
50
|
# a proc/lambda that takes an array of stack traces
|
44
51
|
# it'll be used to silence (reduce) backtrace of the exception
|
45
52
|
#
|
@@ -142,6 +149,14 @@ module Sentry
|
|
142
149
|
# @return [Boolean]
|
143
150
|
attr_accessor :include_local_variables
|
144
151
|
|
152
|
+
# Whether to capture events and traces into Spotlight. Default is false.
|
153
|
+
# If you set this to true, Sentry will send events and traces to the local
|
154
|
+
# Sidecar proxy at http://localhost:8969/stream.
|
155
|
+
# If you want to use a different Sidecar proxy address, set this to String
|
156
|
+
# with the proxy URL.
|
157
|
+
# @return [Boolean, String]
|
158
|
+
attr_accessor :spotlight
|
159
|
+
|
145
160
|
# @deprecated Use {#include_local_variables} instead.
|
146
161
|
alias_method :capture_exception_frame_locals, :include_local_variables
|
147
162
|
|
@@ -321,6 +336,7 @@ module Sentry
|
|
321
336
|
self.app_dirs_pattern = nil
|
322
337
|
self.debug = false
|
323
338
|
self.background_worker_threads = Concurrent.processor_count
|
339
|
+
self.background_worker_max_queue = BackgroundWorker::DEFAULT_MAX_QUEUE
|
324
340
|
self.backtrace_cleanup_callback = nil
|
325
341
|
self.max_breadcrumbs = BreadcrumbBuffer::DEFAULT_SIZE
|
326
342
|
self.breadcrumbs_logger = []
|
@@ -344,6 +360,7 @@ module Sentry
|
|
344
360
|
self.auto_session_tracking = true
|
345
361
|
self.trusted_proxies = []
|
346
362
|
self.dsn = ENV['SENTRY_DSN']
|
363
|
+
self.spotlight = false
|
347
364
|
self.server_name = server_name_from_env
|
348
365
|
self.instrumenter = :sentry
|
349
366
|
self.trace_propagation_targets = [PROPAGATION_TARGETS_MATCH_ALL]
|
@@ -451,7 +468,7 @@ module Sentry
|
|
451
468
|
def sending_allowed?
|
452
469
|
@errors = []
|
453
470
|
|
454
|
-
valid? && capture_in_environment?
|
471
|
+
spotlight || (valid? && capture_in_environment?)
|
455
472
|
end
|
456
473
|
|
457
474
|
def sample_allowed?
|
@@ -4,7 +4,7 @@ module Sentry
|
|
4
4
|
MAX_SLUG_LENGTH = 50
|
5
5
|
|
6
6
|
module Patch
|
7
|
-
def perform(*args)
|
7
|
+
def perform(*args, **opts)
|
8
8
|
slug = self.class.sentry_monitor_slug
|
9
9
|
monitor_config = self.class.sentry_monitor_config
|
10
10
|
|
@@ -13,7 +13,8 @@ module Sentry
|
|
13
13
|
monitor_config: monitor_config)
|
14
14
|
|
15
15
|
start = Sentry.utc_now.to_i
|
16
|
-
|
16
|
+
# need to do this on ruby <= 2.6 sadly
|
17
|
+
ret = method(:perform).super_method.arity == 0 ? super() : super
|
17
18
|
duration = Sentry.utc_now.to_i - start
|
18
19
|
|
19
20
|
Sentry.capture_check_in(slug,
|
@@ -44,7 +45,7 @@ module Sentry
|
|
44
45
|
prepend Patch
|
45
46
|
end
|
46
47
|
|
47
|
-
def sentry_monitor_slug
|
48
|
+
def sentry_monitor_slug(name: self.name)
|
48
49
|
@sentry_monitor_slug ||= begin
|
49
50
|
slug = name.gsub('::', '-').downcase
|
50
51
|
slug[-MAX_SLUG_LENGTH..-1] || slug
|
@@ -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,12 +40,14 @@ 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
|
@@ -58,8 +68,52 @@ module Sentry
|
|
58
68
|
|
59
69
|
raise Sentry::ExternalError, error_info
|
60
70
|
end
|
61
|
-
rescue SocketError => e
|
62
|
-
|
71
|
+
rescue SocketError, *HTTP_ERRORS => e
|
72
|
+
on_error if respond_to?(:on_error)
|
73
|
+
raise Sentry::ExternalError.new(e&.message)
|
74
|
+
end
|
75
|
+
|
76
|
+
def endpoint
|
77
|
+
@dsn.envelope_endpoint
|
78
|
+
end
|
79
|
+
|
80
|
+
def generate_auth_header
|
81
|
+
return nil unless @dsn
|
82
|
+
|
83
|
+
now = Sentry.utc_now.to_i
|
84
|
+
fields = {
|
85
|
+
'sentry_version' => PROTOCOL_VERSION,
|
86
|
+
'sentry_client' => USER_AGENT,
|
87
|
+
'sentry_timestamp' => now,
|
88
|
+
'sentry_key' => @dsn.public_key
|
89
|
+
}
|
90
|
+
fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
|
91
|
+
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
92
|
+
end
|
93
|
+
|
94
|
+
def conn
|
95
|
+
server = URI(@dsn.server)
|
96
|
+
|
97
|
+
# connection respects proxy setting from @transport_configuration, or environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)
|
98
|
+
# Net::HTTP will automatically read the env vars.
|
99
|
+
# See https://ruby-doc.org/3.2.2/stdlibs/net/Net/HTTP.html#class-Net::HTTP-label-Proxies
|
100
|
+
connection =
|
101
|
+
if proxy = normalize_proxy(@transport_configuration.proxy)
|
102
|
+
::Net::HTTP.new(server.hostname, server.port, proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
|
103
|
+
else
|
104
|
+
::Net::HTTP.new(server.hostname, server.port)
|
105
|
+
end
|
106
|
+
|
107
|
+
connection.use_ssl = server.scheme == "https"
|
108
|
+
connection.read_timeout = @transport_configuration.timeout
|
109
|
+
connection.write_timeout = @transport_configuration.timeout if connection.respond_to?(:write_timeout)
|
110
|
+
connection.open_timeout = @transport_configuration.open_timeout
|
111
|
+
|
112
|
+
ssl_configuration.each do |key, value|
|
113
|
+
connection.send("#{key}=", value)
|
114
|
+
end
|
115
|
+
|
116
|
+
connection
|
63
117
|
end
|
64
118
|
|
65
119
|
private
|
@@ -126,31 +180,6 @@ module Sentry
|
|
126
180
|
@transport_configuration.encoding == GZIP_ENCODING && data.bytesize >= GZIP_THRESHOLD
|
127
181
|
end
|
128
182
|
|
129
|
-
def conn
|
130
|
-
server = URI(@dsn.server)
|
131
|
-
|
132
|
-
# connection respects proxy setting from @transport_configuration, or environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)
|
133
|
-
# Net::HTTP will automatically read the env vars.
|
134
|
-
# See https://ruby-doc.org/3.2.2/stdlibs/net/Net/HTTP.html#class-Net::HTTP-label-Proxies
|
135
|
-
connection =
|
136
|
-
if proxy = normalize_proxy(@transport_configuration.proxy)
|
137
|
-
::Net::HTTP.new(server.hostname, server.port, proxy[:uri].hostname, proxy[:uri].port, proxy[:user], proxy[:password])
|
138
|
-
else
|
139
|
-
::Net::HTTP.new(server.hostname, server.port)
|
140
|
-
end
|
141
|
-
|
142
|
-
connection.use_ssl = server.scheme == "https"
|
143
|
-
connection.read_timeout = @transport_configuration.timeout
|
144
|
-
connection.write_timeout = @transport_configuration.timeout if connection.respond_to?(:write_timeout)
|
145
|
-
connection.open_timeout = @transport_configuration.open_timeout
|
146
|
-
|
147
|
-
ssl_configuration.each do |key, value|
|
148
|
-
connection.send("#{key}=", value)
|
149
|
-
end
|
150
|
-
|
151
|
-
connection
|
152
|
-
end
|
153
|
-
|
154
183
|
# @param proxy [String, URI, Hash] Proxy config value passed into `config.transport`.
|
155
184
|
# Accepts either a URI formatted string, URI, or a hash with the `uri`, `user`, and `password` keys.
|
156
185
|
# @return [Hash] Normalized proxy config that will be passed into `Net::HTTP`
|
@@ -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
@@ -119,18 +119,6 @@ module Sentry
|
|
119
119
|
!!delay && delay > Time.now
|
120
120
|
end
|
121
121
|
|
122
|
-
def generate_auth_header
|
123
|
-
now = Sentry.utc_now.to_i
|
124
|
-
fields = {
|
125
|
-
'sentry_version' => PROTOCOL_VERSION,
|
126
|
-
'sentry_client' => USER_AGENT,
|
127
|
-
'sentry_timestamp' => now,
|
128
|
-
'sentry_key' => @dsn.public_key
|
129
|
-
}
|
130
|
-
fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
|
131
|
-
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
132
|
-
end
|
133
|
-
|
134
122
|
def envelope_from_event(event)
|
135
123
|
# Convert to hash
|
136
124
|
event_payload = event.to_hash
|
@@ -220,3 +208,4 @@ end
|
|
220
208
|
|
221
209
|
require "sentry/transport/dummy_transport"
|
222
210
|
require "sentry/transport/http_transport"
|
211
|
+
require "sentry/transport/spotlight_transport"
|
data/lib/sentry/version.rb
CHANGED
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.15.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: 2023-
|
11
|
+
date: 2023-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/sentry/transport/configuration.rb
|
101
101
|
- lib/sentry/transport/dummy_transport.rb
|
102
102
|
- lib/sentry/transport/http_transport.rb
|
103
|
+
- lib/sentry/transport/spotlight_transport.rb
|
103
104
|
- lib/sentry/utils/argument_checking_helper.rb
|
104
105
|
- lib/sentry/utils/custom_inspection.rb
|
105
106
|
- lib/sentry/utils/encoding_helper.rb
|