sentry-raven 2.13.0 → 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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.craft.yml +19 -0
  3. data/.scripts/bump-version.rb +5 -0
  4. data/{changelog.md → CHANGELOG.md} +182 -1
  5. data/Gemfile +24 -25
  6. data/Makefile +3 -0
  7. data/README.md +44 -16
  8. data/lib/raven/backtrace.rb +9 -5
  9. data/lib/raven/base.rb +7 -2
  10. data/lib/raven/breadcrumbs/{activesupport.rb → active_support_logger.rb} +9 -3
  11. data/lib/raven/breadcrumbs/logger.rb +2 -92
  12. data/lib/raven/breadcrumbs/sentry_logger.rb +73 -0
  13. data/lib/raven/breadcrumbs.rb +1 -1
  14. data/lib/raven/cli.rb +10 -21
  15. data/lib/raven/client.rb +9 -4
  16. data/lib/raven/configuration.rb +95 -10
  17. data/lib/raven/context.rb +13 -8
  18. data/lib/raven/core_ext/object/deep_dup.rb +57 -0
  19. data/lib/raven/core_ext/object/duplicable.rb +153 -0
  20. data/lib/raven/event.rb +31 -15
  21. data/lib/raven/helpers/deprecation_helper.rb +17 -0
  22. data/lib/raven/instance.rb +21 -5
  23. data/lib/raven/integrations/delayed_job.rb +15 -15
  24. data/lib/raven/integrations/rack-timeout.rb +7 -4
  25. data/lib/raven/integrations/rack.rb +9 -7
  26. data/lib/raven/integrations/rails/active_job.rb +6 -4
  27. data/lib/raven/integrations/rails/backtrace_cleaner.rb +29 -0
  28. data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
  29. data/lib/raven/integrations/rails.rb +13 -3
  30. data/lib/raven/integrations/sidekiq/cleanup_middleware.rb +13 -0
  31. data/lib/raven/integrations/sidekiq/error_handler.rb +38 -0
  32. data/lib/raven/integrations/sidekiq.rb +4 -78
  33. data/lib/raven/interface.rb +2 -2
  34. data/lib/raven/interfaces/stack_trace.rb +1 -1
  35. data/lib/raven/linecache.rb +5 -2
  36. data/lib/raven/logger.rb +3 -2
  37. data/lib/raven/processor/cookies.rb +16 -6
  38. data/lib/raven/processor/post_data.rb +2 -0
  39. data/lib/raven/processor/removecircularreferences.rb +3 -1
  40. data/lib/raven/processor/sanitizedata.rb +65 -17
  41. data/lib/raven/processor/utf8conversion.rb +2 -0
  42. data/lib/raven/transports/http.rb +7 -8
  43. data/lib/raven/transports.rb +4 -0
  44. data/lib/raven/utils/context_filter.rb +42 -0
  45. data/lib/raven/utils/exception_cause_chain.rb +1 -0
  46. data/lib/raven/utils/real_ip.rb +1 -1
  47. data/lib/raven/utils/request_id.rb +16 -0
  48. data/lib/raven/version.rb +2 -2
  49. data/lib/sentry-raven-without-integrations.rb +6 -1
  50. data/lib/sentry_raven_without_integrations.rb +1 -0
  51. data/sentry-raven.gemspec +9 -2
  52. metadata +23 -17
  53. data/.gitignore +0 -13
  54. data/.gitmodules +0 -0
  55. data/.rspec +0 -1
  56. data/.rubocop.yml +0 -74
  57. data/.travis.yml +0 -47
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(init = {})
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
- copy_initial_state
40
+ unless REQUIRED_OPTION_KEYS.all? { |key| options.key?(key) }
41
+ raise "you must 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
- init.each_pair { |key, val| public_send("#{key}=", val) unless val.nil? }
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
- configuration = options[:configuration] || Raven.configuration
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] && @interfaces[:logentry].unformatted_message
86
+ @interfaces[:logentry]&.unformatted_message
80
87
  end
