sentry-raven 2.12.2 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.craft.yml +15 -0
  3. data/.github/workflows/test.yml +77 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +44 -9
  6. data/.scripts/bump-version.sh +9 -0
  7. data/Gemfile +17 -25
  8. data/README.md +4 -3
  9. data/changelog.md +37 -0
  10. data/lib/raven/backtrace.rb +7 -5
  11. data/lib/raven/base.rb +5 -3
  12. data/lib/raven/breadcrumbs.rb +1 -1
  13. data/lib/raven/breadcrumbs/activesupport.rb +10 -10
  14. data/lib/raven/breadcrumbs/logger.rb +3 -3
  15. data/lib/raven/cli.rb +2 -2
  16. data/lib/raven/client.rb +12 -6
  17. data/lib/raven/configuration.rb +15 -5
  18. data/lib/raven/event.rb +5 -6
  19. data/lib/raven/instance.rb +4 -3
  20. data/lib/raven/integrations/delayed_job.rb +14 -15
  21. data/lib/raven/integrations/rack-timeout.rb +2 -3
  22. data/lib/raven/integrations/rack.rb +4 -3
  23. data/lib/raven/integrations/rails.rb +1 -0
  24. data/lib/raven/integrations/rails/active_job.rb +10 -7
  25. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  26. data/lib/raven/interface.rb +2 -2
  27. data/lib/raven/interfaces/stack_trace.rb +1 -1
  28. data/lib/raven/linecache.rb +5 -2
  29. data/lib/raven/logger.rb +3 -2
  30. data/lib/raven/processor/cookies.rb +16 -6
  31. data/lib/raven/processor/post_data.rb +2 -0
  32. data/lib/raven/processor/removecircularreferences.rb +1 -0
  33. data/lib/raven/processor/sanitizedata.rb +65 -17
  34. data/lib/raven/processor/utf8conversion.rb +2 -0
  35. data/lib/raven/transports.rb +4 -0
  36. data/lib/raven/transports/http.rb +5 -5
  37. data/lib/raven/utils/exception_cause_chain.rb +1 -0
  38. data/lib/raven/utils/real_ip.rb +1 -1
  39. data/lib/raven/version.rb +2 -2
  40. data/sentry-raven.gemspec +2 -2
  41. metadata +7 -12
  42. data/.travis.yml +0 -47
@@ -4,13 +4,13 @@ module Raven
4
4
  module BreadcrumbLogger
5
5
  LEVELS = {
6
6
  ::Logger::DEBUG => 'debug',
7
- ::Logger::INFO => 'info',
8
- ::Logger::WARN => 'warn',
7
+ ::Logger::INFO => 'info',
8
+ ::Logger::WARN => 'warn',
9
9
  ::Logger::ERROR => 'error',
10
10
  ::Logger::FATAL => 'fatal'
11
11
  }.freeze
12
12
 
13
- EXC_FORMAT = /^([a-zA-Z0-9]+)\:\s(.*)$/
13
+ EXC_FORMAT = /^([a-zA-Z0-9]+)\:\s(.*)$/.freeze
14
14
 
15
15
  def self.parse_exception(message)
16
16
  lines = message.split(/\n\s*/)
@@ -29,8 +29,8 @@ module Raven
29
29
 
30
30
  begin
31
31
  1 / 0
32
- rescue ZeroDivisionError => exception
33
- evt = instance.capture_exception(exception)
32
+ rescue ZeroDivisionError => e
33
+ evt = instance.capture_exception(e)
34
34
  end
35
35
 
36
36
  if evt && !(evt.is_a? Thread)
@@ -1,14 +1,17 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'base64'
3
4
  require 'json'
4
5
  require 'zlib'
5
6
 
7
+ require "raven/transports"
8
+
6
9
  module Raven
7
10
  # Encodes events and sends them to the Sentry server.
8
11
  class Client
