exception_handling 2.17.0.pre.tstarck.1 → 3.0.pre.1

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 (48) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -3
  3. data/.ruby-version +1 -1
  4. data/Gemfile +16 -12
  5. data/Gemfile.lock +138 -153
  6. data/README.md +21 -90
  7. data/Rakefile +11 -8
  8. data/exception_handling.gemspec +10 -14
  9. data/lib/exception_handling/exception_info.rb +11 -15
  10. data/lib/exception_handling/honeybadger_callbacks.rb +59 -0
  11. data/lib/exception_handling/log_stub_error.rb +1 -2
  12. data/lib/exception_handling/methods.rb +53 -6
  13. data/lib/exception_handling/testing.rb +10 -20
  14. data/lib/exception_handling/version.rb +1 -1
  15. data/lib/exception_handling.rb +34 -135
  16. data/semaphore_ci/setup.sh +3 -0
  17. data/{spec → test}/helpers/exception_helpers.rb +2 -2
  18. data/{spec/spec_helper.rb → test/test_helper.rb} +45 -75
  19. data/test/unit/exception_handling/exception_catalog_test.rb +85 -0
  20. data/test/unit/exception_handling/exception_description_test.rb +82 -0
  21. data/{spec/unit/exception_handling/exception_info_spec.rb → test/unit/exception_handling/exception_info_test.rb} +114 -170
  22. data/test/unit/exception_handling/honeybadger_callbacks_test.rb +122 -0
  23. data/{spec/unit/exception_handling/log_error_stub_spec.rb → test/unit/exception_handling/log_error_stub_test.rb} +22 -38
  24. data/{spec/unit/exception_handling/mailer_spec.rb → test/unit/exception_handling/mailer_test.rb} +18 -17
  25. data/test/unit/exception_handling/methods_test.rb +84 -0
  26. data/test/unit/exception_handling/sensu_test.rb +52 -0
  27. data/test/unit/exception_handling_test.rb +1109 -0
  28. metadata +59 -99
  29. data/.github/CODEOWNERS +0 -1
  30. data/.github/workflows/pipeline.yml +0 -36
  31. data/.rspec +0 -3
  32. data/.tool-versions +0 -1
  33. data/Appraisals +0 -19
  34. data/CHANGELOG.md +0 -149
  35. data/gemfiles/rails_5.gemfile +0 -18
  36. data/gemfiles/rails_6.gemfile +0 -18
  37. data/gemfiles/rails_7.gemfile +0 -18
  38. data/lib/exception_handling/escalate_callback.rb +0 -19
  39. data/lib/exception_handling/logging_methods.rb +0 -27
  40. data/spec/rake_test_warning_false.rb +0 -20
  41. data/spec/unit/exception_handling/escalate_callback_spec.rb +0 -81
  42. data/spec/unit/exception_handling/exception_catalog_spec.rb +0 -85
  43. data/spec/unit/exception_handling/exception_description_spec.rb +0 -82
  44. data/spec/unit/exception_handling/logging_methods_spec.rb +0 -38
  45. data/spec/unit/exception_handling/methods_spec.rb +0 -105
  46. data/spec/unit/exception_handling/sensu_spec.rb +0 -51
  47. data/spec/unit/exception_handling_spec.rb +0 -1465
  48. /data/{spec → test}/helpers/controller_helpers.rb +0 -0
@@ -3,7 +3,7 @@
3
3
  module ExceptionHandling
4
4
  class ExceptionInfo
5
5
 
6
- ENVIRONMENT_ALLOWLIST = [
6
+ ENVIRONMENT_WHITELIST = [
7
7
  /^HTTP_/,
8
8
  /^QUERY_/,
9
9
  /^REQUEST_/,
@@ -46,20 +46,16 @@ module ExceptionHandling
46
46
  EOS
47
47
 
48
48
  SECTIONS = [:request, :session, :environment, :backtrace, :event_response].freeze
49
- HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes,
50
- :user_details, :request, :session, :environment, :backtrace, :event_response, :log_context].freeze
49
+ HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes, :user_details, :request, :session, :environment, :backtrace, :event_response].freeze
51
50
 
