escalate 0.1.0.pre.1 → 0.2.0.pre.3

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: bb743da8ea57e11a7bfa80d653548239e0b760ab
4
- data.tar.gz: 36555a0ba6f8bca3f821c5b0044739e26762cc23
2
+ SHA256:
3
+ metadata.gz: 67b615521fd3e15a59bb8401486496175afa19be36a98c415d9eccf52dd0815f
4
+ data.tar.gz: 951d5afc0052cde73fca383e23dc38aa63e759fce7f4863b2093e9bf9b2463b4
5
5
  SHA512:
6
- metadata.gz: 7c735aa3214359068d14e0fd981c64c62e14896d73965d467d5b28ebaa3d2bf300ae9037164d3a4a7e5a6b4a77439a8a5137dd5d3b7b51eda27cef0ec7a57a60
7
- data.tar.gz: a3899dc985f47f6e87d609b5fdf85443b9278ca100b40e5e41e4be641c8aa6116850dc80a4426f779c34e741b5b0893c9032e3c2b59974a9b802da0bcc8629bd
6
+ metadata.gz: 7979594ec79d527e123efb08114d602ab11446d8e822a9a716b582150d7e0f4b97840443974270177d861d874fbf4544f7e14eb8bd5e98e66acc86d49b51e19a
7
+ data.tar.gz: 2ab19d1367350559290fb9603e7af73934fcf1085121bf5a1cebe03059d450d19e53f76dc9947d92fac8a06f2a08fc0bb6ed12d0135a1e09617c87c6835dc158
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 CHANGED
@@ -5,6 +5,8 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in escalate.gemspec
6
6
  gemspec
7
7
 
8
+ gem "contextual_logger"
9
+
8
10
  gem "pry"
9
11
  gem "pry-byebug"
10
12
 
data/Gemfile.lock CHANGED
@@ -1,9 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- escalate (0.1.0.pre.1)
4
+ escalate (0.2.0.pre.3)
5
5
  activesupport
6
- contextual_logger
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
@@ -50,9 +49,11 @@ GEM
50
49
  thread_safe (~> 0.1)
51
50
 
52
51
  PLATFORMS
52
+ ruby
53
53
  x86_64-darwin-19
54
54
 
55
55
  DEPENDENCIES
56
+ contextual_logger
56
57
  escalate!
57
58
  pry
58
59
  pry-byebug
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Escalate
2
2
 
3
- A simple and lightweight gem to help with escalating errors
3
+ A simple and lightweight gem to escalate rescued exceptions. This implementation
4
+ is an abstract interface that can be used on it's own, or attached to more concrete
5
+ implementations like Honeybadger, Airbrake, or Sentry in order to not just log
6
+ exceptions in an easy to parse way, but also escalate the appropriate information
7
+ to third party systems.
4
8
 
5
9
  ## Installation
6
10
 
@@ -30,7 +34,7 @@ module SomeGem
30
34
  end
31
35
  ```
32
36
 
33
- This will expose the `Escalate#ex_escalate` method within your gem to be used instead
37
+ This will expose the `Escalate#escalate` method within your gem to be used instead
34
38
  of using `logger.error`.
35
39
 
