sentry-raven 2.1.3 → 3.1.2
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 +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
|