52
- attr_reader :exception, :controller, :exception_context, :timestamp, :honeybadger_tags
51
+ attr_reader :exception, :controller, :exception_context, :timestamp
53
52
 
54
- def initialize(exception, exception_context, timestamp, controller: nil, data_callback: nil, log_context: nil)
53
+ def initialize(exception, exception_context, timestamp, controller = nil, data_callback = nil)
55
54
  @exception = exception
56
55
  @exception_context = exception_context
57
56
  @timestamp = timestamp
58
57
  @controller = controller || controller_from_context(exception_context)
59
58
  @data_callback = data_callback
60
- # merge into the surrounding context just like ContextualLogger does when logging
61
- @merged_log_context = ExceptionHandling.logger.current_context_for_thread.deep_merge(log_context || {})
62
- @honeybadger_tags = Array(@merged_log_context[:honeybadger_tags] || [])
63
59
  end
64
60
 
65
61
  def data
@@ -83,10 +79,9 @@ module ExceptionHandling
83
79
  end
84
80
 
85
81
  def controller_name
86
- @controller_name ||= (
87
- @merged_log_context[:honeybadger_grouping] ||
88
- (@controller && @controller.request.parameters.with_indifferent_access[:controller])
89
- ).to_s
82
+ @controller_name ||= if @controller
83
+ @controller.request.parameters.with_indifferent_access[:controller]
84
+ end.to_s
90
85
  end
91
86
 
92
87
  private
@@ -181,7 +176,7 @@ module ExceptionHandling
181
176
 
182
177
  def clean_environment(env)
183
178
  Hash[ env.map do |k, v|
184
- [k, v] if !"#{k}: #{v}".in?(ENVIRONMENT_OMIT) && ENVIRONMENT_ALLOWLIST.any? { |regex| k =~ regex }
179
+ [k, v] if !"#{k}: #{v}".in?(ENVIRONMENT_OMIT) && ENVIRONMENT_WHITELIST.any? { |regex| k =~ regex }
185
180
  end.compact ]
186
181
  end
187
182
 
@@ -272,13 +267,14 @@ module ExceptionHandling
272
267
  data = enhanced_data.dup
273
268
  data[:server] = ExceptionHandling.server_name
274
269
  data[:exception_context] = deep_clean_hash(@exception_context) if @exception_context.present?
275
- data[:log_context] = @merged_log_context
276
270
  unstringify_sections(data)
277
- HONEYBADGER_CONTEXT_SECTIONS.each_with_object({}) do |section, context|
271
+ context_data = HONEYBADGER_CONTEXT_SECTIONS.reduce({}) do |context, section|
278
272
  if data[section].present?
279
273
  context[section] = data[section]
280
274
  end
275
+ context
281
276
  end
277
+ context_data
282
278
  end
283
279
  end