81
88
 
82
89
  def message=(args)
83
- message, params = *args
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" || new_level == :warn ? :warning : new_level
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
@@ -214,6 +226,10 @@ module Raven
214
226
  int.from_rack(context.rack_env)
215
227
  end
216
228
  context.user[:ip_address] = calculate_real_ip_from_rack
229
+
230
+ if request_id = Utils::RequestId.read_from(context.rack_env)
231
+ context.tags[:request_id] = request_id
232
+ end
217
233
  end
218
234
 
219
235
  # When behind a proxy (or if the user is using a proxy), we can't use
@@ -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
@@ -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 error")
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
- if (evt = Event.send("from_" + message_or_exc, obj, options))
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 => ex
122
- logger.error("async event sending failed: #{ex.message}")
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
@@ -171,7 +176,18 @@ module Raven
171
176
  # @example
172
177
  # Raven.user_context('id' => 1, 'email' => 'foo@example.com')
173
178
  def user_context(options = nil)
174
- context.user = options || {}
179
+ original_user_context = context.user
180
+
181
+ if options
182
+ context.user.merge!(options)
183
+ else
184
+ context.user = {}
185
+ end
186
+
187
+ yield if block_given?
188
+ context.user
189
+ ensure
190
+ context.user = original_user_context if block_given?
175
191
  end
176
192
 
177
193
  # Bind tags context. Merges with existing context (if any).
@@ -1,4 +1,5 @@
1
1
  require 'delayed_job'
2
+ require 'raven/utils/context_filter'
2
3
 
3
4
  module Delayed
4
5
  module Plugins
@@ -8,19 +9,18 @@ module Delayed
8
9
  begin
9
10
  # Forward the call to the next callback in the callback chain
10
11
  block.call(job, *args)
11
-
12
- rescue Exception => exception
12
+ rescue Exception => e
13
13
  # Log error to Sentry
14
14
  extra = {
15
15
  :delayed_job => {
16
- :id => job.id.to_s,
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
16
+ :id => job.id.to_s,
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
24
24
  }
25
25
  }
26
26
  # last_error can be nil
@@ -30,18 +30,18 @@ module Delayed
30
30
  extra[:handler] = job.handler[0...1000] if job.handler
31
31
 
32
32
  if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data')
33
- extra[:active_job] = job.payload_object.job_data
33
+ extra[:active_job] = ::Raven::Utils::ContextFilter.filter_context(job.payload_object.job_data)
34
34
  end
35
- ::Raven.capture_exception(exception,
36
- :logger => 'delayed_job',
37
- :tags => {
35
+ ::Raven.capture_exception(e,
36
+ :logger => 'delayed_job',
37
+ :tags => {
38
38
  :delayed_job_queue => job.queue,
39
39
  :delayed_job_id => job.id.to_s
40
40
  },
41
41
  :extra => extra)
42
42
 
43
43
  # Make sure we propagate the failure!
44
- raise exception
44
+ raise e
45
45
  ensure
46
46
  ::Raven::Context.clear!
47
47
  ::Raven::BreadcrumbBuffer.clear!
@@ -10,10 +10,13 @@ module RackTimeoutExtensions
10
10
  # Only rack-timeout 0.3.0+ provides the request environment, but we can't
11
11
  # gate this based on a gem version constant because rack-timeout does
12
12
  # not provide one.
13
- { :fingerprint => ["{{ default }}", env["REQUEST_URI"]] } if defined?(env)
13
+ if defined?(env)
14
+ { :fingerprint => ["{{ default }}", env["REQUEST_URI"]] }
15
+ else
16
+ {}
17
+ end
14
18
  end
15
19
  end
16
20
 
17
- # Include is private in Ruby 1.9
18
- Rack::Timeout::Error.__send__(:include, RackTimeoutExtensions)
19
- Rack::Timeout::RequestTimeoutException.__send__(:include, RackTimeoutExtensions)
21
+ Rack::Timeout::Error.include(RackTimeoutExtensions)
22
+ Rack::Timeout::RequestTimeoutException.include(RackTimeoutExtensions)
@@ -92,15 +92,15 @@ 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)
100
100
  env_hash.each_with_object({}) do |(key, value), memo|
101
101
  begin
102
102
  key = key.to_s # rack env can contain symbols
103
- value = value.to_s
103
+ next memo['X-Request-Id'] ||= Utils::RequestId.read_from(env_hash) if Utils::RequestId::REQUEST_ID_HEADERS.include?(key)
104
104
  next unless key.upcase == key # Non-upper case stuff isn't either
105
105
 
106
106
  # Rack adds in an incorrect HTTP_VERSION key, which causes downstream
@@ -110,12 +110,12 @@ module Raven
110
110
  # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29
111
111
  next if key == 'HTTP_VERSION' && value == env_hash['SERVER_PROTOCOL']
112
112
  next if key == 'HTTP_COOKIE' # Cookies don't go here, they go somewhere else
113
-
114
113
  next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key)
