sentry-ruby 5.21.0 → 5.22.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/Gemfile +1 -0
- data/lib/sentry/excon/middleware.rb +77 -0
- data/lib/sentry/excon.rb +10 -0
- data/lib/sentry/hub.rb +5 -1
- data/lib/sentry/rspec.rb +91 -0
- data/lib/sentry/session_flusher.rb +8 -4
- data/lib/sentry/span.rb +5 -0
- data/lib/sentry/utils/http_tracing.rb +20 -1
- data/lib/sentry/vernier/profiler.rb +7 -2
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +8 -3
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cf4ebc58389dd621be706b53b86c30e689f9f52c5d5cbda72ef01528c540e5a
|
4
|
+
data.tar.gz: f347cb6245d5d37f2d883870b26d846244d33ef6cbb67b838fe231d1c17e95f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2dae846cd0a9d3c10d41d44a775bd39e6d175f559924bf101cd2a88816145ea2cf048962504615d5f05acca0b59451483a2b602a9fb87bba3b2be4364493fd27
|
7
|
+
data.tar.gz: b17875017e20c0126c8ddc5d360873430c92d69f0633134743198140c2258f828b3b444748c7a4cd8e0bb9137a9990f2dc394182ffcfe6a19d1e0f3795beebcd
|
data/Gemfile
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module Excon
|
5
|
+
OP_NAME = "http.client"
|
6
|
+
|
7
|
+
class Middleware < ::Excon::Middleware::Base
|
8
|
+
def initialize(stack)
|
9
|
+
super
|
10
|
+
@instrumenter = Instrumenter.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def request_call(datum)
|
14
|
+
@instrumenter.start_transaction(datum)
|
15
|
+
@stack.request_call(datum)
|
16
|
+
end
|
17
|
+
|
18
|
+
def response_call(datum)
|
19
|
+
@instrumenter.finish_transaction(datum)
|
20
|
+
@stack.response_call(datum)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Instrumenter
|
25
|
+
SPAN_ORIGIN = "auto.http.excon"
|
26
|
+
BREADCRUMB_CATEGORY = "http"
|
27
|
+
|
28
|
+
include Utils::HttpTracing
|
29
|
+
|
30
|
+
def start_transaction(env)
|
31
|
+
return unless Sentry.initialized?
|
32
|
+
|
33
|
+
current_span = Sentry.get_current_scope&.span
|
34
|
+
@span = current_span&.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN)
|
35
|
+
|
36
|
+
request_info = extract_request_info(env)
|
37
|
+
|
38
|
+
if propagate_trace?(request_info[:url])
|
39
|
+
set_propagation_headers(env[:headers])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def finish_transaction(response)
|
44
|
+
return unless @span
|
45
|
+
|
46
|
+
response_status = response[:response][:status]
|
47
|
+
request_info = extract_request_info(response)
|
48
|
+
|
49
|
+
if record_sentry_breadcrumb?
|
50
|
+
record_sentry_breadcrumb(request_info, response_status)
|
51
|
+
end
|
52
|
+
|
53
|
+
set_span_info(@span, request_info, response_status)
|
54
|
+
ensure
|
55
|
+
@span&.finish
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def extract_request_info(env)
|
61
|
+
url = env[:scheme] + "://" + env[:hostname] + env[:path]
|
62
|
+
result = { method: env[:method].to_s.upcase, url: url }
|
63
|
+
|
64
|
+
if Sentry.configuration.send_default_pii
|
65
|
+
result[:query] = env[:query]
|
66
|
+
|
67
|
+
# Handle excon 1.0.0+
|
68
|
+
result[:query] = build_nested_query(result[:query]) unless result[:query].is_a?(String)
|
69
|
+
|
70
|
+
result[:body] = env[:body]
|
71
|
+
end
|
72
|
+
|
73
|
+
result
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/sentry/excon.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Sentry.register_patch(:excon) do
|
4
|
+
if defined?(::Excon)
|
5
|
+
require "sentry/excon/middleware"
|
6
|
+
if Excon.defaults[:middlewares]
|
7
|
+
Excon.defaults[:middlewares] << Sentry::Excon::Middleware unless Excon.defaults[:middlewares].include?(Sentry::Excon::Middleware)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/sentry/hub.rb
CHANGED
@@ -255,7 +255,11 @@ module Sentry
|
|
255
255
|
|
256
256
|
return unless session
|
257
257
|
session.close
|
258
|
-
|
258
|
+
|
259
|
+
# NOTE: Under some circumstances, session_flusher nilified out of sync
|
260
|
+
# See: https://github.com/getsentry/sentry-ruby/issues/2378
|
261
|
+
# See: https://github.com/getsentry/sentry-ruby/pull/2396
|
262
|
+
Sentry.session_flusher&.add_session(session)
|
259
263
|
end
|
260
264
|
|
261
265
|
def with_session_tracking(&block)
|
data/lib/sentry/rspec.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :include_sentry_event do |event_message = "", **opts|
|
4
|
+
match do |sentry_events|
|
5
|
+
@expected_exception = expected_exception(**opts)
|
6
|
+
@context = context(**opts)
|
7
|
+
@tags = tags(**opts)
|
8
|
+
|
9
|
+
@expected_event = expected_event(event_message)
|
10
|
+
@matched_event = find_matched_event(event_message, sentry_events)
|
11
|
+
|
12
|
+
return false unless @matched_event
|
13
|
+
|
14
|
+
[verify_context(), verify_tags()].all?
|
15
|
+
end
|
16
|
+
|
17
|
+
chain :with_context do |context|
|
18
|
+
@context = context
|
19
|
+
end
|
20
|
+
|
21
|
+
chain :with_tags do |tags|
|
22
|
+
@tags = tags
|
23
|
+
end
|
24
|
+
|
25
|
+
failure_message do |sentry_events|
|
26
|
+
info = ["Failed to find event matching:\n"]
|
27
|
+
info << " message: #{@expected_event.message.inspect}"
|
28
|
+
info << " exception: #{@expected_exception.inspect}"
|
29
|
+
info << " context: #{@context.inspect}"
|
30
|
+
info << " tags: #{@tags.inspect}"
|
31
|
+
info << "\n"
|
32
|
+
info << "Captured events:\n"
|
33
|
+
info << dump_events(sentry_events)
|
34
|
+
info.join("\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
def expected_event(event_message)
|
38
|
+
if @expected_exception
|
39
|
+
Sentry.get_current_client.event_from_exception(@expected_exception)
|
40
|
+
else
|
41
|
+
Sentry.get_current_client.event_from_message(event_message)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def expected_exception(**opts)
|
46
|
+
opts[:exception].new(opts[:message]) if opts[:exception]
|
47
|
+
end
|
48
|
+
|
49
|
+
def context(**opts)
|
50
|
+
opts.fetch(:context, @context || {})
|
51
|
+
end
|
52
|
+
|
53
|
+
def tags(**opts)
|
54
|
+
opts.fetch(:tags, @tags || {})
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_matched_event(event_message, sentry_events)
|
58
|
+
@matched_event ||= sentry_events
|
59
|
+
.find { |event|
|
60
|
+
if @expected_exception
|
61
|
+
# Is it OK that we only compare the first exception?
|
62
|
+
event_exception = event.exception.values.first
|
63
|
+
expected_event_exception = @expected_event.exception.values.first
|
64
|
+
|
65
|
+
event_exception.type == expected_event_exception.type && event_exception.value == expected_event_exception.value
|
66
|
+
else
|
67
|
+
event.message == @expected_event.message
|
68
|
+
end
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def dump_events(sentry_events)
|
73
|
+
sentry_events.map(&Kernel.method(:Hash)).map do |hash|
|
74
|
+
hash.select { |k, _| [:message, :contexts, :tags, :exception].include?(k) }
|
75
|
+
end.map do |hash|
|
76
|
+
JSON.pretty_generate(hash)
|
77
|
+
end.join("\n\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
def verify_context
|
81
|
+
return true if @context.empty?
|
82
|
+
|
83
|
+
@matched_event.contexts.any? { |key, value| value == @context[key] }
|
84
|
+
end
|
85
|
+
|
86
|
+
def verify_tags
|
87
|
+
return true if @tags.empty?
|
88
|
+
|
89
|
+
@tags.all? { |key, value| @matched_event.tags.include?(key) && @matched_event.tags[key] == value }
|
90
|
+
end
|
91
|
+
end
|
@@ -10,6 +10,7 @@ module Sentry
|
|
10
10
|
@pending_aggregates = {}
|
11
11
|
@release = configuration.release
|
12
12
|
@environment = configuration.environment
|
13
|
+
@mutex = Mutex.new
|
13
14
|
|
14
15
|
log_debug("[Sessions] Sessions won't be captured without a valid release") unless @release
|
15
16
|
end
|
@@ -18,7 +19,6 @@ module Sentry
|
|
18
19
|
return if @pending_aggregates.empty?
|
19
20
|
|
20
21
|
@client.capture_envelope(pending_envelope)
|
21
|
-
@pending_aggregates = {}
|
22
22
|
end
|
23
23
|
|
24
24
|
alias_method :run, :flush
|
@@ -42,11 +42,15 @@ module Sentry
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def pending_envelope
|
45
|
-
|
45
|
+
aggregates = @mutex.synchronize do
|
46
|
+
aggregates = @pending_aggregates.values
|
47
|
+
@pending_aggregates = {}
|
48
|
+
aggregates
|
49
|
+
end
|
46
50
|
|
51
|
+
envelope = Envelope.new
|
47
52
|
header = { type: "sessions" }
|
48
|
-
payload = { attrs: attrs, aggregates:
|
49
|
-
|
53
|
+
payload = { attrs: attrs, aggregates: aggregates }
|
50
54
|
envelope.add_item(header, payload)
|
51
55
|
envelope
|
52
56
|
end
|
data/lib/sentry/span.rb
CHANGED
@@ -44,6 +44,11 @@ module Sentry
|
|
44
44
|
LINENO = "code.lineno"
|
45
45
|
FUNCTION = "code.function"
|
46
46
|
NAMESPACE = "code.namespace"
|
47
|
+
|
48
|
+
MESSAGING_MESSAGE_ID = "messaging.message.id"
|
49
|
+
MESSAGING_DESTINATION_NAME = "messaging.destination.name"
|
50
|
+
MESSAGING_MESSAGE_RECEIVE_LATENCY = "messaging.message.receive.latency"
|
51
|
+
MESSAGING_MESSAGE_RETRY_COUNT = "messaging.message.retry.count"
|
47
52
|
end
|
48
53
|
|
49
54
|
STATUS_MAP = {
|
@@ -19,7 +19,7 @@ module Sentry
|
|
19
19
|
crumb = Sentry::Breadcrumb.new(
|
20
20
|
level: :info,
|
21
21
|
category: self.class::BREADCRUMB_CATEGORY,
|
22
|
-
type:
|
22
|
+
type: "info",
|
23
23
|
data: { status: response_status, **request_info }
|
24
24
|
)
|
25
25
|
|
@@ -36,6 +36,25 @@ module Sentry
|
|
36
36
|
Sentry.configuration.propagate_traces &&
|
37
37
|
Sentry.configuration.trace_propagation_targets.any? { |target| url.match?(target) }
|
38
38
|
end
|
39
|
+
|
40
|
+
# Kindly borrowed from Rack::Utils
|
41
|
+
def build_nested_query(value, prefix = nil)
|
42
|
+
case value
|
43
|
+
when Array
|
44
|
+
value.map { |v|
|
45
|
+
build_nested_query(v, "#{prefix}[]")
|
46
|
+
}.join("&")
|
47
|
+
when Hash
|
48
|
+
value.map { |k, v|
|
49
|
+
build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
|
50
|
+
}.delete_if(&:empty?).join("&")
|
51
|
+
when nil
|
52
|
+
URI.encode_www_form_component(prefix)
|
53
|
+
else
|
54
|
+
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
55
|
+
"#{URI.encode_www_form_component(prefix)}=#{URI.encode_www_form_component(value)}"
|
56
|
+
end
|
57
|
+
end
|
39
58
|
end
|
40
59
|
end
|
41
60
|
end
|
@@ -55,8 +55,7 @@ module Sentry
|
|
55
55
|
return unless @sampled
|
56
56
|
return if @started
|
57
57
|
|
58
|
-
::Vernier.start_profile
|
59
|
-
@started = true
|
58
|
+
@started = ::Vernier.start_profile
|
60
59
|
|
61
60
|
log("Started")
|
62
61
|
|
@@ -77,6 +76,12 @@ module Sentry
|
|
77
76
|
@result = ::Vernier.stop_profile
|
78
77
|
|
79
78
|
log("Stopped")
|
79
|
+
rescue RuntimeError => e
|
80
|
+
if e.message.include?("Profile not started")
|
81
|
+
log("Not stopped since not started")
|
82
|
+
else
|
83
|
+
log("Failed to stop Vernier: #{e.message}")
|
84
|
+
end
|
80
85
|
end
|
81
86
|
|
82
87
|
def active_thread_id
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -50,6 +50,8 @@ module Sentry
|
|
50
50
|
|
51
51
|
THREAD_LOCAL = :sentry_hub
|
52
52
|
|
53
|
+
MUTEX = Mutex.new
|
54
|
+
|
53
55
|
class << self
|
54
56
|
# @!visibility private
|
55
57
|
def exception_locals_tp
|
@@ -275,8 +277,10 @@ module Sentry
|
|
275
277
|
|
276
278
|
@background_worker.shutdown
|
277
279
|
|
278
|
-
|
279
|
-
|
280
|
+
MUTEX.synchronize do
|
281
|
+
@main_hub = nil
|
282
|
+
Thread.current.thread_variable_set(THREAD_LOCAL, nil)
|
283
|
+
end
|
280
284
|
end
|
281
285
|
|
282
286
|
# Returns true if the SDK is initialized.
|
@@ -303,7 +307,7 @@ module Sentry
|
|
303
307
|
#
|
304
308
|
# @return [Hub]
|
305
309
|
def get_main_hub
|
306
|
-
@main_hub
|
310
|
+
MUTEX.synchronize { @main_hub }
|
307
311
|
end
|
308
312
|
|
309
313
|
# Takes an instance of Sentry::Breadcrumb and stores it to the current active scope.
|
@@ -610,3 +614,4 @@ require "sentry/redis"
|
|
610
614
|
require "sentry/puma"
|
611
615
|
require "sentry/graphql"
|
612
616
|
require "sentry/faraday"
|
617
|
+
require "sentry/excon"
|
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.22.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: 2024-
|
11
|
+
date: 2024-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -87,6 +87,8 @@ files:
|
|
87
87
|
- lib/sentry/error_event.rb
|
88
88
|
- lib/sentry/event.rb
|
89
89
|
- lib/sentry/exceptions.rb
|
90
|
+
- lib/sentry/excon.rb
|
91
|
+
- lib/sentry/excon/middleware.rb
|
90
92
|
- lib/sentry/faraday.rb
|
91
93
|
- lib/sentry/graphql.rb
|
92
94
|
- lib/sentry/hub.rb
|
@@ -121,6 +123,7 @@ files:
|
|
121
123
|
- lib/sentry/rake.rb
|
122
124
|
- lib/sentry/redis.rb
|
123
125
|
- lib/sentry/release_detector.rb
|
126
|
+
- lib/sentry/rspec.rb
|
124
127
|
- lib/sentry/scope.rb
|
125
128
|
- lib/sentry/session.rb
|
126
129
|
- lib/sentry/session_flusher.rb
|
@@ -148,15 +151,15 @@ files:
|
|
148
151
|
- lib/sentry/version.rb
|
149
152
|
- sentry-ruby-core.gemspec
|
150
153
|
- sentry-ruby.gemspec
|
151
|
-
homepage: https://github.com/getsentry/sentry-ruby/tree/5.
|
154
|
+
homepage: https://github.com/getsentry/sentry-ruby/tree/5.22.1/sentry-ruby
|
152
155
|
licenses:
|
153
156
|
- MIT
|
154
157
|
metadata:
|
155
|
-
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
156
|
-
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.
|
157
|
-
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.
|
158
|
+
homepage_uri: https://github.com/getsentry/sentry-ruby/tree/5.22.1/sentry-ruby
|
159
|
+
source_code_uri: https://github.com/getsentry/sentry-ruby/tree/5.22.1/sentry-ruby
|
160
|
+
changelog_uri: https://github.com/getsentry/sentry-ruby/blob/5.22.1/CHANGELOG.md
|
158
161
|
bug_tracker_uri: https://github.com/getsentry/sentry-ruby/issues
|
159
|
-
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.
|
162
|
+
documentation_uri: http://www.rubydoc.info/gems/sentry-ruby/5.22.1
|
160
163
|
post_install_message:
|
161
164
|
rdoc_options: []
|
162
165
|
require_paths:
|
@@ -172,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
175
|
- !ruby/object:Gem::Version
|
173
176
|
version: '0'
|
174
177
|
requirements: []
|
175
|
-
rubygems_version: 3.5.
|
178
|
+
rubygems_version: 3.5.22
|
176
179
|
signing_key:
|
177
180
|
specification_version: 4
|
178
181
|
summary: A gem that provides a client interface for the Sentry error logger
|