284
280
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionHandling
4
+ module HoneybadgerCallbacks
5
+ class << self
6
+ def register_callbacks
7
+ if ExceptionHandling.honeybadger_defined?
8
+ Honeybadger.local_variable_filter(&method(:local_variable_filter))
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def inspect_object(object, filter_keys)
15
+ inspection_output = object.inspect
16
+
17
+ if contains_filter_key?(filter_keys, inspection_output)
18
+ filtered_object(object)
19
+ else
20
+ inspection_output
21
+ end
22
+ rescue => ex
23
+ details = if object.respond_to?(:to_pk)
24
+ " @pk=#{object.to_pk}"
25
+ elsif object.respond_to?(:id)
26
+ " @id=#{object.id}"
27
+ end
28
+
29
+ "#<#{object.class.name}#{details} [error '#{ex.class.name}: #{ex.message}' while calling #inspect]>"
30
+ end
31
+
32
+ def local_variable_filter(_symbol, object, filter_keys)
33
+ case object
34
+ # Honeybadger will filter these data types for us
35
+ when String, Hash, Array, Set, Numeric, TrueClass, FalseClass, NilClass
36
+ object
37
+ else # handle other Ruby objects, intended for POROs
38
+ inspect_object(object, filter_keys)
39
+ end
40
+ end
41
+
42
+ def contains_filter_key?(filter_keys, string)
43
+ filter_keys._?.any? { |key| string.include?(key) }
44
+ end
45
+
46
+ def filtered_object(object)
47
+ # make the output look similar to inspect
48
+ # use [FILTERED], just like honeybadger does
49
+ if object.respond_to?(:to_pk)
50
+ "#<#{object.class.name} @pk=#{object.to_pk}, [FILTERED]>"
51
+ elsif object.respond_to?(:id)
52
+ "#<#{object.class.name} @id=#{object.id}, [FILTERED]>"
53
+ else
54
+ "#<#{object.class.name} [FILTERED]>"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Test Helper that supports Minitest::Test and Test::Unit
5
- # Used by tests in the consumers of this gem to track exceptions.
4
+ # Used by functional tests to track exceptions.
6
5
  #
7
6
 
8
7
  module LogErrorStub
@@ -1,15 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/concern'
4
- require_relative 'logging_methods'
5
4
 
6
5
  module ExceptionHandling
7
6
  module Methods # included on models and controllers
8
7
  extend ActiveSupport::Concern
9
- include ExceptionHandling::LoggingMethods
10
8
 
11
9
  protected
12
10
 
11
+ def log_error(exception_or_string, exception_context = '')
12
+ controller = self if respond_to?(:request) && respond_to?(:session)
13
+ ExceptionHandling.log_error(exception_or_string, exception_context, controller)
14
+ end
15
+
16
+ def log_error_rack(exception_or_string, exception_context = '', rack_filter = '')
17
+ ExceptionHandling.log_error_rack(exception_or_string, exception_context, rack_filter)
18
+ end
19
+
20
+ def log_warning(message)
21
+ ExceptionHandling.log_warning(message)
22
+ end
23
+
24
+ def log_info(message)
25
+ ExceptionHandling.logger.info(message)
26
+ end
27
+
28
+ def log_debug(message)
29
+ ExceptionHandling.logger.debug(message)
30
+ end
31
+
32
+ def ensure_safe(exception_context = "")
33
+ yield
34
+ rescue => ex
35
+ log_error ex, exception_context
36
+ nil
37
+ end
38
+
39
+ def escalate_error(exception_or_string, email_subject)
40
+ ExceptionHandling.escalate_error(exception_or_string, email_subject)
41
+ end
42
+
43
+ def escalate_warning(message, email_subject)
44
+ ExceptionHandling.escalate_warning(message, email_subject)
45
+ end
46
+
47
+ def ensure_escalation(*args)
48
+ ExceptionHandling.ensure_escalation(*args) do
49
+ yield
50
+ end
51
+ end
52
+
53
+ def alert_warning(*args)
54
+ ExceptionHandling.alert_warning(*args)
55
+ end
56
+
57
+ def ensure_alert(*args)
58
+ ExceptionHandling.ensure_alert(*args) do
59
+ yield
60
+ end
61
+ end
62
+
13
63
  def long_controller_action_timeout
14
64
  if defined?(Rails) && Rails.respond_to?(:env) && Rails.env == 'test'
15
65
  300
@@ -38,10 +88,7 @@ module ExceptionHandling
38
88
  end
39
89
 
40
90
  included do
41
- Deprecation3_0.deprecation_warning('ExceptionHandling::Methods', 'include LoggingMethods; in controllers, set your own around_filter to set logging context')
42
- if respond_to? :around_filter
43
- around_filter :set_current_controller
44
- end
91
+ around_filter :set_current_controller if respond_to? :around_filter
45
92
  end