114
+
115
115
  # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever
116
- key = key.gsub("HTTP_", "")
116
+ key = key.sub(/^HTTP_/, "")
117
117
  key = key.split('_').map(&:capitalize).join('-')
118
- memo[key] = value
118
+ memo[key] = value.to_s
119
119
  rescue StandardError => e
120
120
  # Rails adds objects to the Rack env that can sometimes raise exceptions
121
121
  # when `to_s` is called.
@@ -127,8 +127,10 @@ module Raven
127
127
  end
128
128
 
129
129
  def format_env_for_sentry(env_hash)
130
+ return env_hash if Raven.configuration.rack_env_whitelist.empty?
131
+
130
132
  env_hash.select do |k, _v|
131
- %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s
133
+ Raven.configuration.rack_env_whitelist.include? k.to_s
132
134
  end
133
135
  end
134
136
  end
@@ -20,10 +20,12 @@ module Raven
20
20
 
21
21
  def capture_and_reraise_with_sentry(job, block)
22
22
  block.call
23
- rescue Exception => exception # rubocop:disable Lint/RescueException
24
- return if rescue_with_handler(exception)
25
- Raven.capture_exception(exception, :extra => raven_context(job))
26
- raise exception
23
+ rescue Exception => e # rubocop:disable Lint/RescueException
24
+ rescue_handler_result = rescue_with_handler(e)
25
+ return rescue_handler_result if rescue_handler_result
26
+
27
+ Raven.capture_exception(e, :extra => raven_context(job))
28
+ raise e
27
29
  ensure
28
30
  Context.clear!
29
31
  BreadcrumbBuffer.clear!
@@ -0,0 +1,29 @@
1
+ require "active_support/backtrace_cleaner"
2
+ require "active_support/core_ext/string/access"
3
+
4
+ module Raven
5
+ class Rails
6
+ class BacktraceCleaner < ActiveSupport::BacktraceCleaner
7
+ APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/.freeze
8
+ RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/.freeze
9
+
10
+ def initialize
11
+ super
12
+ # we don't want any default silencers because they're too aggressive
13
+ remove_silencers!
14
+
15
+ @root = "#{Raven.configuration.project_root}/"
16
+ add_filter do |line|
17
+ line.start_with?(@root) ? line.from(@root.size) : line
18
+ end
19
+ add_filter do |line|
20
+ if line =~ RENDER_TEMPLATE_PATTERN
21
+ line.sub(RENDER_TEMPLATE_PATTERN, "")
22
+ else
23
+ line
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -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
@@ -5,6 +5,8 @@ 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/rails/backtrace_cleaner'
9
+ require 'raven/integrations/rack'
8
10
 
9
11
  initializer "raven.use_rack_middleware" do |app|
10
12
  app.config.middleware.insert 0, Raven::Rack
