escalate 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ca403c35fe8123ebf15d068d392789e5de418f71
4
- data.tar.gz: df6eb4d755258ce4e6d3617ca88075266e591acc
2
+ SHA256:
3
+ metadata.gz: 367073142399930c67886a1890af1e684d767a11c62d3719fd95ecd392a4c47d
4
+ data.tar.gz: 368728d4e4db7d3e466571c563902e096093310685ffffc64c1906b05d95338e
5
5
  SHA512:
6
- metadata.gz: aae531b8f6fc1f8bb4e52a2cbf1ff613fd74f19298ca18aca77936f6e44b741c9ce42b02817bcfb755379d95c6e577342b1a17af0a387e66a00348baf96a3703
7
- data.tar.gz: 2d4c26aad91e60c1c2b192b66d6f332db6a858b7f06588788f5b166d41912a8daa27cac39d166ac3cea7e770417037062add542bf36f4429a8c0cc8f0ad74a7b
6
+ metadata.gz: 59605b0ed9a30982a6e6dc92d37c20578b4b52c643361a8b6e7ac2876579ade371c0b528f156de8da92502f7002d66f515c467f8fe5e4a5038580d506f174d08
7
+ data.tar.gz: 0a24440c7988110d5cacc07bd6ec262074de501938c4076e29bea9607ee38d4d6c19f424086f81fd09ef9266e65f65a9f39b6f9ca36018fcbe9f9688041d820e
data/CHANGELOG.md CHANGED
@@ -4,10 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.2.0] - 2021-03-02
8
+ ### Added
9
+ - Added support for `on_escalate(log_first: false)`. The `escalate` gem will log first before
10
+ escalating if either of these is true: there are no `on_escalate` blocks registered, or
11
+ there are some and at least one of them passed `log_first: false`.
12
+
7
13
  ## [0.1.0] - 2021-02-03
8
14
  ### Added
9
15
  - Added `Escalate.mixin` interface for mixing in `Escalate` with your module for easy escalation of rescued exceptions
10
16
  - Added `escalate` method for escalating rescued exceptions with default behavior of logging to `STDERR`
11
17
  - Added `Escalate.on_escalate` for registering escalation callbacks like `Honeybadger` or `Sentry`
12
18
 
19
+ [0.2.0]: https://github.com/Invoca/escalate/compare/v0.1.0...v0.2.0
13
20
  [0.1.0]: https://github.com/Invoca/escalate/releases/tag/v0.1.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- escalate (0.1.0)