46
93
 
47
94
  class_methods do
@@ -4,7 +4,7 @@
4
4
 
5
5
  module ExceptionHandling
6
6
  module Testing
7
- class ControllerStubBase
7
+ class ControllerStub
8
8
 
9
9
  class Request
10
10
  attr_accessor :parameters, :protocol, :host, :request_uri, :env, :session_options
@@ -25,7 +25,7 @@ module ExceptionHandling
25
25
  attr_accessor :around_filter_method
26
26
 
27
27
  def around_filter(method)
28
- self.around_filter_method = method
28
+ ControllerStub.around_filter_method = method
29
29
  end
30
30
  end
31
31
 
@@ -44,6 +44,14 @@ module ExceptionHandling
44
44
  end
45
45
  end
46
46
 
47
+ def simulate_around_filter(&block)
48
+ set_current_controller(&block)
49
+ end
50
+
51
+ def controller_name
52
+ "ControllerStub"
53
+ end
54
+
47
55
  def action_name
48
56
  "test_action"
49
57
  end
@@ -51,27 +59,9 @@ module ExceptionHandling
51
59
  def complete_request_uri
52
60
  "#{@request.protocol}#{@request.host}#{@request.request_uri}"
53
61
  end
54
- end
55
-
56
- class LoggingMethodsControllerStub < ControllerStubBase
57
- include ExceptionHandling::LoggingMethods
58
-
59
- def controller_name
60
- "LoggingMethodsControllerStub"
61
- end
62
- end
63
62
 
64
- class MethodsControllerStub < ControllerStubBase
65
63
  include ExceptionHandling::Methods
66
64
  set_long_controller_action_timeout 2
67
-
68
- def simulate_around_filter(&block)
69
- set_current_controller(&block)
70
- end
71
-
72
- def controller_name
73
- "MethodsControllerStub"
74
- end
75
65
  end
76
66
  end
77
67
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExceptionHandling
4
- VERSION = '2.17.0.pre.tstarck.1'
4
+ VERSION = '3.0.pre.1'
5
5
  end
@@ -1,21 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'digest'
4
3
  require 'timeout'
5
4
  require 'active_support'
6
- require 'active_support/core_ext'
5
+ require 'active_support/core_ext/hash'
7
6
  require 'contextual_logger'
8
7
 
9
8
  require 'invoca/utils'
10
9
 
11
- require 'exception_handling/mailer'
12
- require 'exception_handling/sensu'
13
- require 'exception_handling/methods'
14
- require 'exception_handling/log_stub_error'
15
- require 'exception_handling/exception_description'
16
- require 'exception_handling/exception_catalog'
17
- require 'exception_handling/exception_info'
18
- require 'exception_handling/escalate_callback'
10
+ require "exception_handling/mailer"
11
+ require "exception_handling/sensu"
12
+ require "exception_handling/methods"
13
+ require "exception_handling/log_stub_error"
14
+ require "exception_handling/exception_description"
15
+ require "exception_handling/exception_catalog"
16
+ require "exception_handling/exception_info"
17
+ require "exception_handling/honeybadger_callbacks.rb"
19
18
 
20
19
  _ = ActiveSupport::HashWithIndifferentAccess
21
20
 
@@ -30,8 +29,6 @@ module ExceptionHandling # never included
30
29
  AUTHENTICATION_HEADERS = ['HTTP_AUTHORIZATION', 'X-HTTP_AUTHORIZATION', 'X_HTTP_AUTHORIZATION', 'REDIRECT_X_HTTP_AUTHORIZATION'].freeze
31
30
  HONEYBADGER_STATUSES = [:success, :failure, :skipped].freeze
32
31
 
33
- Deprecation3_0 = ActiveSupport::Deprecation.new('3.0', 'exception_handling')
34
-
35
32
  class << self
