sentry-ruby 0.1.3 → 4.1.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/CHANGELOG.md +69 -0
- data/Gemfile +6 -1
- data/README.md +88 -8
- data/Rakefile +3 -1
- data/lib/sentry-ruby.rb +38 -3
- data/lib/sentry/background_worker.rb +37 -0
- data/lib/sentry/benchmarks/benchmark_transport.rb +14 -0
- data/lib/sentry/breadcrumb.rb +7 -7
- data/lib/sentry/breadcrumb/sentry_logger.rb +10 -26
- data/lib/sentry/breadcrumb_buffer.rb +2 -5
- data/lib/sentry/client.rb +25 -7
- data/lib/sentry/configuration.rb +88 -87
- data/lib/sentry/dsn.rb +6 -3
- data/lib/sentry/event.rb +32 -26
- data/lib/sentry/hub.rb +13 -2
- data/lib/sentry/interfaces/request.rb +1 -31
- data/lib/sentry/rack.rb +2 -2
- data/lib/sentry/rack/{capture_exception.rb → capture_exceptions.rb} +20 -11
- data/lib/sentry/rack/interface.rb +22 -0
- data/lib/sentry/rake.rb +17 -0
- data/lib/sentry/scope.rb +27 -5
- data/lib/sentry/span.rb +132 -0
- data/lib/sentry/transaction.rb +157 -0
- data/lib/sentry/transaction_event.rb +29 -0
- data/lib/sentry/transport.rb +16 -24
- data/lib/sentry/transport/http_transport.rb +8 -8
- data/lib/sentry/utils/request_id.rb +16 -0
- data/lib/sentry/version.rb +1 -1
- data/sentry-ruby.gemspec +1 -0
- metadata +25 -4
- data/lib/sentry/transport/state.rb +0 -40
@@ -10,11 +10,8 @@ module Sentry
|
|
10
10
|
@buffer = Array.new(size)
|
11
11
|
end
|
12
12
|
|
13
|
-
def record(crumb
|
14
|
-
if block_given?
|
15
|
-
crumb = Breadcrumb.new if crumb.nil?
|
16
|
-
yield(crumb)
|
17
|
-
end
|
13
|
+
def record(crumb)
|
14
|
+
yield(crumb) if block_given?
|
18
15
|
@buffer.slice!(0)
|
19
16
|
@buffer << crumb
|
20
17
|
end
|
data/lib/sentry/client.rb
CHANGED
@@ -20,8 +20,10 @@ module Sentry
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def capture_event(event, scope)
|
24
|
-
|
23
|
+
def capture_event(event, scope, hint = {})
|
24
|
+
return false unless configuration.sending_allowed?
|
25
|
+
|
26
|
+
scope.apply_to_event(event, hint)
|
25
27
|
|
26
28
|
if configuration.async?
|
27
29
|
begin
|
@@ -30,10 +32,16 @@ module Sentry
|
|
30
32
|
configuration.async.call(event.to_json_compatible)
|
31
33
|
rescue => e
|
32
34
|
configuration.logger.error(LOGGER_PROGNAME) { "async event sending failed: #{e.message}" }
|
33
|
-
send_event(event)
|
35
|
+
send_event(event, hint)
|
34
36
|
end
|
35
37
|
else
|
36
|
-
|
38
|
+
if hint.fetch(:background, true)
|
39
|
+
Sentry.background_worker.perform do
|
40
|
+
send_event(event, hint)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
send_event(event, hint)
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
event
|
@@ -51,10 +59,20 @@ module Sentry
|
|
51
59
|
Event.new(configuration: configuration, message: message)
|
52
60
|
end
|
53
61
|
|
54
|
-
def
|
55
|
-
|
62
|
+
def event_from_transaction(transaction)
|
63
|
+
TransactionEvent.new(configuration: configuration).tap do |event|
|
64
|
+
event.transaction = transaction.name
|
65
|
+
event.contexts.merge!(trace: transaction.get_trace_context)
|
66
|
+
event.timestamp = transaction.timestamp
|
67
|
+
event.start_timestamp = transaction.start_timestamp
|
68
|
+
|
69
|
+
finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
|
70
|
+
event.spans = finished_spans.map(&:to_hash)
|
71
|
+
end
|
72
|
+
end
|
56
73
|
|
57
|
-
|
74
|
+
def send_event(event, hint = nil)
|
75
|
+
event = configuration.before_send.call(event, hint) if configuration.before_send
|
58
76
|
if event.nil?
|
59
77
|
configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
|
60
78
|
return
|
data/lib/sentry/configuration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "concurrent/utility/processor_counter"
|
2
|
+
|
1
3
|
require "sentry/utils/exception_cause_chain"
|
2
4
|
require "sentry/dsn"
|
3
5
|
require "sentry/transport/configuration"
|
@@ -15,6 +17,37 @@ module Sentry
|
|
15
17
|
attr_reader :async
|
16
18
|
alias async? async
|
17
19
|
|
20
|
+
# to send events in a non-blocking way, sentry-ruby has its own background worker
|
21
|
+
# by default, the worker holds a thread pool that has [the number of processors] threads
|
22
|
+
# but you can configure it with this configuration option
|
23
|
+
# E.g.: config.background_worker_threads = 5
|
24
|
+
#
|
25
|
+
# if you want to send events synchronously, set the value to 0
|
26
|
+
# E.g.: config.background_worker_threads = 0
|
27
|
+
attr_accessor :background_worker_threads
|
28
|
+
|
29
|
+
# a proc/lambda that takes an array of stack traces
|
30
|
+
# it'll be used to silence (reduce) backtrace of the exception
|
31
|
+
#
|
32
|
+
# for example:
|
33
|
+
#
|
34
|
+
# ```ruby
|
35
|
+
# Sentry.configuration.backtrace_cleanup_callback = lambda do |backtrace|
|
36
|
+
# Rails.backtrace_cleaner.clean(backtrace)
|
37
|
+
# end
|
38
|
+
# ```
|
39
|
+
#
|
40
|
+
attr_accessor :backtrace_cleanup_callback
|
41
|
+
|
42
|
+
# Optional Proc, called before sending an event to the server/
|
43
|
+
# E.g.: lambda { |event| event }
|
44
|
+
# E.g.: lambda { |event| nil }
|
45
|
+
# E.g.: lambda { |event|
|
46
|
+
# event[:message] = 'a'
|
47
|
+
# event
|
48
|
+
# }
|
49
|
+
attr_reader :before_send
|
50
|
+
|
18
51
|
# An array of breadcrumbs loggers to be used. Available options are:
|
19
52
|
# - :sentry_logger
|
20
53
|
# - :active_support_logger
|
@@ -24,10 +57,13 @@ module Sentry
|
|
24
57
|
attr_accessor :context_lines
|
25
58
|
|
26
59
|
# RACK_ENV by default.
|
27
|
-
attr_reader :
|
60
|
+
attr_reader :environment
|
28
61
|
|
29
|
-
#
|
30
|
-
|
62
|
+
# the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
|
63
|
+
attr_reader :dsn
|
64
|
+
|
65
|
+
# Whitelist of enabled_environments that will send notifications to Sentry. Array of Strings.
|
66
|
+
attr_accessor :enabled_environments
|
31
67
|
|
32
68
|
# Logger 'progname's to exclude from breadcrumbs
|
33
69
|
attr_accessor :exclude_loggers
|
@@ -64,51 +100,36 @@ module Sentry
|
|
64
100
|
# any events, and a value of 1.0 will send 100% of events.
|
65
101
|
attr_accessor :sample_rate
|
66
102
|
|
67
|
-
# a proc/lambda that takes an array of stack traces
|
68
|
-
# it'll be used to silence (reduce) backtrace of the exception
|
69
|
-
#
|
70
|
-
# for example:
|
71
|
-
#
|
72
|
-
# ```ruby
|
73
|
-
# Sentry.configuration.backtrace_cleanup_callback = lambda do |backtrace|
|
74
|
-
# Rails.backtrace_cleaner.clean(backtrace)
|
75
|
-
# end
|
76
|
-
# ```
|
77
|
-
#
|
78
|
-
attr_accessor :backtrace_cleanup_callback
|
79
|
-
|
80
103
|
# Include module versions in reports - boolean.
|
81
104
|
attr_accessor :send_modules
|
82
105
|
|
106
|
+
# When send_default_pii's value is false (default), sensitive information like
|
107
|
+
# - user ip
|
108
|
+
# - user cookie
|
109
|
+
# - request body
|
110
|
+
# will not be sent to Sentry.
|
83
111
|
attr_accessor :send_default_pii
|
84
112
|
|
85
113
|
attr_accessor :server_name
|
86
114
|
|
87
|
-
#
|
88
|
-
# Note that the object passed into the block will be a String (messages) or
|
89
|
-
# an exception.
|
90
|
-
# e.g. lambda { |exc_or_msg| exc_or_msg.some_attr == false }
|
91
|
-
attr_reader :should_capture
|
92
|
-
|
93
|
-
# Silences ready message when true.
|
94
|
-
attr_accessor :silence_ready
|
95
|
-
|
115
|
+
# Return a Transport::Configuration object for transport-related configurations.
|
96
116
|
attr_reader :transport
|
97
117
|
|
98
|
-
#
|
99
|
-
|
100
|
-
# E.g.: lambda { |event| nil }
|
101
|
-
# E.g.: lambda { |event|
|
102
|
-
# event[:message] = 'a'
|
103
|
-
# event
|
104
|
-
# }
|
105
|
-
attr_reader :before_send
|
118
|
+
# Take a float between 0.0 and 1.0 as the sample rate for tracing events (transactions).
|
119
|
+
attr_accessor :traces_sample_rate
|
106
120
|
|
107
|
-
#
|
108
|
-
|
121
|
+
# Take a Proc that controls the sample rate for every tracing event, e.g.
|
122
|
+
# ```
|
123
|
+
# lambda do |tracing_context|
|
124
|
+
# # tracing_context[:transaction_context] contains the information about the transaction
|
125
|
+
# # tracing_context[:parent_sampled] contains the transaction's parent's sample decision
|
126
|
+
# true # return value can be a boolean or a float between 0.0 and 1.0
|
127
|
+
# end
|
128
|
+
# ```
|
129
|
+
attr_accessor :traces_sampler
|
109
130
|
|
110
|
-
#
|
111
|
-
attr_reader :
|
131
|
+
# these are not config options
|
132
|
+
attr_reader :errors, :gem_specs
|
112
133
|
|
113
134
|
# Most of these errors generate 4XX responses. In general, Sentry clients
|
114
135
|
# only automatically report 5xx responses.
|
@@ -136,10 +157,11 @@ module Sentry
|
|
136
157
|
|
137
158
|
def initialize
|
138
159
|
self.async = false
|
160
|
+
self.background_worker_threads = Concurrent.processor_count
|
139
161
|
self.breadcrumbs_logger = []
|
140
162
|
self.context_lines = 3
|
141
|
-
self.
|
142
|
-
self.
|
163
|
+
self.environment = environment_from_env
|
164
|
+
self.enabled_environments = []
|
143
165
|
self.exclude_loggers = []
|
144
166
|
self.excluded_exceptions = IGNORE_DEFAULT.dup
|
145
167
|
self.inspect_exception_causes_for_exclusion = false
|
@@ -153,11 +175,12 @@ module Sentry
|
|
153
175
|
self.send_default_pii = false
|
154
176
|
self.dsn = ENV['SENTRY_DSN']
|
155
177
|
self.server_name = server_name_from_env
|
156
|
-
self.should_capture = false
|
157
178
|
|
158
|
-
@transport = Transport::Configuration.new
|
159
179
|
self.before_send = false
|
160
180
|
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
181
|
+
|
182
|
+
@transport = Transport::Configuration.new
|
183
|
+
@gem_specs = Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
161
184
|
post_initialization_callback
|
162
185
|
end
|
163
186
|
|
@@ -195,14 +218,6 @@ module Sentry
|
|
195
218
|
@breadcrumbs_logger = logger
|
196
219
|
end
|
197
220
|
|
198
|
-
def should_capture=(value)
|
199
|
-
unless value == false || value.respond_to?(:call)
|
200
|
-
raise ArgumentError, "should_capture must be callable (or false to disable)"
|
201
|
-
end
|
202
|
-
|
203
|
-
@should_capture = value
|
204
|
-
end
|
205
|
-
|
206
221
|
def before_send=(value)
|
207
222
|
unless value == false || value.respond_to?(:call)
|
208
223
|
raise ArgumentError, "before_send must be callable (or false to disable)"
|
@@ -211,31 +226,21 @@ module Sentry
|
|
211
226
|
@before_send = value
|
212
227
|
end
|
213
228
|
|
214
|
-
|
215
|
-
|
216
|
-
# @param [Symbol] option Key for a given attribute
|
217
|
-
def [](option)
|
218
|
-
public_send(option)
|
229
|
+
def environment=(environment)
|
230
|
+
@environment = environment.to_s
|
219
231
|
end
|
220
232
|
|
221
|
-
def
|
222
|
-
@current_environment = environment.to_s
|
223
|
-
end
|
224
|
-
|
225
|
-
def capture_allowed?(message_or_exc = nil)
|
233
|
+
def sending_allowed?
|
226
234
|
@errors = []
|
227
235
|
|
228
236
|
valid? &&
|
229
|
-
|
230
|
-
capture_allowed_by_callback?(message_or_exc) &&
|
237
|
+
capture_in_environment? &&
|
231
238
|
sample_allowed?
|
232
239
|
end
|
233
|
-
# If we cannot capture, we cannot send.
|
234
|
-
alias sending_allowed? capture_allowed?
|
235
240
|
|
236
241
|
def error_messages
|
237
|
-
@errors = [errors[0]] + errors[1..-1].map(&:downcase) # fix case of all but first
|
238
|
-
errors.join(", ")
|
242
|
+
@errors = [@errors[0]] + @errors[1..-1].map(&:downcase) # fix case of all but first
|
243
|
+
@errors.join(", ")
|
239
244
|
end
|
240
245
|
|
241
246
|
def project_root=(root_dir)
|
@@ -256,7 +261,11 @@ module Sentry
|
|
256
261
|
end
|
257
262
|
|
258
263
|
def enabled_in_current_env?
|
259
|
-
|
264
|
+
enabled_environments.empty? || enabled_environments.include?(environment)
|
265
|
+
end
|
266
|
+
|
267
|
+
def tracing_enabled?
|
268
|
+
!!((@traces_sample_rate && @traces_sample_rate > 0.0) || @traces_sampler)
|
260
269
|
end
|
261
270
|
|
262
271
|
private
|
@@ -279,13 +288,17 @@ module Sentry
|
|
279
288
|
end
|
280
289
|
|
281
290
|
def excluded_exception?(incoming_exception)
|
282
|
-
|
283
|
-
matches_exception?(
|
291
|
+
excluded_exception_classes.any? do |excluded_exception|
|
292
|
+
matches_exception?(excluded_exception, incoming_exception)
|
284
293
|
end
|
285
294
|
end
|
286
295
|
|
296
|
+
def excluded_exception_classes
|
297
|
+
@excluded_exception_classes ||= excluded_exceptions.map { |e| get_exception_class(e) }
|
298
|
+
end
|
299
|
+
|
287
300
|
def get_exception_class(x)
|
288
|
-
x.is_a?(Module) ? x :
|
301
|
+
x.is_a?(Module) ? x : safe_const_get(x)
|
289
302
|
end
|
290
303
|
|
291
304
|
def matches_exception?(excluded_exception_class, incoming_exception)
|
@@ -296,14 +309,9 @@ module Sentry
|
|
296
309
|
end
|
297
310
|
end
|
298
311
|
|
299
|
-
|
300
|
-
|
301
|
-
x
|
302
|
-
if !x.match(/::/)
|
303
|
-
Object.const_get(x)
|
304
|
-
else
|
305
|
-
x.split(MODULE_SEPARATOR).reject(&:empty?).inject(Object) { |a, e| a.const_get(e) }
|
306
|
-
end
|
312
|
+
def safe_const_get(x)
|
313
|
+
x = x.to_s unless x.is_a?(String)
|
314
|
+
Object.const_get(x)
|
307
315
|
rescue NameError # There's no way to safely ask if a constant exist for an unknown string
|
308
316
|
nil
|
309
317
|
end
|
@@ -339,17 +347,10 @@ module Sentry
|
|
339
347
|
ENV['SENTRY_RELEASE']
|
340
348
|
end
|
341
349
|
|
342
|
-
def
|
350
|
+
def capture_in_environment?
|
343
351
|
return true if enabled_in_current_env?
|
344
352
|
|
345
|
-
@errors << "Not configured to send/capture in environment '#{
|
346
|
-
false
|
347
|
-
end
|
348
|
-
|
349
|
-
def capture_allowed_by_callback?(message_or_exc)
|
350
|
-
return true if !should_capture || message_or_exc.nil? || should_capture.call(message_or_exc)
|
351
|
-
|
352
|
-
@errors << "should_capture returned false"
|
353
|
+
@errors << "Not configured to send/capture in environment '#{environment}'"
|
353
354
|
false
|
354
355
|
end
|
355
356
|
|
@@ -380,7 +381,7 @@ module Sentry
|
|
380
381
|
Socket.gethostbyname(hostname).first rescue server_name
|
381
382
|
end
|
382
383
|
|
383
|
-
def
|
384
|
+
def environment_from_env
|
384
385
|
ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
|
385
386
|
end
|
386
387
|
|
data/lib/sentry/dsn.rb
CHANGED
@@ -2,7 +2,10 @@ require "uri"
|
|
2
2
|
|
3
3
|
module Sentry
|
4
4
|
class DSN
|
5
|
-
|
5
|
+
PORT_MAP = { 'http' => 80, 'https' => 443 }.freeze
|
6
|
+
REQUIRED_ATTRIBUTES = %w(host path public_key project_id).freeze
|
7
|
+
|
8
|
+
attr_reader :scheme, :secret_key, :port, *REQUIRED_ATTRIBUTES
|
6
9
|
|
7
10
|
def initialize(dsn_string)
|
8
11
|
@raw_value = dsn_string
|
@@ -24,7 +27,7 @@ module Sentry
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def valid?
|
27
|
-
|
30
|
+
REQUIRED_ATTRIBUTES.all? { |k| public_send(k) }
|
28
31
|
end
|
29
32
|
|
30
33
|
def to_s
|
@@ -33,7 +36,7 @@ module Sentry
|
|
33
36
|
|
34
37
|
def server
|
35
38
|
server = "#{scheme}://#{host}"
|
36
|
-
server += ":#{port}" unless port ==
|
39
|
+
server += ":#{port}" unless port == PORT_MAP[scheme]
|
37
40
|
server += path
|
38
41
|
server
|
39
42
|
end
|
data/lib/sentry/event.rb
CHANGED
@@ -5,6 +5,7 @@ require 'securerandom'
|
|
5
5
|
require 'sentry/interface'
|
6
6
|
require 'sentry/backtrace'
|
7
7
|
require 'sentry/utils/real_ip'
|
8
|
+
require 'sentry/utils/request_id'
|
8
9
|
|
9
10
|
module Sentry
|
10
11
|
class Event
|
@@ -13,21 +14,19 @@ module Sentry
|
|
13
14
|
release environment server_name modules
|
14
15
|
message user tags contexts extra
|
15
16
|
fingerprint breadcrumbs backtrace transaction
|
16
|
-
platform sdk
|
17
|
+
platform sdk type
|
17
18
|
)
|
18
19
|
|
19
20
|
attr_accessor(*ATTRIBUTES)
|
20
|
-
attr_reader :
|
21
|
-
|
22
|
-
alias event_id id
|
21
|
+
attr_reader :configuration, :request, :exception, :stacktrace
|
23
22
|
|
24
23
|
def initialize(configuration:, message: nil)
|
25
24
|
# this needs to go first because some setters rely on configuration
|
26
25
|
@configuration = configuration
|
27
26
|
|
28
27
|
# Set some simple default values
|
29
|
-
@
|
30
|
-
@timestamp =
|
28
|
+
@event_id = SecureRandom.uuid.delete("-")
|
29
|
+
@timestamp = Sentry.utc_now.iso8601
|
31
30
|
@platform = :ruby
|
32
31
|
@sdk = Sentry.sdk_meta
|
33
32
|
|
@@ -39,9 +38,9 @@ module Sentry
|
|
39
38
|
@fingerprint = []
|
40
39
|
|
41
40
|
@server_name = configuration.server_name
|
42
|
-
@environment = configuration.
|
41
|
+
@environment = configuration.environment
|
43
42
|
@release = configuration.release
|
44
|
-
@modules =
|
43
|
+
@modules = configuration.gem_specs if configuration.send_modules
|
45
44
|
|
46
45
|
@message = message || ""
|
47
46
|
|
@@ -51,8 +50,8 @@ module Sentry
|
|
51
50
|
class << self
|
52
51
|
def get_log_message(event_hash)
|
53
52
|
message = event_hash[:message] || event_hash['message']
|
54
|
-
message = get_message_from_exception(event_hash) if message.empty?
|
55
|
-
message = '<no message value>' if message.empty?
|
53
|
+
message = get_message_from_exception(event_hash) if message.nil? || message.empty?
|
54
|
+
message = '<no message value>' if message.nil? || message.empty?
|
56
55
|
message
|
57
56
|
end
|
58
57
|
|
@@ -68,7 +67,7 @@ module Sentry
|
|
68
67
|
end
|
69
68
|
|
70
69
|
def timestamp=(time)
|
71
|
-
@timestamp = time.is_a?(Time) ? time.
|
70
|
+
@timestamp = time.is_a?(Time) ? time.to_f : time
|
72
71
|
end
|
73
72
|
|
74
73
|
def level=(new_level) # needed to meet the Sentry spec
|
@@ -76,7 +75,7 @@ module Sentry
|
|
76
75
|
end
|
77
76
|
|
78
77
|
def rack_env=(env)
|
79
|
-
unless
|
78
|
+
unless request || env.empty?
|
80
79
|
@request = Sentry::RequestInterface.new.tap do |int|
|
81
80
|
int.from_rack(env)
|
82
81
|
end
|
@@ -84,18 +83,22 @@ module Sentry
|
|
84
83
|
if configuration.send_default_pii && ip = calculate_real_ip_from_rack(env.dup)
|
85
84
|
user[:ip_address] = ip
|
86
85
|
end
|
86
|
+
if request_id = Utils::RequestId.read_from(env)
|
87
|
+
tags[:request_id] = request_id
|
88
|
+
end
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
end
|
92
|
+
def type
|
93
|
+
"event"
|
94
|
+
end
|
94
95
|
|
96
|
+
def to_hash
|
97
|
+
data = serialize_attributes
|
95
98
|
data[:breadcrumbs] = breadcrumbs.to_hash if breadcrumbs
|
96
|
-
data[:stacktrace] =
|
97
|
-
data[:request] =
|
98
|
-
data[:exception] =
|
99
|
+
data[:stacktrace] = stacktrace.to_hash if stacktrace
|
100
|
+
data[:request] = request.to_hash if request
|
101
|
+
data[:exception] = exception.to_hash if exception
|
99
102
|
|
100
103
|
data
|
101
104
|
end
|
@@ -141,9 +144,9 @@ module Sentry
|
|
141
144
|
frame.in_app = line.in_app
|
142
145
|
frame.module = line.module_name if line.module_name
|
143
146
|
|
144
|
-
if configuration
|
147
|
+
if configuration.context_lines && frame.abs_path
|
145
148
|
frame.pre_context, frame.context_line, frame.post_context = \
|
146
|
-
configuration.linecache.get_file_context(frame.abs_path, frame.lineno, configuration
|
149
|
+
configuration.linecache.get_file_context(frame.abs_path, frame.lineno, configuration.context_lines)
|
147
150
|
end
|
148
151
|
|
149
152
|
memo << frame if frame.filename
|
@@ -152,6 +155,14 @@ module Sentry
|
|
152
155
|
|
153
156
|
private
|
154
157
|
|
158
|
+
def serialize_attributes
|
159
|
+
self.class::ATTRIBUTES.each_with_object({}) do |att, memo|
|
160
|
+
if value = public_send(att)
|
161
|
+
memo[att] = value
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
155
166
|
# When behind a proxy (or if the user is using a proxy), we can't use
|
156
167
|
# REMOTE_ADDR to determine the Event IP, and must use other headers instead.
|
157
168
|
def calculate_real_ip_from_rack(env)
|
@@ -162,10 +173,5 @@ module Sentry
|
|
162
173
|
:forwarded_for => env["HTTP_X_FORWARDED_FOR"]
|
163
174
|
).calculate_ip
|
164
175
|
end
|
165
|
-
|
166
|
-
def list_gem_specs
|
167
|
-
# Older versions of Rubygems don't support iterating over all specs
|
168
|
-
Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map)
|
169
|
-
end
|
170
176
|
end
|
171
177
|
end
|