4
+ escalate (0.2.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -49,6 +49,7 @@ GEM
49
49
  thread_safe (~> 0.1)
50
50
 
51
51
  PLATFORMS
52
+ ruby
52
53
  x86_64-darwin-19
53
54
 
54
55
  DEPENDENCIES
data/README.md CHANGED
@@ -58,8 +58,44 @@ end
58
58
  When `SomeGem.escalate` above is triggered, it will use the logger returned by `SomeGem.logger` or
59
59
  default to a `STDERR` logger and do the following:
60
60
 
61
- 1. Log an error containing the exception and any additional information about the current environment that is specified
62
- 2. Trigger any `escalation_callbacks` configured on the `Escalate` gem
61
+ 1. [optional] Log an error containing the exception, location_message, and context hash
62
+ 2. Trigger any `on_escalate_callbacks` configured on the `Escalate` gem
63
+
64
+ Step (1) is optional. It will happen if either of these is true:
65
+ - by default if no `on_escalate_callbacks` have been registered; or
66
+ - if any of the `on_escalate_callbacks` was registered with `on_escalate(log_first: true)`.
67
+
68
+ ### Registering an Escalate Callback
69
+
70
+ If you are using an error reporting service, you can register an `on_escalate` callback to escalate exceptions.
71
+ You have the option to handle logging yourself, or to let `escalate` log first, before calling your callback.
72
+
73
+ #### Leave the Logging to the Escalate Gem
74
+ Here is an example that uses the default `log_first: true` so that logging is handled by the `Escalate` gem first:
75
+ ```
76
+ Escalate.on_escalate do |exception, location_message, **context|
77
+ # send exception, location_message, **context to the error reporting service here
78
+ end
79
+ ```
80
+
81
+ #### Callback Uniqueness
82
+ Each callback may be named with the `name:` keyword argument.
83
+ If a callback with the same name has been registered before, it will be overwritten with the new one.
84
+ ```
85
+ Escalate.on_escalate(name: 'abc gem') do |exception, location_message, **context|
86
+ # send exception, location_message, **context to the error reporting service here
87
+ end
88
+ ```
89
+ If not given, the `name:` defaults to the `.source_location` property of the passed-in block.
90
+
91
+ #### Handle the Logging in the `on_escalate` Callback
92
+ Here is an example that handles logging itself with `log_first: false`:
93
+ ```
94
+ Escalate.on_escalate(log_first: false) do |exception, location_message, **context|
95
+ # log here first
96
+ # send exception, location_message, **context to the error reporting service here
97
+ end
98
+ ```
63
99
  ## Development
64
100
 
65
101
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/escalate.rb CHANGED
@@ -9,37 +9,46 @@ require_relative "escalate/mixin"
9
9
  module Escalate
10
10
  class Error < StandardError; end
11
11
 
12
+ LOG_FIRST_INSTANCE_VARIABLE = :@_escalate_log_first
13
+
14
+ @on_escalate_callbacks = {}
15
+
12
16
  class << self
17
+ attr_reader :on_escalate_callbacks
18
+
13
19
  # Logs and escalated an exception
14
20
  #
15
21
  # @param [Exception] exception
16
- # The exception that was raised and needs to be escalated
22
+ # The exception that was rescued and needs to be escalated
17
23
  #
18
- # @param [String] message
19
- # An additional message about what was happening at the time of the exception
24
+ # @param [String] location_message
25
+ # An additional message giving an indication of where in the code this exception was rescued
20
26
  #
21
27
  # @param [Logger] logger
22
28
  # The logger object to use when logging the exception
23
29
  #
24
30
  # @param [Hash] context
25
31
  # Any additional context to be tied to the escalation
26
- def escalate(exception, message, logger, **context)
32
+ def escalate(exception, location_message, logger, **context)
27
33
  ensure_failsafe("Exception rescued while escalating #{exception.inspect}") do
28
- error_message = <<~EOS
29
- [Escalate] #{message} (#{context.inspect})
34
+ if on_escalate_callbacks.none? || on_escalate_callbacks.values.any? { |block| block.instance_variable_get(LOG_FIRST_INSTANCE_VARIABLE) }
35
+ logger_allows_added_context?(logger) or context_string = " (#{context.inspect})"
36
+ error_message = <<~EOS
37
+ [Escalate] #{location_message}#{context_string}
30
38
  #{exception.class.name}: #{exception.message}
31
39
  #{exception.backtrace.join("\n")}
32
- EOS
40
+ EOS
33
41
 
34
- if logger_allows_added_context?(logger)
35
- logger.error(error_message, **context)
36
- else
37
- logger.error(error_message)
42
+ if context_string
43
+ logger.error(error_message)
44
+ else
45
+ logger.error(error_message, **context)
46
+ end
38
47
  end
39
48
 
40
- on_escalate_blocks.each do |block|
49
+ on_escalate_callbacks.values.each do |block|
41
50
  ensure_failsafe("Exception rescued while escalating #{exception.inspect} to #{block.inspect}") do
42
- block.call(exception, message, **context)
51
+ block.call(exception, location_message, **context)
43
52
  end
44
53
  end
45
54
  end
@@ -63,8 +72,8 @@ module Escalate
63
72
 
64
73
  attr_accessor :escalate_logger_block
65
74
 
66
- def escalate(exception, message, **context)
67
- Escalate.escalate(exception, message, escalate_logger, **context)
75
+ def escalate(exception, location_message, **context)
76
+ Escalate.escalate(exception, location_message, escalate_logger, **context)
68
77
  end
69
78
 
70
79
  private
@@ -79,10 +88,21 @@ module Escalate
79
88
  end
80
89
  end
81
90
 
82
- # Registers an escalation callback to be executed when `escalate`
83
- # is invoked.
84
- def on_escalate(&block)
85
- on_escalate_blocks.add(block)
91
+ # Registers an escalation callback to be executed when `escalate` is invoked.
92
+ #
93
+ # @param [boolean] log_first: true
94
+ # whether escalate should log first before escalating, or leave the logging to the escalate block
95
+ # @param [string | Array] name:
96
+ # unique name for this callback block
97
+ # any previously-registered block with the same name will be discarded
98
+ # if not provided, name defaults to `block.source_location`
99
+ def on_escalate(log_first: true, name: nil, &block)
100
+ block.instance_variable_set(LOG_FIRST_INSTANCE_VARIABLE, log_first)
101
+ on_escalate_callbacks[name || block.source_location] = block
102
+ end
103
+
104
+ def clear_on_escalate_callbacks
105
+ on_escalate_callbacks.clear
86
106
  end
87
107
 
88
108
  private
@@ -97,9 +117,5 @@ module Escalate
97
117
  defined?(ContextualLogger::LoggerMixin) &&
98
118
  logger.is_a?(ContextualLogger::LoggerMixin)
99
119
  end
100
-
101
- def on_escalate_blocks
102
- @on_escalate_blocks ||= Set.new
103
- end
104
120
  end
105
121
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Escalate
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: escalate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca Development
8
8
  - Octothorp
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-03 00:00:00.000000000 Z
12
+ date: 2021-03-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -56,7 +56,7 @@ metadata:
56
56
  allowed_push_host: https://rubygems.org
57
57
  homepage_uri: https://github.com/invoca/escalate
58
58
  changelog_uri: https://github.com/invoca/escalate/blob/main/CHANGELOG.md
59
- post_install_message:
59
+ post_install_message:
60
60
  rdoc_options: []
61
61
  require_paths:
62
62
  - lib
@@ -71,9 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
71
  - !ruby/object:Gem::Version
72
72
  version: '0'
73
73
  requirements: []
74
- rubyforge_project:
75
- rubygems_version: 2.6.13
76
- signing_key:
74
+ rubygems_version: 3.1.2
75
+ signing_key:
77
76
  specification_version: 4
78
77
  summary: A simple and lightweight gem to escalate rescued exceptions.
79
78
  test_files: []