36
33
 
37
34
  #
@@ -53,28 +50,15 @@ module ExceptionHandling # never included
53
50
  @exception_recipients or raise ArgumentError, "You must assign a value to #{name}.exception_recipients"
54
51
  end
55
52
 
56
- def configured?
57
- !@logger.nil?
58
- end
59
-
60
53
  def logger
61
54
  @logger or raise ArgumentError, "You must assign a value to #{name}.logger"
62
55
  end
63
56
 
64
57
  def logger=(logger)
65
- @logger = if logger.nil? || logger.is_a?(ContextualLogger::LoggerMixin)
66
- logger
67
- else
68
- Deprecation3_0.deprecation_warning('implicit extend with ContextualLogger::LoggerMixin', 'extend your logger instance or include into your logger class first')
69
- logger.extend(ContextualLogger::LoggerMixin)
70
- end
71
- EscalateCallback.register_if_configured!
58
+ @logger = logger.is_a?(ContextualLogger) ? logger : ContextualLogger.new(logger)
72
59
  end
73
60
 
74
- def default_metric_name(exception_data, exception, treat_like_warning, include_prefix: true)
75
- include_prefix and Deprecation3_0.deprecation_warning("the 'expection_handling.' prefix in ExceptionHandling::default_metric_name",
76
- "do not rely on metric names including the 'exception_handling.' prefix.")
77
-
61
+ def default_metric_name(exception_data, exception, treat_like_warning)
78
62
  metric_name = if exception_data['metric_name']
79
63
  exception_data['metric_name']
80
64
  elsif exception.is_a?(ExceptionHandling::Warning)
@@ -86,7 +70,7 @@ module ExceptionHandling # never included
86
70
  "exception"
87
71
  end
88
72
 
89
- "#{'exception_handling.' if include_prefix}#{metric_name}"
73
+ "exception_handling.#{metric_name}"
90
74
  end
91
75
 
92
76
  def default_honeybadger_metric_name(honeybadger_status)
@@ -110,12 +94,10 @@ module ExceptionHandling # never included
110
94
  attr_accessor :sensu_host
111
95
  attr_accessor :sensu_port
112
96
  attr_accessor :sensu_prefix
113
- attr_reader :honeybadger_log_context_tags
114
97
 
115
98
  attr_reader :filter_list_filename
116
99
  attr_reader :eventmachine_safe
117
100
  attr_reader :eventmachine_synchrony
118
- attr_reader :honeybadger_auto_tagger
119
101
 
120
102
  @filter_list_filename = "./config/exception_filters.yml"
121
103
  @email_environment = ""
@@ -156,30 +138,6 @@ module ExceptionHandling # never included
156
138
  @exception_catalog ||= ExceptionCatalog.new(@filter_list_filename)
157
139
  end
158
140
 
159
- # rubocop:disable Style/TrivialAccessors
160
- # @param value [Proc|nil] Proc that accepts 1 parameter that will be the exception object or nil to disable the auto-tagger.
161
- # The proc is always expected to return an array of strings. The array can be empty.
162
- def honeybadger_auto_tagger=(value)
163
- @honeybadger_auto_tagger = value
164
- end
165
- # rubocop:enable Style/TrivialAccessors
166
-
167
- # @param tag_name [String]
168
- # @param path [Array]
169
- def add_honeybadger_tag_from_log_context(tag_name, path:)
170
- tag_name.is_a?(String) or raise ArgumentError, "tag_name must be a String, #{tag_name.inspect}"
171
- path.is_a?(Array) or raise ArgumentError, "path must be an Array, #{path.inspect}"
172
- @honeybadger_log_context_tags ||= {}
173
- if @honeybadger_log_context_tags.key?(tag_name)
174
- log_warning("Overwriting existing tag path for '#{tag_name}' from #{@honeybadger_log_context_tags[tag_name]} to #{path}")
175
- end
176
- @honeybadger_log_context_tags[tag_name] = path
177
- end
178
-
179
- def clear_honeybadger_tags_from_log_context
180
- @honeybadger_log_context_tags = nil
181
- end
182
-
183
141
  #