@@ -36,12 +38,20 @@ module Raven
36
38
 
37
39
  config.before_initialize do
38
40
  Raven.configuration.logger = ::Rails.logger
41
+
42
+ backtrace_cleaner = Raven::Rails::BacktraceCleaner.new
43
+
44
+ Raven.configuration.backtrace_cleanup_callback = lambda do |backtrace|
45
+ backtrace_cleaner.clean(backtrace)
46
+ end
39
47
  end
40
48
 
41
49
  config.after_initialize do
42
- if Raven.configuration.rails_activesupport_breadcrumbs
43
- require 'raven/breadcrumbs/activesupport'
44
- Raven::ActiveSupportBreadcrumbs.inject
50
+ if Raven.configuration.breadcrumbs_logger.include?(:active_support_logger) ||
51
+ Raven.configuration.rails_activesupport_breadcrumbs
52
+
53
+ require 'raven/breadcrumbs/active_support_logger'
54
+ Raven::Breadcrumbs::ActiveSupportLogger.inject
45
55
  end
46
56
 
47
57
  if Raven.configuration.rails_report_rescued_exceptions
@@ -0,0 +1,13 @@
1
+ module Raven
2
+ module Sidekiq
3
+ class CleanupMiddleware
4
+ def call(_worker, job, queue)
5
+ Raven.context.transaction.push "Sidekiq/#{job['class']}"
6
+ Raven.extra_context(:sidekiq => job.merge("queue" => queue))
7
+ yield
8
+ Context.clear!
9
+ BreadcrumbBuffer.clear!
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ require 'raven/utils/context_filter'
2
+
3
+ module Raven
4
+ module Sidekiq
5
+ class ErrorHandler
6
+ SIDEKIQ_NAME = "Sidekiq".freeze
7
+
8
+ def call(ex, context)
9
+ context = Utils::ContextFilter.filter_context(context)
10
+ Raven.context.transaction.push transaction_from_context(context)
11
+ Raven.capture_exception(
12
+ ex,
13
+ :message => ex.message,
14
+ :extra => { :sidekiq => context }
15
+ )
16
+ Context.clear!
17
+ BreadcrumbBuffer.clear!
18
+ end
19
+
20
+ private
21
+
22
+ # this will change in the future:
23
+ # https://github.com/mperham/sidekiq/pull/3161
24
+ def transaction_from_context(context)
25
+ classname = (context["wrapped"] || context["class"] ||
26
+ (context[:job] && (context[:job]["wrapped"] || context[:job]["class"]))
27
+ )
28
+ if classname
29
+ "#{SIDEKIQ_NAME}/#{classname}"
30
+ elsif context[:event]
31
+ "#{SIDEKIQ_NAME}/#{context[:event]}"
32
+ else
33
+ SIDEKIQ_NAME
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,87 +1,13 @@
1
1
  require 'time'
2
2
  require 'sidekiq'