9
- PROTOCOL_VERSION = '5'.freeze
10
- USER_AGENT = "raven-ruby/#{Raven::VERSION}".freeze
11
- CONTENT_TYPE = 'application/json'.freeze
12
+ PROTOCOL_VERSION = '5'
13
+ USER_AGENT = "raven-ruby/#{Raven::VERSION}"
14
+ CONTENT_TYPE = 'application/json'
12
15
 
13
16
  attr_accessor :configuration
14
17
 
@@ -35,7 +38,8 @@ module Raven
35
38
  return
36
39
  end
37
40
 
38
- configuration.logger.info "Sending event #{event[:event_id]} to Sentry"
41
+ event_id = event[:event_id] || event['event_id']
42
+ configuration.logger.info "Sending event #{event_id} to Sentry"
39
43
 
40
44
  content_type, encoded_data = encode(event)
41
45
 
@@ -92,7 +96,7 @@ module Raven
92
96
  end
93
97
 
94
98
  def get_log_message(event)
95
- (event && event[:message]) || get_message_from_exception(event) || '<no message value>'
99
+ (event && event[:message]) || (event && event['message']) || get_message_from_exception(event) || '<no message value>'
96
100
  end
97
101
 
98
102
  def generate_auth_header
@@ -119,7 +123,9 @@ module Raven
119
123
  configuration.logger.warn "Not sending event due to previous failure(s)."
120
124
  end
121
125
  configuration.logger.warn("Failed to submit event: #{get_log_message(event)}")
122
- configuration.transport_failure_callback.call(event) if configuration.transport_failure_callback
126
+
127
+ # configuration.transport_failure_callback can be false & nil
128
+ configuration.transport_failure_callback.call(event) if configuration.transport_failure_callback # rubocop:disable Style/SafeNavigation
123
129
  end
124
130
  end
125
131
 
@@ -236,6 +236,7 @@ module Raven
236
236
 
237
237
  def server=(value)
238
238
  return if value.nil?
239
+
239
240
  uri = URI.parse(value)
240
241
  uri_path = uri.path.split('/')
241
242
 
@@ -253,13 +254,14 @@ module Raven
253
254
 
254
255
  # For anyone who wants to read the base server string
255
256
  @server = "#{scheme}://#{host}"
256
- @server << ":#{port}" unless port == { 'http' => 80, 'https' => 443 }[scheme]
257
- @server << path
257
+ @server += ":#{port}" unless port == { 'http' => 80, 'https' => 443 }[scheme]
258
+ @server += path
258
259
  end
259
260
  alias dsn= server=
260
261
 
261
262
  def encoding=(encoding)
262
263
  raise(Error, 'Unsupported encoding') unless %w(gzip json).include? encoding
264
+
263
265
  @encoding = encoding
264
266
  end
265
267
 
@@ -267,6 +269,7 @@ module Raven
267
269
  unless value == false || value.respond_to?(:call)
268
270
  raise(ArgumentError, "async must be callable (or false to disable)")
269
271
  end
272
+
270
273
  @async = value
271
274
  end
272
275
 
@@ -274,6 +277,7 @@ module Raven
274
277
  unless value == false || value.respond_to?(:call)
275
278
  raise(ArgumentError, "transport_failure_callback must be callable (or false to disable)")
276
279
  end
280
+
277
281
  @transport_failure_callback = value
278
282
  end
279
283
 
@@ -281,6 +285,7 @@ module Raven
281
285
  unless value == false || value.respond_to?(:call)
282
286
  raise ArgumentError, "should_capture must be callable (or false to disable)"
283
287
  end
288
+
284
289
  @should_capture = value
285
290
  end
286
291
 
@@ -288,6 +293,7 @@ module Raven
288
293
  unless value == false || value.respond_to?(:call)
289
294
  raise ArgumentError, "before_send must be callable (or false to disable)"
290
295
  end
296
+
291
297
  @before_send = value
292
298
  end
293
299
 