184
142
  # internal settings (don't set directly)
185
143
  #
@@ -219,18 +177,13 @@ module ExceptionHandling # never included
219
177
  # Called directly by our code, usually from rescue blocks.
220
178
  # Writes to log file and may send to honeybadger
221
179
  #
222
- # TODO: the **log_context means we can never have context named treat_like_warning. In general, keyword args will be conflated with log_context.
223
- # Ideally we'd separate to log_context from the other keywords so they don't interfere in any way. Or have no keyword args.
224
- #
225
180
  # Functional Test Operation:
226
181
  # Calls into handle_stub_log_error and returns. no log file. no honeybadger
227
182
  #
228
- def log_error(exception_or_string, exception_context = '', controller = nil, treat_like_warning: false, **log_context, &data_callback)
183
+ def log_error(exception_or_string, exception_context = '', treat_like_warning: false, **log_context, &data_callback)
229
184
  ex = make_exception(exception_or_string)
230
185
  timestamp = set_log_error_timestamp
231
- exception_info = ExceptionInfo.new(ex, exception_context, timestamp,
232
- controller: controller || current_controller, data_callback: data_callback,
233
- log_context: log_context)
186
+ exception_info = ExceptionInfo.new(ex, exception_context, timestamp, current_controller, data_callback)
234
187
 
235
188
  if stub_handler
236
189
  stub_handler.handle_stub_log_error(exception_info.data)
@@ -257,13 +210,7 @@ module ExceptionHandling # never included
257
210
  #
258
211
  def write_exception_to_log(ex, exception_context, timestamp, log_context = {})
259
212
  ActiveSupport::Deprecation.silence do
260
- log_message = "#{exception_context}\n#{ex.class}: (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n"
261
-
262
- if ex.is_a?(Warning)
263
- ExceptionHandling.logger.warn("\nExceptionHandlingWarning (Warning:#{timestamp}) #{log_message}", **log_context)
264
- else
265
- ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{log_message}", **log_context)
266
- end
213
+ ExceptionHandling.logger.fatal("\nExceptionHandlingError (Error:#{timestamp}) #{ex.class} #{exception_context} (#{encode_utf8(ex.message.to_s)}):\n " + clean_backtrace(ex).join("\n ") + "\n\n", log_context)
267
214
  end
268
215
  end
269
216
 
@@ -296,16 +243,11 @@ module ExceptionHandling # never included
296
243
  def send_exception_to_honeybadger(exception_info)
297
244
  exception = exception_info.exception
298
245
  exception_description = exception_info.exception_description
299
-
300
- # Note: Both commas and spaces are treated as delimiters for the :tags string. Space-delimiters are not officially documented.
301
- # https://github.com/honeybadger-io/honeybadger-ruby/pull/422
302
- tags = tags_for_honeybadger(exception_info).join(' ')
303
246
  response = Honeybadger.notify(error_class: exception_description ? exception_description.filter_name : exception.class.name,
304
247
  error_message: exception.message.to_s,
305
248
  exception: exception,
306
249
  context: exception_info.honeybadger_context_data,
307
- controller: exception_info.controller_name,
308
- tags: tags)
250
+ controller: exception_info.controller_name)
309
251
  response ? :success : :failure
310
252
  rescue Exception => ex
