sentry-ruby-core 4.7.3 → 4.8.3
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/.yardopts +2 -0
- data/Gemfile +6 -2
- data/README.md +7 -7
- data/bin/console +5 -1
- data/lib/sentry/background_worker.rb +30 -2
- data/lib/sentry/backtrace.rb +1 -0
- data/lib/sentry/breadcrumb/sentry_logger.rb +2 -0
- data/lib/sentry/breadcrumb.rb +2 -0
- data/lib/sentry/breadcrumb_buffer.rb +2 -0
- data/lib/sentry/client.rb +13 -1
- data/lib/sentry/configuration.rb +136 -112
- data/lib/sentry/core_ext/object/deep_dup.rb +2 -0
- data/lib/sentry/core_ext/object/duplicable.rb +1 -0
- data/lib/sentry/dsn.rb +2 -0
- data/lib/sentry/envelope.rb +26 -0
- data/lib/sentry/event.rb +5 -0
- data/lib/sentry/exceptions.rb +2 -0
- data/lib/sentry/hub.rb +7 -0
- data/lib/sentry/integrable.rb +2 -0
- data/lib/sentry/interface.rb +2 -0
- data/lib/sentry/interfaces/exception.rb +2 -0
- data/lib/sentry/interfaces/single_exception.rb +31 -0
- data/lib/sentry/interfaces/stacktrace.rb +10 -0
- data/lib/sentry/interfaces/stacktrace_builder.rb +2 -0
- data/lib/sentry/interfaces/threads.rb +2 -0
- data/lib/sentry/linecache.rb +3 -0
- data/lib/sentry/net/http.rb +3 -0
- data/lib/sentry/rack/capture_exceptions.rb +2 -0
- data/lib/sentry/rack.rb +2 -0
- data/lib/sentry/rake.rb +16 -6
- data/lib/sentry/release_detector.rb +39 -0
- data/lib/sentry/scope.rb +8 -4
- data/lib/sentry/span.rb +1 -0
- data/lib/sentry/transaction.rb +6 -1
- data/lib/sentry/transport/configuration.rb +2 -0
- data/lib/sentry/transport/dummy_transport.rb +2 -0
- data/lib/sentry/transport/http_transport.rb +6 -4
- data/lib/sentry/transport.rb +77 -19
- data/lib/sentry/utils/argument_checking_helper.rb +2 -0
- data/lib/sentry/utils/custom_inspection.rb +14 -0
- data/lib/sentry/utils/exception_cause_chain.rb +10 -10
- data/lib/sentry/utils/logging_helper.rb +2 -0
- data/lib/sentry/utils/real_ip.rb +2 -0
- data/lib/sentry/utils/request_id.rb +2 -0
- data/lib/sentry/version.rb +3 -1
- data/lib/sentry-ruby.rb +102 -28
- data/sentry-ruby.gemspec +1 -1
- metadata +6 -2
data/lib/sentry/linecache.rb
CHANGED
data/lib/sentry/net/http.rb
CHANGED
data/lib/sentry/rack.rb
CHANGED
data/lib/sentry/rake.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rake"
|
2
4
|
require "rake/task"
|
3
5
|
|
4
6
|
module Sentry
|
5
7
|
module Rake
|
6
8
|
module Application
|
9
|
+
# @api private
|
7
10
|
def display_error_message(ex)
|
8
|
-
Sentry.capture_exception(ex
|
11
|
+
Sentry.capture_exception(ex) do |scope|
|
9
12
|
task_name = top_level_tasks.join(' ')
|
10
13
|
scope.set_transaction_name(task_name)
|
11
14
|
scope.set_tag("rake_task", task_name)
|
@@ -16,16 +19,23 @@ module Sentry
|
|
16
19
|
end
|
17
20
|
|
18
21
|
module Task
|
22
|
+
# @api private
|
19
23
|
def execute(args=nil)
|
20
24
|
return super unless Sentry.initialized? && Sentry.get_current_hub
|
21
25
|
|
22
|
-
|
23
|
-
super
|
24
|
-
end
|
26
|
+
super
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
31
|
-
Rake
|
32
|
+
# @api private
|
33
|
+
module Rake
|
34
|
+
class Application
|
35
|
+
prepend(Sentry::Rake::Application)
|
36
|
+
end
|
37
|
+
|
38
|
+
class Task
|
39
|
+
prepend(Sentry::Rake::Task)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
# @api private
|
5
|
+
class ReleaseDetector
|
6
|
+
class << self
|
7
|
+
def detect_release(project_root:, running_on_heroku:)
|
8
|
+
detect_release_from_env ||
|
9
|
+
detect_release_from_git ||
|
10
|
+
detect_release_from_capistrano(project_root) ||
|
11
|
+
detect_release_from_heroku(running_on_heroku)
|
12
|
+
end
|
13
|
+
|
14
|
+
def detect_release_from_heroku(running_on_heroku)
|
15
|
+
return unless running_on_heroku
|
16
|
+
ENV['HEROKU_SLUG_COMMIT']
|
17
|
+
end
|
18
|
+
|
19
|
+
def detect_release_from_capistrano(project_root)
|
20
|
+
revision_file = File.join(project_root, 'REVISION')
|
21
|
+
revision_log = File.join(project_root, '..', 'revisions.log')
|
22
|
+
|
23
|
+
if File.exist?(revision_file)
|
24
|
+
File.read(revision_file).strip
|
25
|
+
elsif File.exist?(revision_log)
|
26
|
+
File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def detect_release_from_git
|
31
|
+
Sentry.sys_command("git rev-parse --short HEAD") if File.directory?(".git")
|
32
|
+
end
|
33
|
+
|
34
|
+
def detect_release_from_env
|
35
|
+
ENV['SENTRY_RELEASE']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/breadcrumb_buffer"
|
2
4
|
require "etc"
|
3
5
|
|
@@ -112,7 +114,7 @@ module Sentry
|
|
112
114
|
end
|
113
115
|
|
114
116
|
def set_extra(key, value)
|
115
|
-
|
117
|
+
set_extras(key => value)
|
116
118
|
end
|
117
119
|
|
118
120
|
def set_tags(tags_hash)
|
@@ -121,17 +123,19 @@ module Sentry
|
|
121
123
|
end
|
122
124
|
|
123
125
|
def set_tag(key, value)
|
124
|
-
|
126
|
+
set_tags(key => value)
|
125
127
|
end
|
126
128
|
|
127
129
|
def set_contexts(contexts_hash)
|
128
130
|
check_argument_type!(contexts_hash, Hash)
|
129
|
-
@contexts.merge!(contexts_hash)
|
131
|
+
@contexts.merge!(contexts_hash) do |key, old, new|
|
132
|
+
new.merge(old)
|
133
|
+
end
|
130
134
|
end
|
131
135
|
|
132
136
|
def set_context(key, value)
|
133
137
|
check_argument_type!(value, Hash)
|
134
|
-
|
138
|
+
set_contexts(key => value)
|
135
139
|
end
|
136
140
|
|
137
141
|
def set_level(level)
|
data/lib/sentry/span.rb
CHANGED
data/lib/sentry/transaction.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
class Transaction < Span
|
3
5
|
SENTRY_TRACE_REGEXP = Regexp.new(
|
@@ -129,7 +131,10 @@ module Sentry
|
|
129
131
|
@name = UNLABELD_NAME
|
130
132
|
end
|
131
133
|
|
132
|
-
|
134
|
+
unless @sampled || @parent_sampled
|
135
|
+
hub.current_client.transport.record_lost_event(:sample_rate, 'transaction')
|
136
|
+
return
|
137
|
+
end
|
133
138
|
|
134
139
|
event = hub.current_client.event_from_transaction(self)
|
135
140
|
hub.capture_event(event)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'zlib'
|
3
5
|
|
@@ -139,10 +141,10 @@ module Sentry
|
|
139
141
|
end
|
140
142
|
|
141
143
|
def ssl_configuration
|
142
|
-
|
143
|
-
:
|
144
|
-
:
|
145
|
-
)
|
144
|
+
{
|
145
|
+
verify: @transport_configuration.ssl_verification,
|
146
|
+
ca_file: @transport_configuration.ssl_ca_file
|
147
|
+
}.merge(@transport_configuration.ssl || {})
|
146
148
|
end
|
147
149
|
end
|
148
150
|
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -1,22 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "json"
|
2
4
|
require "base64"
|
5
|
+
require "sentry/envelope"
|
3
6
|
|
4
7
|
module Sentry
|
5
8
|
class Transport
|
6
9
|
PROTOCOL_VERSION = '7'
|
7
10
|
USER_AGENT = "sentry-ruby/#{Sentry::VERSION}"
|
11
|
+
CLIENT_REPORT_INTERVAL = 30
|
12
|
+
|
13
|
+
# https://develop.sentry.dev/sdk/client-reports/#envelope-item-payload
|
14
|
+
CLIENT_REPORT_REASONS = [
|
15
|
+
:ratelimit_backoff,
|
16
|
+
:queue_overflow,
|
17
|
+
:cache_overflow, # NA
|
18
|
+
:network_error,
|
19
|
+
:sample_rate,
|
20
|
+
:before_send,
|
21
|
+
:event_processor
|
22
|
+
]
|
8
23
|
|
9
24
|
include LoggingHelper
|
10
25
|
|
11
|
-
|
12
|
-
attr_reader :logger, :rate_limits
|
26
|
+
attr_reader :logger, :rate_limits, :discarded_events, :last_client_report_sent
|
13
27
|
|
14
28
|
def initialize(configuration)
|
15
|
-
@configuration = configuration
|
16
29
|
@logger = configuration.logger
|
17
30
|
@transport_configuration = configuration.transport
|
18
31
|
@dsn = configuration.dsn
|
19
32
|
@rate_limits = {}
|
33
|
+
@send_client_reports = configuration.send_client_reports
|
34
|
+
|
35
|
+
if @send_client_reports
|
36
|
+
@discarded_events = Hash.new(0)
|
37
|
+
@last_client_report_sent = Time.now
|
38
|
+
end
|
20
39
|
end
|
21
40
|
|
22
41
|
def send_data(data, options = {})
|
@@ -27,14 +46,9 @@ module Sentry
|
|
27
46
|
event_hash = event.to_hash
|
28
47
|
item_type = get_item_type(event_hash)
|
29
48
|
|
30
|
-
unless configuration.sending_allowed?
|
31
|
-
log_debug("Envelope [#{item_type}] not sent: #{configuration.error_messages}")
|
32
|
-
|
33
|
-
return
|
34
|
-
end
|
35
|
-
|
36
49
|
if is_rate_limited?(item_type)
|
37
50
|
log_info("Envelope [#{item_type}] not sent: rate limiting")
|
51
|
+
record_lost_event(:ratelimit_backoff, item_type)
|
38
52
|
|
39
53
|
return
|
40
54
|
end
|
@@ -91,20 +105,38 @@ module Sentry
|
|
91
105
|
|
92
106
|
def encode(event)
|
93
107
|
# Convert to hash
|
94
|
-
|
108
|
+
event_payload = event.to_hash
|
109
|
+
event_id = event_payload[:event_id] || event_payload["event_id"]
|
110
|
+
item_type = get_item_type(event_payload)
|
111
|
+
|
112
|
+
envelope = Envelope.new(
|
113
|
+
{
|
114
|
+
event_id: event_id,
|
115
|
+
dsn: @dsn.to_s,
|
116
|
+
sdk: Sentry.sdk_meta,
|
117
|
+
sent_at: Sentry.utc_now.iso8601
|
118
|
+
}
|
119
|
+
)
|
120
|
+
|
121
|
+
envelope.add_item(
|
122
|
+
{ type: item_type, content_type: 'application/json' },
|
123
|
+
event_payload
|
124
|
+
)
|
125
|
+
|
126
|
+
client_report_headers, client_report_payload = fetch_pending_client_report
|
127
|
+
envelope.add_item(client_report_headers, client_report_payload) if client_report_headers
|
95
128
|
|
96
|
-
|
97
|
-
item_type = get_item_type(event_hash)
|
129
|
+
log_info("Sending envelope [#{item_type}] #{event_id} to Sentry")
|
98
130
|
|
99
|
-
envelope
|
100
|
-
|
101
|
-
{"type":"#{item_type}","content_type":"application/json"}
|
102
|
-
#{JSON.generate(event_hash)}
|
103
|
-
ENVELOPE
|
131
|
+
envelope.to_s
|
132
|
+
end
|
104
133
|
|
105
|
-
|
134
|
+
def record_lost_event(reason, item_type)
|
135
|
+
return unless @send_client_reports
|
136
|
+
return unless CLIENT_REPORT_REASONS.include?(reason)
|
106
137
|
|
107
|
-
|
138
|
+
item_type ||= 'event'
|
139
|
+
@discarded_events[[reason, item_type]] += 1
|
108
140
|
end
|
109
141
|
|
110
142
|
private
|
@@ -112,6 +144,32 @@ module Sentry
|
|
112
144
|
def get_item_type(event_hash)
|
113
145
|
event_hash[:type] || event_hash["type"] || "event"
|
114
146
|
end
|
147
|
+
|
148
|
+
def fetch_pending_client_report
|
149
|
+
return nil unless @send_client_reports
|
150
|
+
return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
151
|
+
return nil if @discarded_events.empty?
|
152
|
+
|
153
|
+
discarded_events_hash = @discarded_events.map do |key, val|
|
154
|
+
reason, type = key
|
155
|
+
|
156
|
+
# 'event' has to be mapped to 'error'
|
157
|
+
category = type == 'transaction' ? 'transaction' : 'error'
|
158
|
+
|
159
|
+
{ reason: reason, category: category, quantity: val }
|
160
|
+
end
|
161
|
+
|
162
|
+
item_header = { type: 'client_report' }
|
163
|
+
item_payload = {
|
164
|
+
timestamp: Sentry.utc_now.iso8601,
|
165
|
+
discarded_events: discarded_events_hash
|
166
|
+
}
|
167
|
+
|
168
|
+
@discarded_events = Hash.new(0)
|
169
|
+
@last_client_report_sent = Time.now
|
170
|
+
|
171
|
+
[item_header, item_payload]
|
172
|
+
end
|
115
173
|
end
|
116
174
|
end
|
117
175
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
module CustomInspection
|
5
|
+
def inspect
|
6
|
+
attr_strings = (instance_variables - self.class::SKIP_INSPECTION_ATTRIBUTES).each_with_object([]) do |attr, result|
|
7
|
+
value = instance_variable_get(attr)
|
8
|
+
result << "#{attr}=#{value.inspect}" if value
|
9
|
+
end
|
10
|
+
|
11
|
+
"#<#{self.class.name} #{attr_strings.join(", ")}>"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Utils
|
3
5
|
module ExceptionCauseChain
|
4
6
|
def self.exception_to_array(exception)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
exceptions = [exception]
|
8
|
+
|
9
|
+
while exception.cause
|
10
|
+
exception = exception.cause
|
11
|
+
break if exceptions.any? { |e| e.object_id == exception.object_id }
|
10
12
|
|
11
|
-
|
12
|
-
end
|
13
|
-
exceptions
|
14
|
-
else
|
15
|
-
[exception]
|
13
|
+
exceptions << exception
|
16
14
|
end
|
15
|
+
|
16
|
+
exceptions
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
data/lib/sentry/utils/real_ip.rb
CHANGED
data/lib/sentry/version.rb
CHANGED