3
-
4
- module Raven
5
- class SidekiqCleanupMiddleware
6
- def call(_worker, job, queue)
7
- Raven.context.transaction.push "Sidekiq/#{job['class']}"
8
- Raven.extra_context(:sidekiq => job.merge("queue" => queue))
9
- yield
10
- Context.clear!
11
- BreadcrumbBuffer.clear!
12
- end
13
- end
14
-
15
- class SidekiqErrorHandler
16
- ACTIVEJOB_RESERVED_PREFIX = "_aj_".freeze
17
- HAS_GLOBALID = const_defined?('GlobalID')
18
-
19
- def call(ex, context)
20
- context = filter_context(context)
21
- Raven.context.transaction.push transaction_from_context(context)
22
- Raven.capture_exception(
23
- ex,
24
- :message => ex.message,
25
- :extra => { :sidekiq => context }
26
- )
27
- Context.clear!
28
- BreadcrumbBuffer.clear!
29
- end
30
-
31
- private
32
-
33
- # Once an ActiveJob is queued, ActiveRecord references get serialized into
34
- # some internal reserved keys, such as _aj_globalid.
35
- #
36
- # The problem is, if this job in turn gets queued back into ActiveJob with
37
- # these magic reserved keys, ActiveJob will throw up and error. We want to
38
- # capture these and mutate the keys so we can sanely report it.
39
- def filter_context(context)
40
- case context
41
- when Array
42
- context.map { |arg| filter_context(arg) }
43
- when Hash
44
- Hash[context.map { |key, value| filter_context_hash(key, value) }]
45
- else
46
- format_globalid(context)
47
- end
48
- end
49
-
50
- def filter_context_hash(key, value)
51
- (key = key[3..-1]) if key [0..3] == ACTIVEJOB_RESERVED_PREFIX
52
- [key, filter_context(value)]
53
- end
54
-
55
- # this will change in the future:
56
- # https://github.com/mperham/sidekiq/pull/3161
57
- def transaction_from_context(context)
58
- classname = (context["wrapped"] || context["class"] ||
59
- (context[:job] && (context[:job]["wrapped"] || context[:job]["class"]))
60
- )
61
- if classname
62
- "Sidekiq/#{classname}"
63
- elsif context[:event]
64
- "Sidekiq/#{context[:event]}"
65
- else
66
- "Sidekiq"
67
- end
68
- end
69
-
70
- def format_globalid(context)
71
- if HAS_GLOBALID && context.is_a?(GlobalID)
72
- context.to_s
73
- else
74
- context
75
- end
76
- end
77
- end
78
- end
3
+ require 'raven/integrations/sidekiq/cleanup_middleware'
4
+ require 'raven/integrations/sidekiq/error_handler'
79
5
 
80
6
  if Sidekiq::VERSION > '3'
81
7
  Sidekiq.configure_server do |config|
82
- config.error_handlers << Raven::SidekiqErrorHandler.new
8
+ config.error_handlers << Raven::Sidekiq::ErrorHandler.new
83
9
  config.server_middleware do |chain|
84
- chain.add Raven::SidekiqCleanupMiddleware
10
+ chain.add Raven::Sidekiq::CleanupMiddleware
85
11
  end
86
12
  end
87
13
  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
data/lib/raven/logger.rb CHANGED
@@ -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
@@ -10,17 +10,27 @@ module Raven
10
10
  private
11
11
 
12
12
  def process_if_symbol_keys(data)
13
- data[:request][:cookies] = STRING_MASK if data[:request][:cookies]
13
+ if cookies = data.dig(:request, :cookies)
14
+ data[:request][:cookies] = generate_masked_cookies(cookies)
15
+ end
14
16
 
15
- return unless data[:request][:headers] && data[:request][:headers]["Cookie"]
16
- data[:request][:headers]["Cookie"] = STRING_MASK
17
+ if cookies_header = data[:request][:headers]["Cookie"]
18
+ data[:request][:headers]["Cookie"] = generate_masked_cookies(cookies_header)
19
+ end
17
20
  end
18
21
 
19
22
  def process_if_string_keys(data)
20
- data["request"]["cookies"] = STRING_MASK if data["request"]["cookies"]
23
+ if cookies = data.dig("request", "cookies")
24
+ data["request"]["cookies"] = generate_masked_cookies(cookies)
25
+ end
21
26
 
22
- return unless data["request"]["headers"] && data["request"]["headers"]["Cookie"]
23
- data["request"]["headers"]["Cookie"] = STRING_MASK
27
+ if cookies_header = data.dig("request", "headers", "Cookie")
28
+ data["request"]["headers"]["Cookie"] = generate_masked_cookies(cookies_header)
29
+ end
30
+ end
31
+
32
+ def generate_masked_cookies(cookies)
33
+ cookies.merge(cookies) { STRING_MASK } if cookies.respond_to?(:merge)
24
34
  end
25
35
  end
26
36
  end