311
253
  warn("ExceptionHandling.send_exception_to_honeybadger rescued exception while logging #{exception_info.exception_context}:\n#{exception.class}: #{exception.message}:\n#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
@@ -323,41 +265,38 @@ module ExceptionHandling # never included
323
265
  #
324
266
  # Expects passed in hash to only include keys which be directly set on the Honeybadger config
325
267
  #
326
- def enable_honeybadger(**config)
268
+ def enable_honeybadger(config = {})
327
269
  Bundler.require(:honeybadger)
270
+ HoneybadgerCallbacks.register_callbacks
328
271
  Honeybadger.configure do |config_klass|
329
272
  config.each do |k, v|
330
- if k == :before_notify
331
- config_klass.send(k, v)
332
- else
333
- config_klass.send(:"#{k}=", v)
334
- end
273
+ config_klass.send(:"#{k}=", v)
335
274
  end
336
275
  end
337
276
  end
338
277
 
339
- def log_warning(message, **log_context)
278
+ def log_warning(message, log_context = {})
340
279
  warning = Warning.new(message)
341
280
  warning.set_backtrace([])
342
281
  log_error(warning, **log_context)
343
282
  end
344
283
 
345
- def log_info(message, **log_context)
346
- ExceptionHandling.logger.info(message, **log_context)
284
+ def log_info(message, log_context = {})
285
+ ExceptionHandling.logger.info(message, log_context)
347
286
  end
348
287
 
349
- def log_debug(message, **log_context)
350
- ExceptionHandling.logger.debug(message, **log_context)
288
+ def log_debug(message, log_context = {})
289
+ ExceptionHandling.logger.debug(message, log_context)
351
290
  end
352
291
 
353
- def ensure_safe(exception_context = "", **log_context)
292
+ def ensure_safe(exception_context = "", log_context = {})
354
293
  yield
355
294
  rescue => ex
356
295
  log_error(ex, exception_context, **log_context)
357
296
  nil
358
297
  end
359
298
 
360
- def ensure_completely_safe(exception_context = "", **log_context)
299
+ def ensure_completely_safe(exception_context = "", log_context = {})
361
300
  yield
362
301
  rescue SystemExit, SystemStackError, NoMemoryError, SecurityError, SignalException
363
302
  raise
@@ -372,29 +311,26 @@ module ExceptionHandling # never included
372
311
  escalate(email_subject, ex, last_exception_timestamp, production_support_recipients)
373
312
  end
374
313
 
375
- def escalate_error(exception_or_string, email_subject, custom_recipients = nil, **log_context)
314
+ def escalate_error(exception_or_string, email_subject, custom_recipients = nil, log_context = {})
376
315
  ex = make_exception(exception_or_string)
377
316
  log_error(ex, **log_context)
378
317
  escalate(email_subject, ex, last_exception_timestamp, custom_recipients)
379
318
  end
380
319
 
381
- def escalate_warning(message, email_subject, custom_recipients = nil, **log_context)
320
+ def escalate_warning(message, email_subject, custom_recipients = nil, log_context = {})
382
321
  ex = Warning.new(message)
383
322
  log_error(ex, **log_context)
384
323
  escalate(email_subject, ex, last_exception_timestamp, custom_recipients)
385
324
  end
386
325
 
387
- def ensure_escalation(email_subject, custom_recipients = nil, **log_context)
326
+ def ensure_escalation(email_subject, custom_recipients = nil, log_context = {})
388
327
  yield
389
328
  rescue => ex
390
- escalate_error(ex, email_subject, custom_recipients, **log_context)
329
+ escalate_error(ex, email_subject, custom_recipients, log_context)
391
330
  nil
392
331
  end
393
332
 
394
- deprecate :escalate_to_production_support, :escalate_error, :escalate_warning, :ensure_escalation,
395
- deprecator: ActiveSupport::Deprecation.new('3.0', 'ExceptionHandling')
396
-
397
- def alert_warning(exception_or_string, alert_name, exception_context, **log_context)
333
+ def alert_warning(exception_or_string, alert_name, exception_context, log_context)
398
334
  ex = make_exception(exception_or_string)
399
335
  log_error(ex, exception_context, **log_context)
400
336
  begin
@@ -404,10 +340,10 @@ module ExceptionHandling # never included
404
340
  end
405
341
  end
406
342
 
407
- def ensure_alert(alert_name, exception_context, **log_context)
343
+ def ensure_alert(alert_name, exception_context, log_context = {})
408
344
  yield
409
345
  rescue => ex
410
- alert_warning(ex, alert_name, exception_context, **log_context)
346
+ alert_warning(ex, alert_name, exception_context, log_context)
411
347
  nil
412
348
  end
413
349
 
@@ -424,7 +360,7 @@ module ExceptionHandling # never included
424
360
  result
425
361
  end
426
362
 
427
- def log_periodically(exception_key, interval, message, **log_context)
363
+ def log_periodically(exception_key, interval, message, log_context = {})
428
364
  self.periodic_exception_intervals ||= {}
429
365
  last_logged = self.periodic_exception_intervals[exception_key]
430
366
  if !last_logged || ((last_logged + interval) < Time.now)
@@ -461,41 +397,6 @@ module ExceptionHandling # never included
461
397
 
462
398
  private
463
399
 
464
- # @param exception_info [ExceptionInfo]
465
- #
466
- # @return [Array<String>]
467
- def tags_for_honeybadger(exception_info)
468
- (
469
- honeybadger_auto_tags(exception_info.exception) +
470
- exception_info.honeybadger_tags +
471
- honeybadger_tags_from_log_context(exception_info.honeybadger_context_data)
472
- ).uniq
473
- end
474
-
475
- # @param exception [Exception]
476
- #
477
- # @return [Array<String>]
478
- def honeybadger_auto_tags(exception)
479
- @honeybadger_auto_tagger&.call(exception) || []
480
- rescue => ex
481
- traces = ex.backtrace.join("\n")
482
- message = "Unable to execute honeybadger_auto_tags callback. #{ExceptionHandling.encode_utf8(ex.message.to_s)} #{traces}\n"
483
- ExceptionHandling.log_info(message)
484
- []
485
- end
486
-
487
- def honeybadger_tags_from_log_context(honeybadger_context_data)
488
- if @honeybadger_log_context_tags
489
- @honeybadger_log_context_tags.map do |tag_name, tag_path|
490
- if (value_from_log_context = honeybadger_context_data.dig(:log_context, *tag_path))
491
- "#{tag_name}:#{value_from_log_context}"
492
- end
493
- end.compact
494
- else
495
- []
496
- end
497
- end
498
-
499
400
  def execute_custom_log_error_callback(exception_data, exception, treat_like_warning, external_notification_results)
500
401
  if ExceptionHandling.post_log_error_hook
501
402
  honeybadger_status = external_notification_results[:honeybadger_status] || :skipped
@@ -562,6 +463,4 @@ module ExceptionHandling # never included
562
463
  end
563
464
  end
564
465
  end
565
-
566
- EscalateCallback.register_if_configured!
567
466
  end
@@ -0,0 +1,3 @@
1
+ #!/bin/sh -x
2
+
3
+ bundle install --path vendor/bundle
@@ -7,7 +7,7 @@ module ExceptionHelpers
7
7
 
8
8
  def exception_with_nil_message
9
9
  exception_with_nil_message = RuntimeError.new(nil)
10
- allow(exception_with_nil_message).to receive(:message).and_return(nil)
10
+ stub(exception_with_nil_message).message { nil }
11
11
  exception_with_nil_message
12
12
  end
13
13
 
@@ -15,6 +15,6 @@ module ExceptionHelpers
15
15
 
16
16
  def capture_notifications
17
17
  @sent_notifications = []
18
- allow(ExceptionHandling).to receive(:send_exception_to_honeybadger).with(any_args) { |exception_info| @sent_notifications << exception_info }
18
+ stub(ExceptionHandling).send_exception_to_honeybadger(anything) { |exception_info| @sent_notifications << exception_info }
19
19
  end
20
20
  end