sentry-raven 2.13.0 → 3.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/.craft.yml +15 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- data/.github/pull_request_template.md +16 -0
- data/.github/workflows/test.yml +92 -0
- data/.github/workflows/zeus_upload.yml +32 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +50 -12
- data/.scripts/bump-version.sh +9 -0
- data/{changelog.md → CHANGELOG.md} +155 -1
- data/CONTRIBUTING.md +71 -0
- data/Gemfile +20 -25
- data/README.md +26 -16
- data/lib/raven/backtrace.rb +9 -5
- data/lib/raven/base.rb +6 -2
- 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 +1 -1
- data/lib/raven/cli.rb +10 -21
- data/lib/raven/client.rb +9 -4
- data/lib/raven/configuration.rb +86 -10
- data/lib/raven/context.rb +13 -8
- 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 +27 -15
- data/lib/raven/helpers/deprecation_helper.rb +17 -0
- data/lib/raven/instance.rb +9 -4
- data/lib/raven/integrations/delayed_job.rb +13 -14
- data/lib/raven/integrations/rack-timeout.rb +7 -4
- data/lib/raven/integrations/rack.rb +4 -3
- data/lib/raven/integrations/rails/active_job.rb +6 -4
- data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
- data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
- data/lib/raven/integrations/rails.rb +13 -3
- data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
- data/lib/raven/integrations/sidekiq/context_filter.rb +42 -0
- data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
- data/lib/raven/integrations/sidekiq.rb +4 -78
- data/lib/raven/interface.rb +2 -2
- data/lib/raven/interfaces/stack_trace.rb +1 -1
- data/lib/raven/linecache.rb +5 -2
- data/lib/raven/logger.rb +3 -2
- data/lib/raven/processor/cookies.rb +16 -6
- data/lib/raven/processor/post_data.rb +2 -0
- data/lib/raven/processor/removecircularreferences.rb +3 -1
- data/lib/raven/processor/sanitizedata.rb +65 -17
- data/lib/raven/processor/utf8conversion.rb +2 -0
- data/lib/raven/transports/http.rb +5 -5
- data/lib/raven/transports.rb +4 -0
- data/lib/raven/utils/exception_cause_chain.rb +1 -0
- data/lib/raven/utils/real_ip.rb +1 -1
- 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 +2 -2
- metadata +21 -12
- data/.travis.yml +0 -47
data/lib/raven/configuration.rb
CHANGED
@@ -12,6 +12,11 @@ module Raven
|
|
12
12
|
attr_reader :async
|
13
13
|
alias async? async
|
14
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
|
+
|
15
20
|
# Number of lines of code context to capture, or nil for none
|
16
21
|
attr_accessor :context_lines
|
17
22
|
|
@@ -83,7 +88,7 @@ module Raven
|
|
83
88
|
attr_accessor :public_key
|
84
89
|
|
85
90
|
# Turns on ActiveSupport breadcrumbs integration
|
86
|
-
|
91
|
+
attr_reader :rails_activesupport_breadcrumbs
|
87
92
|
|
88
93
|
# Rails catches exceptions in the ActionDispatch::ShowExceptions or
|
89
94
|
# ActionDispatch::DebugExceptions middlewares, depending on the environment.
|
@@ -118,6 +123,19 @@ module Raven
|
|
118
123
|
# Otherwise, can be one of "http", "https", or "dummy"
|
119
124
|
attr_accessor :scheme
|
120
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
|
+
|
121
139
|
# Secret key for authentication with the Sentry server
|
122
140
|
# If you provide a DSN, this will be set automatically.
|
123
141
|
#
|
@@ -172,16 +190,32 @@ module Raven
|
|
172
190
|
# Errors object - an Array that contains error messages. See #
|
173
191
|
attr_reader :errors
|
174
192
|
|
193
|
+
# the dsn value, whether it's set via `config.dsn=` or `ENV["SENTRY_DSN"]`
|
194
|
+
attr_reader :dsn
|
195
|
+
|
196
|
+
# Most of these errors generate 4XX responses. In general, Sentry clients
|
197
|
+
# only automatically report 5xx responses.
|
175
198
|
IGNORE_DEFAULT = [
|
176
199
|
'AbstractController::ActionNotFound',
|
200
|
+
'ActionController::BadRequest',
|
177
201
|
'ActionController::InvalidAuthenticityToken',
|
202
|
+
'ActionController::InvalidCrossOriginRequest',
|
203
|
+
'ActionController::MethodNotAllowed',
|
204
|
+
'ActionController::NotImplemented',
|
205
|
+
'ActionController::ParameterMissing',
|
178
206
|
'ActionController::RoutingError',
|
179
207
|
'ActionController::UnknownAction',
|
208
|
+
'ActionController::UnknownFormat',
|
209
|
+
'ActionController::UnknownHttpMethod',
|
210
|
+
'ActionDispatch::Http::Parameters::ParseError',
|
211
|
+
'ActionView::MissingTemplate',
|
212
|
+
'ActiveJob::DeserializationError', # Can cause infinite loops
|
180
213
|
'ActiveRecord::RecordNotFound',
|
181
214
|
'CGI::Session::CookieStore::TamperedWithCookie',
|
182
215
|
'Mongoid::Errors::DocumentNotFound',
|
183
|
-
'
|
184
|
-
'
|
216
|
+
'Rack::QueryParser::InvalidParameterError',
|
217
|
+
'Rack::QueryParser::ParameterTypeError',
|
218
|
+
'Sinatra::NotFound'
|
185
219
|
].freeze
|
186
220
|
|
187
221
|
# Note the order - we have to remove circular references and bad characters
|
@@ -201,8 +235,11 @@ module Raven
|
|
201
235
|
LOG_PREFIX = "** [Raven] ".freeze
|
202
236
|
MODULE_SEPARATOR = "::".freeze
|
203
237
|
|
238
|
+
AVAILABLE_BREADCRUMBS_LOGGERS = [:sentry_logger, :active_support_logger].freeze
|
239
|
+
|
204
240
|
def initialize
|
205
241
|
self.async = false
|
242
|
+
self.breadcrumbs_logger = []
|
206
243
|
self.context_lines = 3
|
207
244
|
self.current_environment = current_environment_from_env
|
208
245
|
self.encoding = 'gzip'
|
@@ -215,7 +252,8 @@ module Raven
|
|
215
252
|
self.open_timeout = 1
|
216
253
|
self.processors = DEFAULT_PROCESSORS.dup
|
217
254
|
self.project_root = detect_project_root
|
218
|
-
|
255
|
+
@rails_activesupport_breadcrumbs = false
|
256
|
+
|
219
257
|
self.rails_report_rescued_exceptions = true
|
220
258
|
self.release = detect_release
|
221
259
|
self.sample_rate = 1.0
|
@@ -236,6 +274,9 @@ module Raven
|
|
236
274
|
|
237
275
|
def server=(value)
|
238
276
|
return if value.nil?
|
277
|
+
|
278
|
+
@dsn = value
|
279
|
+
|
239
280
|
uri = URI.parse(value)
|
240
281
|
uri_path = uri.path.split('/')
|
241
282
|
|
@@ -253,13 +294,14 @@ module Raven
|
|
253
294
|
|
254
295
|
# For anyone who wants to read the base server string
|
255
296
|
@server = "#{scheme}://#{host}"
|
256
|
-
@server
|
257
|
-
@server
|
297
|
+
@server += ":#{port}" unless port == { 'http' => 80, 'https' => 443 }[scheme]
|
298
|
+
@server += path
|
258
299
|
end
|
259
300
|
alias dsn= server=
|
260
301
|
|
261
302
|
def encoding=(encoding)
|
262
303
|
raise(Error, 'Unsupported encoding') unless %w(gzip json).include? encoding
|
304
|
+
|
263
305
|
@encoding = encoding
|
264
306
|
end
|
265
307
|
|
@@ -267,13 +309,32 @@ module Raven
|
|
267
309
|
unless value == false || value.respond_to?(:call)
|
268
310
|
raise(ArgumentError, "async must be callable (or false to disable)")
|
269
311
|
end
|
312
|
+
|
270
313
|
@async = value
|
271
314
|
end
|
272
315
|
|
316
|
+
def breadcrumbs_logger=(logger)
|
317
|
+
loggers =
|
318
|
+
if logger.is_a?(Array)
|
319
|
+
logger
|
320
|
+
else
|
321
|
+
unless AVAILABLE_BREADCRUMBS_LOGGERS.include?(logger)
|
322
|
+
raise Raven::Error, "Unsupported breadcrumbs logger. Supported loggers: #{AVAILABLE_BREADCRUMBS_LOGGERS}"
|
323
|
+
end
|
324
|
+
|
325
|
+
Array(logger)
|
326
|
+
end
|
327
|
+
|
328
|
+
require "raven/breadcrumbs/sentry_logger" if loggers.include?(:sentry_logger)
|
329
|
+
|
330
|
+
@breadcrumbs_logger = logger
|
331
|
+
end
|
332
|
+
|
273
333
|
def transport_failure_callback=(value)
|
274
334
|
unless value == false || value.respond_to?(:call)
|
275
335
|
raise(ArgumentError, "transport_failure_callback must be callable (or false to disable)")
|
276
336
|
end
|
337
|
+
|
277
338
|
@transport_failure_callback = value
|
278
339
|
end
|
279
340
|
|
@@ -281,6 +342,7 @@ module Raven
|
|
281
342
|
unless value == false || value.respond_to?(:call)
|
282
343
|
raise ArgumentError, "should_capture must be callable (or false to disable)"
|
283
344
|
end
|
345
|
+
|
284
346
|
@should_capture = value
|
285
347
|
end
|
286
348
|
|
@@ -288,6 +350,7 @@ module Raven
|
|
288
350
|
unless value == false || value.respond_to?(:call)
|
289
351
|
raise ArgumentError, "before_send must be callable (or false to disable)"
|
290
352
|
end
|
353
|
+
|
291
354
|
@before_send = value
|
292
355
|
end
|
293
356
|
|
@@ -323,6 +386,11 @@ module Raven
|
|
323
386
|
Backtrace::Line.instance_variable_set(:@in_app_pattern, nil) # blow away cache
|
324
387
|
end
|
325
388
|
|
389
|
+
def rails_activesupport_breadcrumbs=(val)
|
390
|
+
DeprecationHelper.deprecate_old_breadcrumbs_configuration(:active_support_logger)
|
391
|
+
@rails_activesupport_breadcrumbs = val
|
392
|
+
end
|
393
|
+
|
326
394
|
def exception_class_allowed?(exc)
|
327
395
|
if exc.is_a?(Raven::Error)
|
328
396
|
# Try to prevent error reporting loops
|
@@ -336,6 +404,10 @@ module Raven
|
|
336
404
|
end
|
337
405
|
end
|
338
406
|
|
407
|
+
def enabled_in_current_env?
|
408
|
+
environments.empty? || environments.include?(current_environment)
|
409
|
+
end
|
410
|
+
|
339
411
|
private
|
340
412
|
|
341
413
|
def detect_project_root
|
@@ -351,8 +423,8 @@ module Raven
|
|
351
423
|
detect_release_from_git ||
|
352
424
|
detect_release_from_capistrano ||
|
353
425
|
detect_release_from_heroku
|
354
|
-
rescue =>
|
355
|
-
logger.error "Error detecting release: #{
|
426
|
+
rescue => e
|
427
|
+
logger.error "Error detecting release: #{e.message}"
|
356
428
|
end
|
357
429
|
|
358
430
|
def excluded_exception?(incoming_exception)
|
@@ -417,19 +489,22 @@ module Raven
|
|
417
489
|
end
|
418
490
|
|
419
491
|
def capture_in_current_environment?
|
420
|
-
return true
|
492
|
+
return true if enabled_in_current_env?
|
493
|
+
|
421
494
|
@errors << "Not configured to send/capture in environment '#{current_environment}'"
|
422
495
|
false
|
423
496
|
end
|
424
497
|
|
425
498
|
def capture_allowed_by_callback?(message_or_exc)
|
426
|
-
return true if !should_capture || message_or_exc.nil? || should_capture.call(
|
499
|
+
return true if !should_capture || message_or_exc.nil? || should_capture.call(message_or_exc)
|
500
|
+
|
427
501
|
@errors << "should_capture returned false"
|
428
502
|
false
|
429
503
|
end
|
430
504
|
|
431
505
|
def valid?
|
432
506
|
return true if %w(server host path public_key project_id).all? { |k| public_send(k) }
|
507
|
+
|
433
508
|
if server
|
434
509
|
%w(server host path public_key project_id).map do |key|
|
435
510
|
@errors << "No #{key} specified" unless public_send(key)
|
@@ -442,6 +517,7 @@ module Raven
|
|
442
517
|
|
443
518
|
def sample_allowed?
|
444
519
|
return true if sample_rate == 1.0
|
520
|
+
|
445
521
|
if Random::DEFAULT.rand >= sample_rate
|
446
522
|
@errors << "Excluded by random sample"
|
447
523
|
false
|
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
|
@@ -24,18 +25,22 @@ module Raven
|
|
24
25
|
|
25
26
|
class << self
|
26
27
|
def os_context
|
27
|
-
@os_context ||=
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
33
38
|
end
|
34
39
|
|
35
40
|
def runtime_context
|
36
41
|
@runtime_context ||= {
|
37
|
-
:
|
38
|
-
:
|
42
|
+
name: RbConfig::CONFIG["ruby_install_name"],
|
43
|
+
version: RUBY_DESCRIPTION || Raven.sys_command("ruby -v")
|
39
44
|
}
|
40
45
|
end
|
41
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
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#########################################
|
4
|
+
# This file was copied from Rails 5.2 #
|
5
|
+
#########################################
|
6
|
+
|
7
|
+
#--
|
8
|
+
# Most objects are cloneable, but not all. For example you can't dup methods:
|
9
|
+
#
|
10
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
11
|
+
#
|
12
|
+
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
13
|
+
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
14
|
+
# use an optimistic approach and are ready to catch an exception, say:
|
15
|
+
#
|
16
|
+
# arbitrary_object.dup rescue object
|
17
|
+
#
|
18
|
+
# Rails dups objects in a few critical spots where they are not that arbitrary.
|
19
|
+
# That rescue is very expensive (like 40 times slower than a predicate), and it
|
20
|
+
# is often triggered.
|
21
|
+
#
|
22
|
+
# That's why we hardcode the following cases and check duplicable? instead of
|
23
|
+
# using that rescue idiom.
|
24
|
+
#++
|
25
|
+
class Object
|
26
|
+
# Can you safely dup this object?
|
27
|
+
#
|
28
|
+
# False for method objects;
|
29
|
+
# true otherwise.
|
30
|
+
def duplicable?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class NilClass
|
36
|
+
begin
|
37
|
+
nil.dup
|
38
|
+
rescue TypeError
|
39
|
+
# +nil+ is not duplicable:
|
40
|
+
#
|
41
|
+
# nil.duplicable? # => false
|
42
|
+
# nil.dup # => TypeError: can't dup NilClass
|
43
|
+
def duplicable?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class FalseClass
|
50
|
+
begin
|
51
|
+
false.dup
|
52
|
+
rescue TypeError
|
53
|
+
# +false+ is not duplicable:
|
54
|
+
#
|
55
|
+
# false.duplicable? # => false
|
56
|
+
# false.dup # => TypeError: can't dup FalseClass
|
57
|
+
def duplicable?
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class TrueClass
|
64
|
+
begin
|
65
|
+
true.dup
|
66
|
+
rescue TypeError
|
67
|
+
# +true+ is not duplicable:
|
68
|
+
#
|
69
|
+
# true.duplicable? # => false
|
70
|
+
# true.dup # => TypeError: can't dup TrueClass
|
71
|
+
def duplicable?
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Symbol
|
78
|
+
begin
|
79
|
+
:symbol.dup # Ruby 2.4.x.
|
80
|
+
"symbol_from_string".to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
|
81
|
+
rescue TypeError
|
82
|
+
# Symbols are not duplicable:
|
83
|
+
#
|
84
|
+
# :my_symbol.duplicable? # => false
|
85
|
+
# :my_symbol.dup # => TypeError: can't dup Symbol
|
86
|
+
def duplicable?
|
87
|
+
false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Numeric
|
93
|
+
begin
|
94
|
+
1.dup
|
95
|
+
rescue TypeError
|
96
|
+
# Numbers are not duplicable:
|
97
|
+
#
|
98
|
+
# 3.duplicable? # => false
|
99
|
+
# 3.dup # => TypeError: can't dup Integer
|
100
|
+
def duplicable?
|
101
|
+
false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
require "bigdecimal"
|
107
|
+
class BigDecimal
|
108
|
+
# BigDecimals are duplicable:
|
109
|
+
#
|
110
|
+
# BigDecimal("1.2").duplicable? # => true
|
111
|
+
# BigDecimal("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
|
112
|
+
def duplicable?
|
113
|
+
true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Method
|
118
|
+
# Methods are not duplicable:
|
119
|
+
#
|
120
|
+
# method(:puts).duplicable? # => false
|
121
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
122
|
+
def duplicable?
|
123
|
+
false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class Complex
|
128
|
+
begin
|
129
|
+
Complex(1).dup
|
130
|
+
rescue TypeError
|
131
|
+
# Complexes are not duplicable:
|
132
|
+
#
|
133
|
+
# Complex(1).duplicable? # => false
|
134
|
+
# Complex(1).dup # => TypeError: can't copy Complex
|
135
|
+
def duplicable?
|
136
|
+
false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Rational
|
142
|
+
begin
|
143
|
+
Rational(1).dup
|
144
|
+
rescue TypeError
|
145
|
+
# Rationals are not duplicable:
|
146
|
+
#
|
147
|
+
# Rational(1).duplicable? # => false
|
148
|
+
# Rational(1).dup # => TypeError: can't copy Rational
|
149
|
+
def duplicable?
|
150
|
+
false
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/raven/event.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'socket'
|
3
4
|
require 'securerandom'
|
4
5
|
|
@@ -7,6 +8,7 @@ module Raven
|
|
7
8
|
# See Sentry server default limits at
|
8
9
|
# https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py
|
9
10
|
MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8
|
11
|
+
REQUIRED_OPTION_KEYS = [:configuration, :context, :breadcrumbs].freeze
|
10
12
|
|
11
13
|
SDK = { "name" => "raven-ruby", "version" => Raven::VERSION }.freeze
|
12
14
|
|
@@ -18,7 +20,7 @@ module Raven
|
|
18
20
|
|
19
21
|
attr_reader :level, :timestamp, :time_spent
|
20
22
|
|
21
|
-
def initialize(
|
23
|
+
def initialize(options)
|
22
24
|
# Set some simple default values
|
23
25
|
self.id = SecureRandom.uuid.delete("-")
|
24
26
|
self.timestamp = Time.now.utc
|
@@ -35,11 +37,17 @@ module Raven
|
|
35
37
|
self.runtime = {} # TODO: contexts
|
36
38
|
self.tags = {} # TODO: contexts
|
37
39
|
|
38
|
-
|
40
|
+
unless REQUIRED_OPTION_KEYS.all? { |key| options.key?(key) }
|
41
|
+
raise "you much provide configuration, context, and breadcrumbs when initializing a Raven::Event"
|
42
|
+
end
|
43
|
+
|
44
|
+
self.configuration = options[:configuration]
|
45
|
+
self.context = options[:context]
|
46
|
+
self.breadcrumbs = options[:breadcrumbs]
|
39
47
|
|
40
48
|
# Allow attributes to be set on the event at initialization
|
41
49
|
yield self if block_given?
|
42
|
-
|
50
|
+
options.each_pair { |key, val| public_send("#{key}=", val) unless val.nil? }
|
43
51
|
|
44
52
|
set_core_attributes_from_configuration
|
45
53
|
set_core_attributes_from_context
|
@@ -55,8 +63,7 @@ module Raven
|
|
55
63
|
end
|
56
64
|
options = Raven::Utils::DeepMergeHash.deep_merge(exception_context, options)
|
57
65
|
|
58
|
-
|
59
|
-
return unless configuration.exception_class_allowed?(exc)
|
66
|
+
return unless options[:configuration].exception_class_allowed?(exc)
|
60
67
|
|
61
68
|
new(options) do |evt|
|
62
69
|
evt.add_exception_interface(exc)
|
@@ -76,11 +83,21 @@ module Raven
|
|
76
83
|
end
|
77
84
|
|
78
85
|
def message
|
79
|
-
@interfaces[:logentry]
|
86
|
+
@interfaces[:logentry]&.unformatted_message
|
80
87
|
end
|
81
88
|
|
82
89
|
def message=(args)
|
83
|
-
|
90
|
+
if args.is_a?(Array)
|
91
|
+
message, params = args[0], args[0..-1]
|
92
|
+
else
|
93
|
+
message = args
|
94
|
+
end
|
95
|
+
|
96
|
+
unless message.is_a?(String)
|
97
|
+
configuration.logger.debug("You're passing a non-string message")
|
98
|
+
message = message.to_s
|
99
|
+
end
|
100
|
+
|
84
101
|
interface(:message) do |int|
|
85
102
|
int.message = message.byteslice(0...MAX_MESSAGE_SIZE_IN_BYTES) # Messages limited to 10kb
|
86
103
|
int.params = params
|
@@ -96,12 +113,13 @@ module Raven
|
|
96
113
|
end
|
97
114
|
|
98
115
|
def level=(new_level) # needed to meet the Sentry spec
|
99
|
-
@level = new_level == "warn"
|
116
|
+
@level = new_level.to_s == "warn" ? :warning : new_level
|
100
117
|
end
|
101
118
|
|
102
119
|
def interface(name, value = nil, &block)
|
103
120
|
int = Interface.registered[name]
|
104
121
|
raise(Error, "Unknown interface: #{name}") unless int
|
122
|
+
|
105
123
|
@interfaces[int.sentry_alias] = int.new(value, &block) if value || block
|
106
124
|
@interfaces[int.sentry_alias]
|
107
125
|
end
|
@@ -157,7 +175,7 @@ module Raven
|
|
157
175
|
end
|
158
176
|
|
159
177
|
def stacktrace_interface_from(backtrace)
|
160
|
-
Backtrace.parse(backtrace).lines.reverse.each_with_object([]) do |line, memo|
|
178
|
+
Backtrace.parse(backtrace, { configuration: configuration }).lines.reverse.each_with_object([]) do |line, memo|
|
161
179
|
frame = StacktraceInterface::Frame.new
|
162
180
|
frame.abs_path = line.file if line.file
|
163
181
|
frame.function = line.method if line.method
|
@@ -184,12 +202,6 @@ module Raven
|
|
184
202
|
|
185
203
|
private
|
186
204
|
|
187
|
-
def copy_initial_state
|
188
|
-
self.configuration = Raven.configuration
|
189
|
-
self.breadcrumbs = Raven.breadcrumbs
|
190
|
-
self.context = Raven.context
|
191
|
-
end
|
192
|
-
|
193
205
|
def set_core_attributes_from_configuration
|
194
206
|
self.server_name ||= configuration.server_name
|
195
207
|
self.release ||= configuration.release
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DeprecationHelper
|
2
|
+
def self.deprecate_dasherized_filename(correct_filename)
|
3
|
+
warn "[Deprecation Warning] Dasherized filename \"#{correct_filename.gsub('_', '-')}\" is deprecated and will be removed in 4.0; use \"#{correct_filename}\" instead" # rubocop:disable Style/LineLength
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.deprecate_old_breadcrumbs_configuration(logger)
|
7
|
+
deprecated_usage =
|
8
|
+
if logger == :sentry_logger
|
9
|
+
"require \"raven/breadcrumbs/logger\""
|
10
|
+
else
|
11
|
+
"Raven.configuration.rails_activesupport_breadcrumbs = true"
|
12
|
+
end
|
13
|
+
recommended_usage = "Raven.configuration.breadcrumbs_logger = :#{logger}"
|
14
|
+
|
15
|
+
warn "[Deprecation Warning] The way you enable breadcrumbs logger (#{deprecated_usage}) is deprecated and will be removed in 4.0; use '#{recommended_usage}' instead" # rubocop:disable Style/LineLength
|
16
|
+
end
|
17
|
+
end
|
data/lib/raven/instance.rb
CHANGED
@@ -50,7 +50,9 @@ module Raven
|
|
50
50
|
|
51
51
|
# Tell the log that the client is good to go
|
52
52
|
def report_status
|
53
|
+
return unless configuration.enabled_in_current_env?
|
53
54
|
return if configuration.silence_ready
|
55
|
+
|
54
56
|
if configuration.capture_allowed?
|
55
57
|
logger.info "Raven #{VERSION} ready to catch errors"
|
56
58
|
else
|
@@ -75,7 +77,7 @@ module Raven
|
|
75
77
|
# Send an event to the configured Sentry server
|
76
78
|
#
|
77
79
|
# @example
|
78
|
-
# evt = Raven::Event.new(:message => "An
|
80
|
+
# evt = Raven::Event.new(:message => "An errore)
|
79
81
|
# Raven.send_event(evt)
|
80
82
|
def send_event(event, hint = nil)
|
81
83
|
client.send_event(event, hint)
|
@@ -109,17 +111,20 @@ module Raven
|
|
109
111
|
end
|
110
112
|
|
111
113
|
message_or_exc = obj.is_a?(String) ? "message" : "exception"
|
114
|
+
options = options.deep_dup
|
112
115
|
options[:configuration] = configuration
|
113
116
|
options[:context] = context
|
114
|
-
|
117
|
+
options[:breadcrumbs] = breadcrumbs
|
118
|
+
|
119
|
+
if evt = Event.send("from_" + message_or_exc, obj, options)
|
115
120
|
yield evt if block_given?
|
116
121
|
if configuration.async?
|
117
122
|
begin
|
118
123
|
# We have to convert to a JSON-like hash, because background job
|
119
124
|
# processors (esp ActiveJob) may not like weird types in the event hash
|
120
125
|
configuration.async.call(evt.to_json_compatible)
|
121
|
-
rescue =>
|
122
|
-
logger.error("async event sending failed: #{
|
126
|
+
rescue => e
|
127
|
+
logger.error("async event sending failed: #{e.message}")
|
123
128
|
send_event(evt, make_hint(obj))
|
124
129
|
end
|
125
130
|
else
|