escalate 0.1.0.pre.2 → 0.2.0.pre.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a3e33eb654953f4c511b2207a89df47f6db4865c
4
- data.tar.gz: 4b245b1e402c24a933eae6ba6ac6eb9be362e5f1
2
+ SHA256:
3
+ metadata.gz: fc6bd15f68b37624979732a8c7b2c55d323c407c397c01ac59d8b8df54e90504
4
+ data.tar.gz: 144d6a67f62d9ca4ce7d740a26285dae283372450fd1149b74da59ab5411c982
5
5
  SHA512:
6
- metadata.gz: 28a1ecb9c22129c0b68c62ac6c5bd00eb5b41580bae1763dfdc9e0d9e732dfd22b7acc37ec84f353d4a3f7f35c18334ae92a78a5677c5e9e6453c4ccfb074767
7
- data.tar.gz: dc2271ab38903b2c8f874adc0b21f26c3851a759f5ed1db34482d447573d3d8f13d8b8d1b5565b9106b73bde766dee65260aeb6c645d402b9326371536d3dce0
6
+ metadata.gz: 1490795a292d531715525872a8bc06d1d27330222a24a436ad22ea62aa1d5fbc2e80b8a36b382cec86ef6281173bd5bddcbaffe9aa35c7f5bc641f6ac3611380
7
+ data.tar.gz: e2e7f3d6fd1be1e679bc6286c7fb892cef56fe64b57bbd55fedf649aa681c6e1d26f2f4f4aadbe8db3d0c327a378da65c46baee8fd20d137a6d6f1e2d40257d0
data/CHANGELOG.md CHANGED
@@ -4,6 +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.1.0] - Unreleased
7
+ ## [0.2.0] - Unreleased
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`.
8
12
 
13
+ ## [0.1.0] - 2021-02-03
14
+ ### Added
15
+ - Added `Escalate.mixin` interface for mixing in `Escalate` with your module for easy escalation of rescued exceptions
16
+ - Added `escalate` method for escalating rescued exceptions with default behavior of logging to `STDERR`
17
+ - Added `Escalate.on_escalate` for registering escalation callbacks like `Honeybadger` or `Sentry`
18
+
19
+ [0.2.0]: https://github.com/Invoca/escalate/compare/v0.1.0...v0.2.0
9
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.pre.2)
4
+ escalate (0.2.0.pre.4)
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
@@ -57,16 +66,43 @@ module Escalate
57
66
 
58
67
  Module.new do
59
68
  def self.included(base)
60
- base.extend Escalate::Mixin
69
+ base.extend self
61
70
  base.escalate_logger_block = Thread.current[:escalate_logger_block] || -> { base.try(:logger) }
62
71
  end
72
+
73
+ attr_accessor :escalate_logger_block
74
+
75
+ def escalate(exception, location_message, **context)
76
+ Escalate.escalate(exception, location_message, escalate_logger, **context)
77
+ end
78
+
79
+ private
80
+
81
+ def escalate_logger
82
+ escalate_logger_block&.call || default_escalate_logger
83
+ end
84
+
85
+ def default_escalate_logger
86
+ @default_escalate_logger ||= Logger.new(STDERR)
87
+ end
63
88
  end
64
89
  end
65
90
 
66
- # Registers an escalation callback to be executed when `escalate`
67
- # is invoked.
68
- def on_escalate(&block)
69
- 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
70
106
  end
71
107
 
72
108
  private
@@ -81,9 +117,5 @@ module Escalate
81
117
  defined?(ContextualLogger::LoggerMixin) &&
82
118
  logger.is_a?(ContextualLogger::LoggerMixin)
83
119
  end
84
-
85
- def on_escalate_blocks
86
- @on_escalate_blocks ||= Set.new
87
- end
88
120
  end
89
121
  end
@@ -4,24 +4,8 @@ module Escalate
4
4
  module Mixin
5
5
  class << self
6
6
  def included(base)
7
- raise 'instead of `include Escalator::Mixin`, you should `include Escalator.mixin`'
7
+ raise 'instead of `include Escalate::Mixin`, you should `include Escalate.mixin`'
8
8
  end
9
9
  end
10
-
11
- attr_accessor :escalate_logger_block
12
-
13
- def escalate(exception, message, **context)
14
- Escalate.escalate(exception, message, escalate_logger, **context)
15
- end
16
-
17
- private
18
-
19
- def escalate_logger
20
- escalate_logger_block.try(:call) || default_escalate_logger
21
- end
22
-
23
- def default_escalate_logger
24
- @default_escalate_logger ||= Logger.new(STDERR)
25
- end
26
10
  end
27
11
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Escalate
4
- VERSION = "0.1.0.pre.2"
4
+ VERSION = "0.2.0.pre.4"
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.pre.2
4
+ version: 0.2.0.pre.4
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-02 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: 1.3.1
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: []