@@ -351,8 +357,8 @@ module Raven
351
357
  detect_release_from_git ||
352
358
  detect_release_from_capistrano ||
353
359
  detect_release_from_heroku
354
- rescue => ex
355
- logger.error "Error detecting release: #{ex.message}"
360
+ rescue => e
361
+ logger.error "Error detecting release: #{e.message}"
356
362
  end
357
363
 
358
364
  def excluded_exception?(incoming_exception)
@@ -418,18 +424,21 @@ module Raven
418
424
 
419
425
  def capture_in_current_environment?
420
426
  return true unless environments.any? && !environments.include?(current_environment)
427
+
421
428
  @errors << "Not configured to send/capture in environment '#{current_environment}'"
422
429
  false
423
430
  end
424
431
 
425
432
  def capture_allowed_by_callback?(message_or_exc)
426
- return true if !should_capture || message_or_exc.nil? || should_capture.call(*[message_or_exc])
433
+ return true if !should_capture || message_or_exc.nil? || should_capture.call(message_or_exc)
434
+
427
435
  @errors << "should_capture returned false"
428
436
  false
429
437
  end
430
438
 
431
439
  def valid?
432
440
  return true if %w(server host path public_key project_id).all? { |k| public_send(k) }
441
+
433
442
  if server
434
443
  %w(server host path public_key project_id).map do |key|
435
444
  @errors << "No #{key} specified" unless public_send(key)
@@ -442,6 +451,7 @@ module Raven
442
451
 
443
452
  def sample_allowed?
444
453
  return true if sample_rate == 1.0
454
+
445
455
  if Random::DEFAULT.rand >= sample_rate
446
456
  @errors << "Excluded by random sample"
447
457
  false
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'socket'
3
4
  require 'securerandom'
4
5
 
@@ -76,7 +77,7 @@ module Raven
76
77
  end
77
78
 
78
79
  def message
79
- @interfaces[:logentry] && @interfaces[:logentry].unformatted_message
80
+ @interfaces[:logentry]&.unformatted_message
80
81
  end
81
82
 
82
83
  def message=(args)
@@ -96,12 +97,13 @@ module Raven
96
97
  end
97
98
 
98
99
  def level=(new_level) # needed to meet the Sentry spec
99
- @level = new_level == "warn" || new_level == :warn ? :warning : new_level
100
+ @level = new_level.to_s == "warn" ? :warning : new_level
100
101
  end
101
102
 
102
103
  def interface(name, value = nil, &block)
103
104
  int = Interface.registered[name]
104
105
  raise(Error, "Unknown interface: #{name}") unless int
106
+
105
107
  @interfaces[int.sentry_alias] = int.new(value, &block) if value || block
106
108
  @interfaces[int.sentry_alias]
107
109
  end
@@ -228,10 +230,7 @@ module Raven
228
230
  end
229
231
 
230
232
  def async_json_processors
231
- [
232
- Raven::Processor::RemoveCircularReferences,
233
- Raven::Processor::UTF8Conversion
234
- ].map { |v| v.new(self) }
233
+ configuration.processors.map { |v| v.new(self) }
235
234
  end
236
235
 
237
236
  def list_gem_specs
@@ -51,6 +51,7 @@ module Raven
51
51
  # Tell the log that the client is good to go
52
52
  def report_status
53
53
  return if configuration.silence_ready
54
+
54
55
  if configuration.capture_allowed?
55
56
  logger.info "Raven #{VERSION} ready to catch errors"
56
57
  else
@@ -111,15 +112,15 @@ module Raven
111
112
  message_or_exc = obj.is_a?(String) ? "message" : "exception"
112
113
  options[:configuration] = configuration
113
114
  options[:context] = context
114
- if (evt = Event.send("from_" + message_or_exc, obj, options))
115
+ if evt = Event.send("from_" + message_or_exc, obj, options)
115
116
  yield evt if block_given?
116
117
  if configuration.async?
117
118
  begin
