sentry-ruby-core 6.3.1 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/lib/sentry/baggage.rb +1 -1
- data/lib/sentry/configuration.rb +8 -0
- data/lib/sentry/dsn.rb +20 -0
- data/lib/sentry/metric_event.rb +1 -1
- data/lib/sentry/rack/capture_exceptions.rb +83 -1
- data/lib/sentry/scope.rb +1 -1
- data/lib/sentry/span.rb +3 -0
- data/lib/sentry/transport/http_transport.rb +1 -11
- data/lib/sentry/transport.rb +1 -1
- data/lib/sentry/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b945d3d2d16b0ba63298017ad761ef832b2b73a40071bfb1d7d660780827ba5b
|
|
4
|
+
data.tar.gz: 51132c054f3d252e41457b2386dccaf1552ccfed4d504164b70b44b1c6202f4b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c258db8a18282fcfb68093c09bccf32d9a0358819bc3a5ea5581fcec99e7aa147be5be47ad71055a4a0b16020ee51452d9e0b0cd43a99f0025bd767d546321ff
|
|
7
|
+
data.tar.gz: edcb0e412d362495836836d39db3753e7bc612968efe9bd036fefdaeb966d8f25541703c2b570c04679c223e421662cef20964d3958a23f471ee6e1794baf376
|
data/Gemfile
CHANGED
|
@@ -21,7 +21,7 @@ gem "puma"
|
|
|
21
21
|
|
|
22
22
|
gem "timecop"
|
|
23
23
|
gem "stackprof" unless RUBY_PLATFORM == "java"
|
|
24
|
-
gem "vernier", platforms: :ruby if
|
|
24
|
+
gem "vernier", platforms: :ruby if ruby_version >= Gem::Version.new("3.3") && ruby_version < Gem::Version.new("4.1.0")
|
|
25
25
|
|
|
26
26
|
gem "graphql", ">= 2.2.6"
|
|
27
27
|
|
data/README.md
CHANGED
|
@@ -33,7 +33,7 @@ If you're using `sentry-raven`, we recommend you to migrate to this new SDK. You
|
|
|
33
33
|
|
|
34
34
|
## Requirements
|
|
35
35
|
|
|
36
|
-
We test from Ruby 2.4 to Ruby
|
|
36
|
+
We test from Ruby 2.4 to Ruby 4.0 at the latest patchlevel/teeny version. We also support JRuby 9.0.
|
|
37
37
|
|
|
38
38
|
If you use self-hosted Sentry, please also make sure its version is above `20.6.0`.
|
|
39
39
|
|
data/lib/sentry/baggage.rb
CHANGED
data/lib/sentry/configuration.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "cgi/escape"
|
|
3
4
|
require "concurrent/utility/processor_counter"
|
|
4
5
|
|
|
5
6
|
require "sentry/utils/exception_cause_chain"
|
|
@@ -234,6 +235,12 @@ module Sentry
|
|
|
234
235
|
# @return [Boolean]
|
|
235
236
|
attr_accessor :send_default_pii
|
|
236
237
|
|
|
238
|
+
# Capture queue time from X-Request-Start header set by reverse proxies.
|
|
239
|
+
# Works with any Rack app behind Nginx, HAProxy, Heroku router, etc.
|
|
240
|
+
# Defaults to true.
|
|
241
|
+
# @return [Boolean]
|
|
242
|
+
attr_accessor :capture_queue_time
|
|
243
|
+
|
|
237
244
|
# Allow to skip Sentry emails within rake tasks
|
|
238
245
|
# @return [Boolean]
|
|
239
246
|
attr_accessor :skip_rake_integration
|
|
@@ -512,6 +519,7 @@ module Sentry
|
|
|
512
519
|
self.enable_backpressure_handling = false
|
|
513
520
|
self.trusted_proxies = []
|
|
514
521
|
self.dsn = ENV["SENTRY_DSN"]
|
|
522
|
+
self.capture_queue_time = true
|
|
515
523
|
|
|
516
524
|
spotlight_env = ENV["SENTRY_SPOTLIGHT"]
|
|
517
525
|
spotlight_bool = Sentry::Utils::EnvHelper.env_to_bool(spotlight_env, strict: true)
|
data/lib/sentry/dsn.rb
CHANGED
|
@@ -6,6 +6,7 @@ require "resolv"
|
|
|
6
6
|
|
|
7
7
|
module Sentry
|
|
8
8
|
class DSN
|
|
9
|
+
PROTOCOL_VERSION = "7"
|
|
9
10
|
PORT_MAP = { "http" => 80, "https" => 443 }.freeze
|
|
10
11
|
REQUIRED_ATTRIBUTES = %w[host path public_key project_id].freeze
|
|
11
12
|
LOCALHOST_NAMES = %w[localhost 127.0.0.1 ::1 [::1]].freeze
|
|
@@ -54,6 +55,10 @@ module Sentry
|
|
|
54
55
|
"#{path}/api/#{project_id}/envelope/"
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
def otlp_traces_endpoint
|
|
59
|
+
"#{path}/api/#{project_id}/integration/otlp/v1/traces/"
|
|
60
|
+
end
|
|
61
|
+
|
|
57
62
|
def local?
|
|
58
63
|
@local ||= (localhost? || private_ip? || resolved_ips_private?)
|
|
59
64
|
end
|
|
@@ -81,5 +86,20 @@ module Sentry
|
|
|
81
86
|
end
|
|
82
87
|
end
|
|
83
88
|
end
|
|
89
|
+
|
|
90
|
+
def generate_auth_header(client: nil)
|
|
91
|
+
now = Sentry.utc_now.to_i
|
|
92
|
+
|
|
93
|
+
fields = {
|
|
94
|
+
"sentry_version" => PROTOCOL_VERSION,
|
|
95
|
+
"sentry_timestamp" => now,
|
|
96
|
+
"sentry_key" => @public_key
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fields["sentry_client"] = client if client
|
|
100
|
+
fields["sentry_secret"] = @secret_key if @secret_key
|
|
101
|
+
|
|
102
|
+
"Sentry " + fields.map { |key, value| "#{key}=#{value}" }.join(", ")
|
|
103
|
+
end
|
|
84
104
|
end
|
|
85
105
|
end
|
data/lib/sentry/metric_event.rb
CHANGED
|
@@ -72,7 +72,14 @@ module Sentry
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
transaction = Sentry.continue_trace(env, **options)
|
|
75
|
-
Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
|
75
|
+
transaction = Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
|
76
|
+
|
|
77
|
+
# attach queue time if available
|
|
78
|
+
if transaction && (queue_time = extract_queue_time(env))
|
|
79
|
+
transaction.set_data(Span::DataConventions::HTTP_QUEUE_TIME_MS, queue_time)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
transaction
|
|
76
83
|
end
|
|
77
84
|
|
|
78
85
|
|
|
@@ -87,6 +94,81 @@ module Sentry
|
|
|
87
94
|
Sentry::Mechanism.new(type: MECHANISM_TYPE, handled: false)
|
|
88
95
|
end
|
|
89
96
|
|
|
97
|
+
# Extracts queue time from the request environment.
|
|
98
|
+
# Calculates the time (in milliseconds) the request spent waiting in the
|
|
99
|
+
# web server queue before processing began.
|
|
100
|
+
#
|
|
101
|
+
# Subtracts puma.request_body_wait to account for time spent waiting for
|
|
102
|
+
# slow clients to send the request body, isolating actual queue time.
|
|
103
|
+
# See: https://github.com/puma/puma/blob/master/docs/architecture.md
|
|
104
|
+
#
|
|
105
|
+
# @param env [Hash] Rack env
|
|
106
|
+
# @return [Float, nil] queue time in milliseconds or nil
|
|
107
|
+
def extract_queue_time(env)
|
|
108
|
+
return unless Sentry.configuration&.capture_queue_time
|
|
109
|
+
|
|
110
|
+
header_value = env["HTTP_X_REQUEST_START"]
|
|
111
|
+
return unless header_value
|
|
112
|
+
|
|
113
|
+
request_start = parse_request_start_header(header_value)
|
|
114
|
+
return unless request_start
|
|
115
|
+
|
|
116
|
+
total_time_ms = ((Time.now.to_f - request_start) * 1000).round(2)
|
|
117
|
+
|
|
118
|
+
# reject negative (clock skew between proxy & app server)
|
|
119
|
+
return unless total_time_ms >= 0
|
|
120
|
+
|
|
121
|
+
puma_wait_ms = env["puma.request_body_wait"]
|
|
122
|
+
puma_wait_ms = puma_wait_ms.to_f if puma_wait_ms.is_a?(String)
|
|
123
|
+
|
|
124
|
+
if puma_wait_ms && puma_wait_ms > 0
|
|
125
|
+
queue_time_ms = total_time_ms - puma_wait_ms
|
|
126
|
+
queue_time_ms >= 0 ? queue_time_ms : 0.0 # more sanity check
|
|
127
|
+
else
|
|
128
|
+
total_time_ms
|
|
129
|
+
end
|
|
130
|
+
rescue StandardError
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Parses X-Request-Start header value to extract a timestamp.
|
|
134
|
+
# Supports multiple formats:
|
|
135
|
+
# - Nginx: "t=1234567890.123" (seconds with decimal)
|
|
136
|
+
# - Heroku, HAProxy 1.9+: "t=1234567890123456" (microseconds)
|
|
137
|
+
# - HAProxy < 1.9: "t=1234567890" (seconds)
|
|
138
|
+
# - Generic: "1234567890.123" (raw timestamp)
|
|
139
|
+
#
|
|
140
|
+
# @param header_value [String] The X-Request-Start header value
|
|
141
|
+
# @return [Float, nil] Timestamp in seconds since epoch or nil
|
|
142
|
+
def parse_request_start_header(header_value)
|
|
143
|
+
return unless header_value
|
|
144
|
+
|
|
145
|
+
# Take the first value if comma-separated (multiple headers collapsed by a proxy)
|
|
146
|
+
# and strip surrounding whitespace from each token
|
|
147
|
+
raw = header_value.split(",").first.to_s.strip
|
|
148
|
+
|
|
149
|
+
timestamp = if raw.start_with?("t=")
|
|
150
|
+
value = raw[2..-1].strip
|
|
151
|
+
return nil unless value.match?(/\A\d+(?:\.\d+)?\z/)
|
|
152
|
+
value.to_f
|
|
153
|
+
elsif raw.match?(/\A\d+(?:\.\d+)?\z/)
|
|
154
|
+
raw.to_f
|
|
155
|
+
else
|
|
156
|
+
return
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# normalize: timestamps can be in seconds, milliseconds or microseconds
|
|
160
|
+
# any timestamp > 10 trillion = microseconds
|
|
161
|
+
if timestamp > 10_000_000_000_000
|
|
162
|
+
timestamp / 1_000_000.0
|
|
163
|
+
# timestamp > 10 billion & < 10 trillion = milliseconds
|
|
164
|
+
elsif timestamp > 10_000_000_000
|
|
165
|
+
timestamp / 1_000.0
|
|
166
|
+
else
|
|
167
|
+
timestamp # assume seconds
|
|
168
|
+
end
|
|
169
|
+
rescue StandardError
|
|
170
|
+
end
|
|
171
|
+
|
|
90
172
|
def status_code_for_exception(exception)
|
|
91
173
|
500
|
|
92
174
|
end
|
data/lib/sentry/scope.rb
CHANGED
|
@@ -98,7 +98,7 @@ module Sentry
|
|
|
98
98
|
telemetry.attributes["sentry.release"] ||= configuration.release if configuration.release
|
|
99
99
|
telemetry.attributes["server.address"] ||= configuration.server_name if configuration.server_name
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
unless user.empty?
|
|
102
102
|
telemetry.attributes["user.id"] ||= user[:id] if user[:id]
|
|
103
103
|
telemetry.attributes["user.name"] ||= user[:username] if user[:username]
|
|
104
104
|
telemetry.attributes["user.email"] ||= user[:email] if user[:email]
|
data/lib/sentry/span.rb
CHANGED
|
@@ -49,6 +49,9 @@ module Sentry
|
|
|
49
49
|
MESSAGING_DESTINATION_NAME = "messaging.destination.name"
|
|
50
50
|
MESSAGING_MESSAGE_RECEIVE_LATENCY = "messaging.message.receive.latency"
|
|
51
51
|
MESSAGING_MESSAGE_RETRY_COUNT = "messaging.message.retry.count"
|
|
52
|
+
|
|
53
|
+
# Time in ms the request spent in the server queue before processing began.
|
|
54
|
+
HTTP_QUEUE_TIME_MS = "http.server.request.time_in_queue"
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
STATUS_MAP = {
|
|
@@ -69,17 +69,7 @@ module Sentry
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def generate_auth_header
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
now = Sentry.utc_now.to_i
|
|
75
|
-
fields = {
|
|
76
|
-
"sentry_version" => PROTOCOL_VERSION,
|
|
77
|
-
"sentry_client" => USER_AGENT,
|
|
78
|
-
"sentry_timestamp" => now,
|
|
79
|
-
"sentry_key" => @dsn.public_key
|
|
80
|
-
}
|
|
81
|
-
fields["sentry_secret"] = @dsn.secret_key if @dsn.secret_key
|
|
82
|
-
"Sentry " + fields.map { |key, value| "#{key}=#{value}" }.join(", ")
|
|
72
|
+
@dsn&.generate_auth_header(client: USER_AGENT)
|
|
83
73
|
end
|
|
84
74
|
|
|
85
75
|
def conn
|
data/lib/sentry/transport.rb
CHANGED
data/lib/sentry/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sentry-ruby-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sentry Team
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 6.
|
|
18
|
+
version: 6.4.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 6.
|
|
25
|
+
version: 6.4.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: concurrent-ruby
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|