36
40
  ```ruby
@@ -54,8 +58,34 @@ end
54
58
  When `SomeGem.escalate` above is triggered, it will use the logger returned by `SomeGem.logger` or
55
59
  default to a `STDERR` logger and do the following:
56
60
 
57
- 1. Log an error containing the exception and any additional information about the current environment that is specified
58
- 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
+ #### Handle the Logging in the `on_escalate` Callback
82
+ Here is an example that handles logging itself with `log_first: false`:
83
+ ```
84
+ Escalate.on_escalate(log_first: false) do |exception, location_message, **context|
85
+ # log here first
86
+ # send exception, location_message, **context to the error reporting service here
87
+ end
88
+ ```
59
89
  ## Development
60
90
 
61
91
  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/escalate.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Invoca Development", "Octothorp"]
9
9
  spec.email = ["development@invoca.com", "octothorp@invoca.com"]
10
10
 
11
- spec.summary = "Simple gem for abstracting log escalations"
12
- spec.description = "Simple gem for abstracting log escalations"
11
+ spec.summary = "A simple and lightweight gem to escalate rescued exceptions."
12
+ spec.description = "A simple and lightweight gem to escalate rescued exceptions."
13
13
  spec.homepage = "https://github.com/invoca/escalate"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
15
 
@@ -28,5 +28,4 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
 
30
30
  spec.add_dependency "activesupport"
31
- spec.add_dependency "contextual_logger"
32
31
  end
data/lib/escalate.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support"
4
4
  require "active_support/core_ext"
5
- require "contextual_logger"
6
5
 
7
6
  require_relative "escalate/version"
8
7
  require_relative "escalate/mixin"
@@ -10,43 +9,53 @@ require_relative "escalate/mixin"
10
9
  module Escalate
11
10
  class Error < StandardError; end
12
11
 
12
+ LOG_FIRST_INSTANCE_VARIABLE = :@_escalate_log_first
13
+
14
+ @on_escalate_callbacks = Set.new
15
+
13
16
  class << self
17
+ attr_reader :on_escalate_callbacks
18
+
14
19
  # Logs and escalated an exception
15
20
  #
16
21
  # @param [Exception] exception
17
- # The exception that was raised and needs to be escalated
22
+ # The exception that was rescued and needs to be escalated
18
23
  #
19
- # @param [String] message
20
- # 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
21
26
  #
22
27
  # @param [Logger] logger
23
28
  # The logger object to use when logging the exception
24
29
  #
25
30
  # @param [Hash] context
26
31
  # Any additional context to be tied to the escalation
27
- def escalate(exception, message, logger, **context)
28
- error_message = <<~EOS
29
- [Escalate] #{message} (#{context.inspect})
30
- #{exception.class.name}: #{exception.message}
31
- #{exception.backtrace.join("\n")}
32
- EOS
33
-
34
- if logger.is_a?(ContextualLogger::LoggerMixin)
35
- logger.error(error_message, **context)
36
- else
37
- logger.error(error_message)
38
- end
32
+ def escalate(exception, location_message, logger, **context)
33
+ ensure_failsafe("Exception rescued while escalating #{exception.inspect}") do
34
+ if on_escalate_callbacks.none? || on_escalate_callbacks.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}
38
+ #{exception.class.name}: #{exception.message}
39
+ #{exception.backtrace.join("\n")}
40
+ EOS
41
+
42
+ if context_string
43
+ logger.error(error_message)
44
+ else
45
+ logger.error(error_message, **context)
46
+ end
47
+ end
39
48
 
40
- on_escalate_blocks.each do |block|
41
- block.call(exception, message, **context)
49
+ on_escalate_callbacks.each do |block|
50
+ ensure_failsafe("Exception rescued while escalating #{exception.inspect} to #{block.inspect}") do
51
+ block.call(exception, location_message, **context)
52
+ end
53
+ end
42
54
  end
43
- rescue Exception => ex
44
- STDERR.puts("[ExEscalator] Exception rescued while escalating #{exception.inspect}:" \
45
- "#{ex.class.name}: #{ex.message}")
46
55
  end
47
56
 
48
57
  # Returns a module to be mixed into a class or module exposing
49
- # the ex_escalate method to be used for escalating and logging
58
+ # the escalate method to be used for escalating and logging
50
59
  # exceptions.
51
60
  #
52
61
  # @param [Proc] logger_block
@@ -57,22 +66,53 @@ 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 `ex_escalate`
91
+ # Registers an escalation callback to be executed when `escalate`
67
92
  # is invoked.
68
- def on_escalate(&block)
69
- on_escalate_blocks.add(block)
93
+ #
94
+ # @param [boolean] log_first: true
95
+ # whether escalate should log first before escalating, or leave the logging to the escalate block
96
+ def on_escalate(log_first: true, &block)
97
+ block.instance_variable_set(LOG_FIRST_INSTANCE_VARIABLE, log_first)
98
+ on_escalate_callbacks.add(block)
99
+ end
100
+
101
+ def clear_on_escalate_callbacks
102
+ on_escalate_callbacks.clear
70
103
  end
71
104
 
72
105
  private
73
106
 
74
- def on_escalate_blocks
75
- @on_escalate_blocks ||= Set.new
107
+ def ensure_failsafe(message)
108
+ yield
109
+ rescue Exception => ex
110
+ STDERR.puts("[Escalator] #{message}: #{ex.class.name}: #{ex.message}")
111
+ end
112
+
113
+ def logger_allows_added_context?(logger)
114
+ defined?(ContextualLogger::LoggerMixin) &&
115
+ logger.is_a?(ContextualLogger::LoggerMixin)
76
116
  end
77
117
  end
78
118
  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 ExEscalator::Mixin`, you should `include ExEscalator.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 ex_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.1"
4
+ VERSION = "0.2.0.pre.3"
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.1
4
+ version: 0.2.0.pre.3
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-01 00:00:00.000000000 Z
12
+ date: 2021-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -25,21 +25,7 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: contextual_logger
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :runtime
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
- description: Simple gem for abstracting log escalations
28
+ description: A simple and lightweight gem to escalate rescued exceptions.
43
29
  email:
44
30
  - development@invoca.com
45
31
  - octothorp@invoca.com
@@ -70,7 +56,7 @@ metadata:
70
56
  allowed_push_host: https://rubygems.org
71
57
  homepage_uri: https://github.com/invoca/escalate
72
58
  changelog_uri: https://github.com/invoca/escalate/blob/main/CHANGELOG.md
73
- post_install_message:
59
+ post_install_message:
74
60
  rdoc_options: []
75
61
  require_paths:
76
62
  - lib
@@ -85,9 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
71
  - !ruby/object:Gem::Version
86
72
  version: 1.3.1
87
73
  requirements: []
88
- rubyforge_project:
89
- rubygems_version: 2.6.13
90
- signing_key:
74
+ rubygems_version: 3.1.2
75
+ signing_key:
91
76
  specification_version: 4
92
- summary: Simple gem for abstracting log escalations
77
+ summary: A simple and lightweight gem to escalate rescued exceptions.
93
78
  test_files: []