118
119
  # We have to convert to a JSON-like hash, because background job
119
120
  # processors (esp ActiveJob) may not like weird types in the event hash
120
121
  configuration.async.call(evt.to_json_compatible)
121
- rescue => ex
122
- logger.error("async event sending failed: #{ex.message}")
122
+ rescue => e
123
+ logger.error("async event sending failed: #{e.message}")
123
124
  send_event(evt, make_hint(obj))
124
125
  end
125
126
  else
@@ -8,19 +8,18 @@ module Delayed
8
8
  begin
9
9
  # Forward the call to the next callback in the callback chain
10
10
  block.call(job, *args)
11
-
12
- rescue Exception => exception
11
+ rescue Exception => e
13
12
  # Log error to Sentry
14
13
  extra = {
15
14
  :delayed_job => {
16
- :id => job.id,
17
- :priority => job.priority,
18
- :attempts => job.attempts,
19
- :run_at => job.run_at,
20
- :locked_at => job.locked_at,
21
- :locked_by => job.locked_by,
22
- :queue => job.queue,
23
- :created_at => job.created_at
15
+ :id => job.id.to_s,
16
+ :priority => job.priority,
17
+ :attempts => job.attempts,
18
+ :run_at => job.run_at,
19
+ :locked_at => job.locked_at,
20
+ :locked_by => job.locked_by,
21
+ :queue => job.queue,
22
+ :created_at => job.created_at
24
23
  }
25
24
  }
26
25
  # last_error can be nil
@@ -32,16 +31,16 @@ module Delayed
32
31
  if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data')
33
32
  extra[:active_job] = job.payload_object.job_data
34
33
  end
