sentry-raven 2.1.3 → 3.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.craft.yml +19 -0
- data/.scripts/bump-version.rb +5 -0
- data/CHANGELOG.md +703 -0
- data/Gemfile +37 -0
- data/Makefile +3 -0
- data/README.md +116 -18
- data/Rakefile +30 -0
- data/exe/raven +32 -0
- data/lib/raven/backtrace.rb +16 -6
- data/lib/raven/base.rb +17 -4
- data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
- data/lib/raven/breadcrumbs/logger.rb +2 -92
- data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
- data/lib/raven/breadcrumbs.rb +3 -1
- data/lib/raven/cli.rb +31 -43
- data/lib/raven/client.rb +39 -17
- data/lib/raven/configuration.rb +277 -37
- data/lib/raven/context.rb +17 -11
- data/lib/raven/core_ext/object/deep_dup.rb +57 -0
- data/lib/raven/core_ext/object/duplicable.rb +153 -0
- data/lib/raven/event.rb +172 -233
- data/lib/raven/helpers/deprecation_helper.rb +17 -0
- data/lib/raven/instance.rb +51 -25
- data/lib/raven/integrations/delayed_job.rb +18 -18
- data/lib/raven/integrations/rack-timeout.rb +11 -5
- data/lib/raven/integrations/rack.rb +36 -19
- data/lib/raven/integrations/rails/active_job.rb +52 -20
- data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
- data/lib/raven/integrations/rails/controller_transaction.rb +13 -0
- data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
- data/lib/raven/integrations/rails.rb +24 -8
- data/lib/raven/integrations/rake.rb +6 -1
- data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
- data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
- data/lib/raven/integrations/sidekiq.rb +6 -57
- data/lib/raven/interface.rb +2 -2
- data/lib/raven/interfaces/exception.rb +0 -2
- data/lib/raven/interfaces/http.rb +0 -2
- data/lib/raven/interfaces/message.rb +1 -1
- data/lib/raven/interfaces/single_exception.rb +0 -2
- data/lib/raven/interfaces/stack_trace.rb +19 -27
- data/lib/raven/linecache.rb +34 -17
- data/lib/raven/logger.rb +11 -18
- data/lib/raven/processor/cookies.rb +27 -7
- data/lib/raven/processor/http_headers.rb +18 -5
- data/lib/raven/processor/post_data.rb +16 -3
- data/lib/raven/processor/removecircularreferences.rb +12 -8
- data/lib/raven/processor/removestacktrace.rb +17 -6
- data/lib/raven/processor/sanitizedata.rb +88 -29
- data/lib/raven/processor/utf8conversion.rb +39 -14
- data/lib/raven/processor.rb +1 -1
- data/lib/raven/transports/http.rb +29 -21
- data/lib/raven/transports/stdout.rb +20 -0
- data/lib/raven/transports.rb +4 -8
- data/lib/raven/utils/context_filter.rb +42 -0
- data/lib/raven/utils/deep_merge.rb +6 -12
- data/lib/raven/utils/exception_cause_chain.rb +20 -0
- data/lib/raven/utils/real_ip.rb +1 -1
- data/lib/raven/utils/request_id.rb +16 -0
- data/lib/raven/version.rb +2 -2
- data/lib/sentry-raven-without-integrations.rb +6 -1
- data/lib/sentry_raven_without_integrations.rb +1 -0
- data/sentry-raven.gemspec +28 -0
- metadata +37 -103
- data/lib/raven/error.rb +0 -4
data/lib/raven/configuration.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'logger'
|
2
1
|
require 'uri'
|
3
2
|
|
4
3
|
module Raven
|
@@ -13,6 +12,11 @@ module Raven
|
|
13
12
|
attr_reader :async
|
14
13
|
alias async? async
|
15
14
|
|
15
|
+
# An array of breadcrumbs loggers to be used. Available options are:
|
16
|
+
# - :sentry_logger
|
17
|
+
# - :active_support_logger
|
18
|
+
attr_reader :breadcrumbs_logger
|
19
|
+
|
16
20
|
# Number of lines of code context to capture, or nil for none
|
17
21
|
attr_accessor :context_lines
|
18
22
|
|
@@ -32,12 +36,25 @@ module Raven
|
|
32
36
|
# You should probably append to this rather than overwrite it.
|
33
37
|
attr_accessor :excluded_exceptions
|
34
38
|
|
39
|
+
# Boolean to check nested exceptions when deciding if to exclude. Defaults to false
|
40
|
+
attr_accessor :inspect_exception_causes_for_exclusion
|
41
|
+
alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion
|
42
|
+
|
35
43
|
# DSN component - set automatically if DSN provided
|
36
44
|
attr_accessor :host
|
37
45
|
|
38
46
|
# The Faraday adapter to be used. Will default to Net::HTTP when not set.
|
39
47
|
attr_accessor :http_adapter
|
40
48
|
|
49
|
+
# A Proc yeilding the faraday builder allowing for further configuration
|
50
|
+
# of the faraday adapter
|
51
|
+
attr_accessor :faraday_builder
|
52
|
+
|
53
|
+
# You may provide your own LineCache for matching paths with source files.
|
54
|
+
# This may be useful if you need to get source code from places other than
|
55
|
+
# the disk. See Raven::LineCache for the required interface you must implement.
|
56
|
+
attr_accessor :linecache
|
57
|
+
|
41
58
|
# Logger used by Raven. In Rails, this is the Rails logger, otherwise
|
42
59
|
# Raven provides its own Raven::Logger.
|
43
60
|
attr_accessor :logger
|
@@ -71,7 +88,7 @@ module Raven
|
|
71
88
|
attr_accessor :public_key
|
72
89
|
|
73
90
|
# Turns on ActiveSupport breadcrumbs integration
|
74
|
-
|
91
|
+
attr_reader :rails_activesupport_breadcrumbs
|
75
92
|
|
76
93
|
# Rails catches exceptions in the ActionDispatch::ShowExceptions or
|
77
94
|
# ActionDispatch::DebugExceptions middlewares, depending on the environment.
|
@@ -83,6 +100,10 @@ module Raven
|
|
83
100
|
# We automatically try to set this to a git SHA or Capistrano release.
|
84
101
|
attr_accessor :release
|
85
102
|
|
103
|
+
# The sampling factor to apply to events. A value of 0.0 will not send
|
104
|
+
# any events, and a value of 1.0 will send 100% of events.
|
105
|
+
attr_accessor :sample_rate
|
106
|
+
|
86
107
|
# Boolean - sanitize values that look like credit card numbers
|
87
108
|
attr_accessor :sanitize_credit_cards
|
88
109
|
|
@@ -91,6 +112,10 @@ module Raven
|
|
91
112
|
# a hash key, will be censored and not sent to Sentry.
|
92
113
|
attr_accessor :sanitize_fields
|
93
114
|
|
115
|
+
# If you're sure you want to override the default sanitization values, you can
|
116
|
+
# add to them to an array of Strings here, e.g. %w(authorization password)
|
117
|
+
attr_accessor :sanitize_fields_excluded
|
118
|
+
|
94
119
|
# Sanitize additional HTTP headers - only Authorization is removed by default.
|
95
120
|
attr_accessor :sanitize_http_headers
|
96
121
|
|
@@ -98,8 +123,23 @@ module Raven
|
|
98
123
|
# Otherwise, can be one of "http", "https", or "dummy"
|
99
124
|
attr_accessor :scheme
|
100
125
|
|
126
|
+
# a proc/lambda that takes an array of stack traces
|
127
|
+
# it'll be used to silence (reduce) backtrace of the exception
|
128
|
+
#
|
129
|
+
# for example:
|
130
|
+
#
|
131
|
+
# ```ruby
|
132
|
+
# Raven.configuration.backtrace_cleanup_callback = lambda do |backtrace|
|
133
|
+
# Rails.backtrace_cleaner.clean(backtrace)
|
134
|
+
# end
|
135
|
+
# ```
|
136
|
+
#
|
137
|
+
attr_accessor :backtrace_cleanup_callback
|
138
|
+
|
101
139
|
# Secret key for authentication with the Sentry server
|
102
140
|
# If you provide a DSN, this will be set automatically.
|
141
|
+
#
|
142
|
+
# This is deprecated and not necessary for newer Sentry installations any more.
|
103
143
|
attr_accessor :secret_key
|
104
144
|
|
105
145
|
# Include module versions in reports - boolean.
|
@@ -114,7 +154,7 @@ module Raven
|
|
114
154
|
# Note that the object passed into the block will be a String (messages) or
|
115
155
|
# an exception.
|
116
156
|
# e.g. lambda { |exc_or_msg| exc_or_msg.some_attr == false }
|
117
|
-
|
157
|
+
attr_reader :should_capture
|
118
158
|
|
119
159
|
# Silences ready message when true.
|
120
160
|
attr_accessor :silence_ready
|
@@ -138,14 +178,45 @@ module Raven
|
|
138
178
|
# E.g. lambda { |event| Thread.new { MyJobProcessor.send_email(event) } }
|
139
179
|
attr_reader :transport_failure_callback
|
140
180
|
|
181
|
+
# Optional Proc, called before sending an event to the server/
|
182
|
+
# E.g.: lambda { |event, hint| event }
|
183
|
+
# E.g.: lambda { |event, hint| nil }
|
184
|
+
# E.g.: lambda { |event, hint|
|
185
|
+
# event[:message] = 'a'
|
186
|
+
# event
|
187
|
+
# }
|
188
|
+
attr_reader :before_send
|
189
|
+
|
190
|
+
# Errors object - an Array that contains error messages. See #
|
191
|
+
attr_reader :errors
|
192
|
+
|
193
|
+
# the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
|
194
|
+
attr_reader :dsn
|
195
|
+
|
196
|
+
# Array of rack env parameters to be included in the event sent to sentry.
|
197
|
+
attr_accessor :rack_env_whitelist
|
198
|
+
|
199
|
+
# Most of these errors generate 4XX responses. In general, Sentry clients
|
200
|
+
# only automatically report 5xx responses.
|
141
201
|
IGNORE_DEFAULT = [
|
142
202
|
'AbstractController::ActionNotFound',
|
203
|
+
'ActionController::BadRequest',
|
143
204
|
'ActionController::InvalidAuthenticityToken',
|
205
|
+
'ActionController::InvalidCrossOriginRequest',
|
206
|
+
'ActionController::MethodNotAllowed',
|
207
|
+
'ActionController::NotImplemented',
|
208
|
+
'ActionController::ParameterMissing',
|
144
209
|
'ActionController::RoutingError',
|
145
210
|
'ActionController::UnknownAction',
|
211
|
+
'ActionController::UnknownFormat',
|
212
|
+
'ActionController::UnknownHttpMethod',
|
213
|
+
'ActionDispatch::Http::Parameters::ParseError',
|
214
|
+
'ActiveJob::DeserializationError', # Can cause infinite loops
|
146
215
|
'ActiveRecord::RecordNotFound',
|
147
216
|
'CGI::Session::CookieStore::TamperedWithCookie',
|
148
217
|
'Mongoid::Errors::DocumentNotFound',
|
218
|
+
'Rack::QueryParser::InvalidParameterError',
|
219
|
+
'Rack::QueryParser::ParameterTypeError',
|
149
220
|
'Sinatra::NotFound'
|
150
221
|
].freeze
|
151
222
|
|
@@ -160,34 +231,61 @@ module Raven
|
|
160
231
|
Raven::Processor::HTTPHeaders
|
161
232
|
].freeze
|
162
233
|
|
234
|
+
HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\
|
235
|
+
"release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`".freeze
|
236
|
+
|
237
|
+
RACK_ENV_WHITELIST_DEFAULT = %w(
|
238
|
+
REMOTE_ADDR
|
239
|
+
SERVER_NAME
|
240
|
+
SERVER_PORT
|
241
|
+
).freeze
|
242
|
+
|
243
|
+
LOG_PREFIX = "** [Raven] ".freeze
|
244
|
+
MODULE_SEPARATOR = "::".freeze
|
245
|
+
|
246
|
+
AVAILABLE_BREADCRUMBS_LOGGERS = [:sentry_logger, :active_support_logger].freeze
|
247
|
+
|
163
248
|
def initialize
|
164
249
|
self.async = false
|
250
|
+
self.breadcrumbs_logger = []
|
165
251
|
self.context_lines = 3
|
166
|
-
self.current_environment =
|
252
|
+
self.current_environment = current_environment_from_env
|
167
253
|
self.encoding = 'gzip'
|
168
254
|
self.environments = []
|
169
255
|
self.exclude_loggers = []
|
170
256
|
self.excluded_exceptions = IGNORE_DEFAULT.dup
|
257
|
+
self.inspect_exception_causes_for_exclusion = false
|
258
|
+
self.linecache = ::Raven::LineCache.new
|
259
|
+
self.logger = ::Raven::Logger.new(STDOUT)
|
171
260
|
self.open_timeout = 1
|
172
261
|
self.processors = DEFAULT_PROCESSORS.dup
|
173
|
-
self.
|
174
|
-
|
262
|
+
self.project_root = detect_project_root
|
263
|
+
@rails_activesupport_breadcrumbs = false
|
264
|
+
|
175
265
|
self.rails_report_rescued_exceptions = true
|
176
266
|
self.release = detect_release
|
267
|
+
self.sample_rate = 1.0
|
177
268
|
self.sanitize_credit_cards = true
|
178
269
|
self.sanitize_fields = []
|
270
|
+
self.sanitize_fields_excluded = []
|
179
271
|
self.sanitize_http_headers = []
|
180
272
|
self.send_modules = true
|
181
|
-
self.server = ENV['SENTRY_DSN']
|
182
|
-
self.server_name =
|
273
|
+
self.server = ENV['SENTRY_DSN']
|
274
|
+
self.server_name = server_name_from_env
|
183
275
|
self.should_capture = false
|
184
276
|
self.ssl_verification = true
|
185
277
|
self.tags = {}
|
186
278
|
self.timeout = 2
|
187
279
|
self.transport_failure_callback = false
|
280
|
+
self.before_send = false
|
281
|
+
self.rack_env_whitelist = RACK_ENV_WHITELIST_DEFAULT
|
188
282
|
end
|
189
283
|
|
190
284
|
def server=(value)
|
285
|
+
return if value.nil?
|
286
|
+
|
287
|
+
@dsn = value
|
288
|
+
|
191
289
|
uri = URI.parse(value)
|
192
290
|
uri_path = uri.path.split('/')
|
193
291
|
|
@@ -195,7 +293,7 @@ module Raven
|
|
195
293
|
# DSN-style string
|
196
294
|
self.project_id = uri_path.pop
|
197
295
|
self.public_key = uri.user
|
198
|
-
self.secret_key = uri.password
|
296
|
+
self.secret_key = !(uri.password.nil? || uri.password.empty?) ? uri.password : nil
|
199
297
|
end
|
200
298
|
|
201
299
|
self.scheme = uri.scheme
|
@@ -205,13 +303,14 @@ module Raven
|
|
205
303
|
|
206
304
|
# For anyone who wants to read the base server string
|
207
305
|
@server = "#{scheme}://#{host}"
|
208
|
-
@server
|
209
|
-
@server
|
306
|
+
@server += ":#{port}" unless port == { 'http' => 80, 'https' => 443 }[scheme]
|
307
|
+
@server += path
|
210
308
|
end
|
211
309
|
alias dsn= server=
|
212
310
|
|
213
311
|
def encoding=(encoding)
|
214
312
|
raise(Error, 'Unsupported encoding') unless %w(gzip json).include? encoding
|
313
|
+
|
215
314
|
@encoding = encoding
|
216
315
|
end
|
217
316
|
|
@@ -219,13 +318,32 @@ module Raven
|
|
219
318
|
unless value == false || value.respond_to?(:call)
|
220
319
|
raise(ArgumentError, "async must be callable (or false to disable)")
|
221
320
|
end
|
321
|
+
|
222
322
|
@async = value
|
223
323
|
end
|
224
324
|
|
325
|
+
def breadcrumbs_logger=(logger)
|
326
|
+
loggers =
|
327
|
+
if logger.is_a?(Array)
|
328
|
+
logger
|
329
|
+
else
|
330
|
+
unless AVAILABLE_BREADCRUMBS_LOGGERS.include?(logger)
|
331
|
+
raise Raven::Error, "Unsupported breadcrumbs logger. Supported loggers: #{AVAILABLE_BREADCRUMBS_LOGGERS}"
|
332
|
+
end
|
333
|
+
|
334
|
+
Array(logger)
|
335
|
+
end
|
336
|
+
|
337
|
+
require "raven/breadcrumbs/sentry_logger" if loggers.include?(:sentry_logger)
|
338
|
+
|
339
|
+
@breadcrumbs_logger = logger
|
340
|
+
end
|
341
|
+
|
225
342
|
def transport_failure_callback=(value)
|
226
343
|
unless value == false || value.respond_to?(:call)
|
227
344
|
raise(ArgumentError, "transport_failure_callback must be callable (or false to disable)")
|
228
345
|
end
|
346
|
+
|
229
347
|
@transport_failure_callback = value
|
230
348
|
end
|
231
349
|
|
@@ -233,9 +351,18 @@ module Raven
|
|
233
351
|
unless value == false || value.respond_to?(:call)
|
234
352
|
raise ArgumentError, "should_capture must be callable (or false to disable)"
|
235
353
|
end
|
354
|
+
|
236
355
|
@should_capture = value
|
237
356
|
end
|
238
357
|
|
358
|
+
def before_send=(value)
|
359
|
+
unless value == false || value.respond_to?(:call)
|
360
|
+
raise ArgumentError, "before_send must be callable (or false to disable)"
|
361
|
+
end
|
362
|
+
|
363
|
+
@before_send = value
|
364
|
+
end
|
365
|
+
|
239
366
|
# Allows config options to be read like a hash
|
240
367
|
#
|
241
368
|
# @param [Symbol] option Key for a given attribute
|
@@ -248,17 +375,19 @@ module Raven
|
|
248
375
|
end
|
249
376
|
|
250
377
|
def capture_allowed?(message_or_exc = nil)
|
251
|
-
|
252
|
-
capture_allowed_by_callback?(message_or_exc)
|
253
|
-
end
|
378
|
+
@errors = []
|
254
379
|
|
380
|
+
valid? &&
|
381
|
+
capture_in_current_environment? &&
|
382
|
+
capture_allowed_by_callback?(message_or_exc) &&
|
383
|
+
sample_allowed?
|
384
|
+
end
|
255
385
|
# If we cannot capture, we cannot send.
|
256
386
|
alias sending_allowed? capture_allowed?
|
257
387
|
|
258
|
-
def
|
259
|
-
|
260
|
-
|
261
|
-
end
|
388
|
+
def error_messages
|
389
|
+
@errors = [errors[0]] + errors[1..-1].map(&:downcase) # fix case of all but first
|
390
|
+
errors.join(", ")
|
262
391
|
end
|
263
392
|
|
264
393
|
def project_root=(root_dir)
|
@@ -266,45 +395,144 @@ module Raven
|
|
266
395
|
Backtrace::Line.instance_variable_set(:@in_app_pattern, nil) # blow away cache
|
267
396
|
end
|
268
397
|
|
398
|
+
def rails_activesupport_breadcrumbs=(val)
|
399
|
+
DeprecationHelper.deprecate_old_breadcrumbs_configuration(:active_support_logger)
|
400
|
+
@rails_activesupport_breadcrumbs = val
|
401
|
+
end
|
402
|
+
|
403
|
+
def exception_class_allowed?(exc)
|
404
|
+
if exc.is_a?(Raven::Error)
|
405
|
+
# Try to prevent error reporting loops
|
406
|
+
logger.debug "Refusing to capture Raven error: #{exc.inspect}"
|
407
|
+
false
|
408
|
+
elsif excluded_exception?(exc)
|
409
|
+
logger.debug "User excluded error: #{exc.inspect}"
|
410
|
+
false
|
411
|
+
else
|
412
|
+
true
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def enabled_in_current_env?
|
417
|
+
environments.empty? || environments.include?(current_environment)
|
418
|
+
end
|
419
|
+
|
420
|
+
private
|
421
|
+
|
422
|
+
def detect_project_root
|
423
|
+
if defined? Rails.root # we are in a Rails application
|
424
|
+
Rails.root.to_s
|
425
|
+
else
|
426
|
+
Dir.pwd
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
269
430
|
def detect_release
|
270
|
-
|
431
|
+
detect_release_from_env ||
|
432
|
+
detect_release_from_git ||
|
271
433
|
detect_release_from_capistrano ||
|
272
434
|
detect_release_from_heroku
|
435
|
+
rescue => e
|
436
|
+
logger.error "Error detecting release: #{e.message}"
|
273
437
|
end
|
274
438
|
|
275
|
-
|
439
|
+
def excluded_exception?(incoming_exception)
|
440
|
+
excluded_exceptions.any? do |excluded_exception|
|
441
|
+
matches_exception?(get_exception_class(excluded_exception), incoming_exception)
|
442
|
+
end
|
443
|
+
end
|
276
444
|
|
277
|
-
def
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
445
|
+
def get_exception_class(x)
|
446
|
+
x.is_a?(Module) ? x : qualified_const_get(x)
|
447
|
+
end
|
448
|
+
|
449
|
+
def matches_exception?(excluded_exception_class, incoming_exception)
|
450
|
+
if inspect_exception_causes_for_exclusion?
|
451
|
+
Raven::Utils::ExceptionCauseChain.exception_to_array(incoming_exception).any? { |cause| excluded_exception_class === cause }
|
452
|
+
else
|
453
|
+
excluded_exception_class === incoming_exception
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
# In Ruby <2.0 const_get can't lookup "SomeModule::SomeClass" in one go
|
458
|
+
def qualified_const_get(x)
|
459
|
+
x = x.to_s
|
460
|
+
if !x.match(/::/)
|
461
|
+
Object.const_get(x)
|
462
|
+
else
|
463
|
+
x.split(MODULE_SEPARATOR).reject(&:empty?).inject(Object) { |a, e| a.const_get(e) }
|
287
464
|
end
|
465
|
+
rescue NameError # There's no way to safely ask if a constant exist for an unknown string
|
466
|
+
nil
|
467
|
+
end
|
468
|
+
|
469
|
+
def detect_release_from_heroku
|
470
|
+
return unless running_on_heroku?
|
471
|
+
return if ENV['CI']
|
472
|
+
logger.warn(HEROKU_DYNO_METADATA_MESSAGE) && return unless ENV['HEROKU_SLUG_COMMIT']
|
473
|
+
|
474
|
+
ENV['HEROKU_SLUG_COMMIT']
|
475
|
+
end
|
476
|
+
|
477
|
+
def running_on_heroku?
|
478
|
+
File.directory?("/etc/heroku")
|
288
479
|
end
|
289
480
|
|
290
481
|
def detect_release_from_capistrano
|
291
|
-
|
482
|
+
revision_file = File.join(project_root, 'REVISION')
|
483
|
+
revision_log = File.join(project_root, '..', 'revisions.log')
|
292
484
|
|
293
|
-
|
294
|
-
|
485
|
+
if File.exist?(revision_file)
|
486
|
+
File.read(revision_file).strip
|
487
|
+
elsif File.exist?(revision_log)
|
488
|
+
File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1')
|
489
|
+
end
|
295
490
|
end
|
296
491
|
|
297
492
|
def detect_release_from_git
|
298
|
-
|
493
|
+
Raven.sys_command("git rev-parse --short HEAD") if File.directory?(".git")
|
494
|
+
end
|
495
|
+
|
496
|
+
def detect_release_from_env
|
497
|
+
ENV['SENTRY_RELEASE']
|
299
498
|
end
|
300
499
|
|
301
500
|
def capture_in_current_environment?
|
302
|
-
|
501
|
+
return true if enabled_in_current_env?
|
502
|
+
|
503
|
+
@errors << "Not configured to send/capture in environment '#{current_environment}'"
|
504
|
+
false
|
303
505
|
end
|
304
506
|
|
305
507
|
def capture_allowed_by_callback?(message_or_exc)
|
306
|
-
return true if !should_capture || message_or_exc.nil?
|
307
|
-
|
508
|
+
return true if !should_capture || message_or_exc.nil? || should_capture.call(message_or_exc)
|
509
|
+
|
510
|
+
@errors << "should_capture returned false"
|
511
|
+
false
|
512
|
+
end
|
513
|
+
|
514
|
+
def valid?
|
515
|
+
return true if %w(server host path public_key project_id).all? { |k| public_send(k) }
|
516
|
+
|
517
|
+
if server
|
518
|
+
%w(server host path public_key project_id).map do |key|
|
519
|
+
@errors << "No #{key} specified" unless public_send(key)
|
520
|
+
end
|
521
|
+
else
|
522
|
+
@errors << "DSN not set"
|
523
|
+
end
|
524
|
+
false
|
525
|
+
end
|
526
|
+
|
527
|
+
def sample_allowed?
|
528
|
+
return true if sample_rate == 1.0
|
529
|
+
|
530
|
+
if Random::DEFAULT.rand >= sample_rate
|
531
|
+
@errors << "Excluded by random sample"
|
532
|
+
false
|
533
|
+
else
|
534
|
+
true
|
535
|
+
end
|
308
536
|
end
|
309
537
|
|
310
538
|
# Try to resolve the hostname to an FQDN, but fall back to whatever
|
@@ -313,5 +541,17 @@ module Raven
|
|
313
541
|
Socket.gethostname ||
|
314
542
|
Socket.gethostbyname(hostname).first rescue server_name
|
315
543
|
end
|
544
|
+
|
545
|
+
def current_environment_from_env
|
546
|
+
ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
|
547
|
+
end
|
548
|
+
|
549
|
+
def server_name_from_env
|
550
|
+
if running_on_heroku?
|
551
|
+
ENV['DYNO']
|
552
|
+
else
|
553
|
+
resolve_hostname
|
554
|
+
end
|
555
|
+
end
|
316
556
|
end
|
317
557
|
end
|
data/lib/raven/context.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rbconfig'
|
2
|
+
require 'etc'
|
2
3
|
|
3
4
|
module Raven
|
4
5
|
class Context
|
@@ -10,31 +11,36 @@ module Raven
|
|
10
11
|
Thread.current[:sentry_context] = nil
|
11
12
|
end
|
12
13
|
|
13
|
-
attr_accessor :extra, :server_os, :rack_env, :runtime, :tags, :user
|
14
|
+
attr_accessor :transaction, :extra, :server_os, :rack_env, :runtime, :tags, :user
|
14
15
|
|
15
16
|
def initialize
|
16
|
-
self.extra = {}
|
17
17
|
self.server_os = self.class.os_context
|
18
|
-
self.rack_env = nil
|
19
18
|
self.runtime = self.class.runtime_context
|
19
|
+
self.extra = { :server => { :os => server_os, :runtime => runtime } }
|
20
|
+
self.rack_env = nil
|
20
21
|
self.tags = {}
|
21
22
|
self.user = {}
|
23
|
+
self.transaction = []
|
22
24
|
end
|
23
25
|
|
24
26
|
class << self
|
25
27
|
def os_context
|
26
|
-
@os_context ||=
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
@os_context ||=
|
29
|
+
begin
|
30
|
+
uname = Etc.uname
|
31
|
+
{
|
32
|
+
name: uname[:sysname] || RbConfig::CONFIG["host_os"],
|
33
|
+
version: uname[:version],
|
34
|
+
build: uname[:release],
|
35
|
+
kernel_version: uname[:version]
|
36
|
+
}
|
37
|
+
end
|
32
38
|
end
|
33
39
|
|
34
40
|
def runtime_context
|
35
41
|
@runtime_context ||= {
|
36
|
-
|
37
|
-
|
42
|
+
name: RbConfig::CONFIG["ruby_install_name"],
|
43
|
+
version: RUBY_DESCRIPTION || Raven.sys_command("ruby -v")
|
38
44
|
}
|
39
45
|
end
|
40
46
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'raven/core_ext/object/duplicable'
|
2
|
+
|
3
|
+
#########################################
|
4
|
+
# This file was copied from Rails 5.2 #
|
5
|
+
#########################################
|
6
|
+
|
7
|
+
class Object
|
8
|
+
# Returns a deep copy of object if it's duplicable. If it's
|
9
|
+
# not duplicable, returns +self+.
|
10
|
+
#
|
11
|
+
# object = Object.new
|
12
|
+
# dup = object.deep_dup
|
13
|
+
# dup.instance_variable_set(:@a, 1)
|
14
|
+
#
|
15
|
+
# object.instance_variable_defined?(:@a) # => false
|
16
|
+
# dup.instance_variable_defined?(:@a) # => true
|
17
|
+
def deep_dup
|
18
|
+
duplicable? ? dup : self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Array
|
23
|
+
# Returns a deep copy of array.
|
24
|
+
#
|
25
|
+
# array = [1, [2, 3]]
|
26
|
+
# dup = array.deep_dup
|
27
|
+
# dup[1][2] = 4
|
28
|
+
#
|
29
|
+
# array[1][2] # => nil
|
30
|
+
# dup[1][2] # => 4
|
31
|
+
def deep_dup
|
32
|
+
map(&:deep_dup)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Hash
|
37
|
+
# Returns a deep copy of hash.
|
38
|
+
#
|
39
|
+
# hash = { a: { b: 'b' } }
|
40
|
+
# dup = hash.deep_dup
|
41
|
+
# dup[:a][:c] = 'c'
|
42
|
+
#
|
43
|
+
# hash[:a][:c] # => nil
|
44
|
+
# dup[:a][:c] # => "c"
|
45
|
+
def deep_dup
|
46
|
+
hash = dup
|
47
|
+
each_pair do |key, value|
|
48
|
+
if key.frozen? && ::String === key
|
49
|
+
hash[key] = value.deep_dup
|
50
|
+
else
|
51
|
+
hash.delete(key)
|
52
|
+
hash[key.deep_dup] = value.deep_dup
|
53
|
+
end
|
54
|
+
end
|
55
|
+
hash
|
56
|
+
end
|
57
|
+
end
|