35
- ::Raven.capture_exception(exception,
36
- :logger => 'delayed_job',
37
- :tags => {
34
+ ::Raven.capture_exception(e,
35
+ :logger => 'delayed_job',
36
+ :tags => {
38
37
  :delayed_job_queue => job.queue,
39
- :delayed_job_id => job.id
38
+ :delayed_job_id => job.id.to_s
40
39
  },
41
40
  :extra => extra)
42
41
 
43
42
  # Make sure we propagate the failure!
44
- raise exception
43
+ raise e
45
44
  ensure
46
45
  ::Raven::Context.clear!
47
46
  ::Raven::BreadcrumbBuffer.clear!
@@ -14,6 +14,5 @@ module RackTimeoutExtensions
14
14
  end
15
15
  end
16
16
 
17
- # Include is private in Ruby 1.9
18
- Rack::Timeout::Error.__send__(:include, RackTimeoutExtensions)
19
- Rack::Timeout::RequestTimeoutException.__send__(:include, RackTimeoutExtensions)
17
+ Rack::Timeout::Error.include(RackTimeoutExtensions)
18
+ Rack::Timeout::RequestTimeoutException.include(RackTimeoutExtensions)
@@ -92,8 +92,8 @@ module Raven
92
92
  request.body.rewind
93
93
  data
94
94
  end
95
- rescue IOError => ex
96
- ex.message
95
+ rescue IOError => e
96
+ e.message
97
97
  end
98
98
 
99
99
  def format_headers_for_sentry(env_hash)
@@ -112,8 +112,9 @@ module Raven
112
112
  next if key == 'HTTP_COOKIE' # Cookies don't go here, they go somewhere else
113
113
 
114
114
  next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
115
+
115
116
  # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
116
- key = key.gsub("HTTP_", "")
117
+ key = key.sub(/^HTTP_/, "")
117
118
  key = key.split('_').map(&:capitalize).join('-')
118
119
  memo[key] = value
119
120
  rescue StandardError => e
@@ -5,6 +5,7 @@ module Raven
5
5
  require 'raven/integrations/rails/overrides/streaming_reporter'
6
6
  require 'raven/integrations/rails/controller_methods'
7
7
  require 'raven/integrations/rails/controller_transaction'
8
+ require 'raven/integrations/rack'
8
9
 
9
10
  initializer "raven.use_rack_middleware" do |app|
10
11
  app.config.middleware.insert 0, Raven::Rack
@@ -9,19 +9,22 @@ module Raven
9
9
  def self.included(base)
10
10
  base.class_eval do
11
11
  around_perform do |job, block|
12
- capture_and_reraise_with_sentry(job, block)
12
+ if already_supported_by_specific_integration?(job)
13
+ block.call
14
+ else
15
+ capture_and_reraise_with_sentry(job, block)
16
+ end
13
17
  end
14
18
  end
15
19
  end
16
20
 
17
21
  def capture_and_reraise_with_sentry(job, block)
18
22
  block.call
19
- rescue Exception => exception # rubocop:disable Lint/RescueException
20
- return if rescue_with_handler(exception)
21
- unless already_supported_by_specific_integration?(job)
22
- Raven.capture_exception(exception, :extra => raven_context(job))
23
- end
24
- raise exception
23
+ rescue Exception => e # rubocop:disable Lint/RescueException
24
+ return if rescue_with_handler(e)
25
+
26
+ Raven.capture_exception(e, :extra => raven_context(job))
27
+ raise e
25
28
  ensure
26
29
  Context.clear!
27
30
  BreadcrumbBuffer.clear!
@@ -6,7 +6,7 @@ module Raven
6
6
  begin
7
7
  env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
8
8
  Raven::Rack.capture_exception(exception, env)
9
- rescue # rubocop:disable Lint/HandleExceptions
9
+ rescue
10
10
  end
11
11
  super
12
12
  end
@@ -21,7 +21,7 @@ module Raven
21
21
  begin
22
22
  env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request
23
23
  Raven::Rack.capture_exception(exception, env)
24
- rescue # rubocop:disable Lint/HandleExceptions
24
+ rescue
25
25
  end
26
26
  render_exception_without_raven(env_or_request, exception)
27
27
  end
@@ -1,9 +1,9 @@
1
1
  module Raven
2
2
  class Interface
3
3
  def initialize(attributes = nil)
4
- attributes.each do |attr, value|
4
+ attributes&.each do |attr, value|
5
5
  public_send "#{attr}=", value
6
- end if attributes
6
+ end
7
7
 
8
8
  yield self if block_given?
9
9
  end
@@ -58,7 +58,7 @@ module Raven
58
58
  end
59
59
 
60
60
  def project_root
61
- @project_root ||= Raven.configuration.project_root && Raven.configuration.project_root.to_s
61
+ @project_root ||= Raven.configuration.project_root&.to_s
62
62
  end
63
63
 
64
64
  def longest_load_path
@@ -10,6 +10,7 @@ module Raven
10
10
  # line should be the line requested by lineno. See specs for more information.
11
11
  def get_file_context(filename, lineno, context)
12
12
  return nil, nil, nil unless valid_path?(filename)
13
+
13
14
  lines = Array.new(2 * context + 1) do |i|
14
15
  getline(filename, lineno - context + i)
15
16
  end
@@ -26,15 +27,17 @@ module Raven
26
27
  def getlines(path)
27
28
  @cache[path] ||= begin
28
29
  IO.readlines(path)
29
- rescue
30
- nil
30
+ rescue
31
+ nil
31
32
  end
32
33
  end
33
34
 
34
35
  def getline(path, n)
35
36
  return nil if n < 1
37
+
36
38
  lines = getlines(path)
37
39
  return nil if lines.nil?
40
+
38
41
  lines[n - 1]
39
42
  end
40
43
  end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'logger'
3
4
 
4
5
  module Raven
5
6
  class Logger < ::Logger
6
- LOG_PREFIX = "** [Raven] ".freeze
7
- PROGNAME = "sentry".freeze
7
+ LOG_PREFIX = "** [Raven] "
8
+ PROGNAME = "sentry"
8
9
 
9
10
  def initialize(*)
10
11
  super