exception_handling 2.15.0 → 2.17.0.pre.tstarck.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/pipeline.yml +6 -10
- data/CHANGELOG.md +18 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +111 -88
- data/README.md +83 -18
- data/exception_handling.gemspec +2 -0
- data/lib/exception_handling/version.rb +1 -1
- data/lib/exception_handling.rb +63 -1
- data/spec/spec_helper.rb +17 -8
- data/spec/unit/exception_handling_spec.rb +164 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4074e67f0ede6cb73665a058c3cd09b02e7518e0fb4d0860d0ce4378aa4023b6
|
4
|
+
data.tar.gz: e2d3726622a44753b679de1f645d3bbf40780c8d8829f46e7803661a7f583100
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa6b1574ba37ac1aee58bfb3bbfc9c15a083d255fa031c1b61dc205dad06c7a1bbee62c6fc6a1e5d24d341f88fa01806cef133cba8beb9f1ad34f0278dbe2848
|
7
|
+
data.tar.gz: e1f4e2e4dc2ff78d948a31eabc2091d7c853f117f2f03c300ee90b4d2b362d59dfe89590d5ae3f8b2949d40e40a09d60ed418786c4dbee9180fb188b590296b9
|
@@ -8,25 +8,21 @@ jobs:
|
|
8
8
|
strategy:
|
9
9
|
fail-fast: false
|
10
10
|
matrix:
|
11
|
-
ruby: [2.
|
11
|
+
ruby: [2.7, '3.0', 3.1, 3.2, 3.3]
|
12
12
|
gemfile:
|
13
13
|
- Gemfile
|
14
14
|
- gemfiles/rails_5.gemfile
|
15
15
|
- gemfiles/rails_6.gemfile
|
16
16
|
- gemfiles/rails_7.gemfile
|
17
17
|
exclude:
|
18
|
-
- gemfile: Gemfile
|
19
|
-
ruby: 2.5
|
20
|
-
- gemfile: gemfiles/rails_7.gemfile
|
21
|
-
ruby: 2.5
|
22
|
-
- gemfile: Gemfile
|
23
|
-
ruby: 2.6
|
24
|
-
- gemfile: gemfiles/rails_7.gemfile
|
25
|
-
ruby: 2.6
|
26
18
|
- gemfile: gemfiles/rails_5.gemfile
|
27
19
|
ruby: '3.0'
|
28
20
|
- gemfile: gemfiles/rails_5.gemfile
|
29
21
|
ruby: 3.1
|
22
|
+
- gemfile: gemfiles/rails_5.gemfile
|
23
|
+
ruby: 3.2
|
24
|
+
- gemfile: gemfiles/rails_5.gemfile
|
25
|
+
ruby: 3.3
|
30
26
|
env:
|
31
27
|
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
32
28
|
steps:
|
@@ -34,7 +30,7 @@ jobs:
|
|
34
30
|
- uses: ruby/setup-ruby@v1
|
35
31
|
with:
|
36
32
|
ruby-version: ${{ matrix.ruby }}
|
37
|
-
bundler: 2.
|
33
|
+
bundler: 2.3.26
|
38
34
|
bundler-cache: true
|
39
35
|
- name: Unit tests
|
40
36
|
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,23 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
4
4
|
|
5
5
|
**Note:** this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [2.17.0] - Unreleased
|
8
|
+
### Added
|
9
|
+
- Add interface for tagging exceptions sent to honeybadger with values from the log context.
|
10
|
+
- `ExceptionHandling.add_honeybadger_tag_from_log_context`
|
11
|
+
- Added Ruby 3.2 and 3.3 to the CI test matrix
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
- Require ruby version 2.7 or greater
|
15
|
+
|
16
|
+
### Removed
|
17
|
+
- Removed Ruby versions 2.5 and 2.6 from the CI test matrix.
|
18
|
+
|
19
|
+
|
20
|
+
## [2.16.0] - 2023-05-01
|
21
|
+
### Added
|
22
|
+
- Add interface for automatically adding honeybadger tags `ExceptionHandling.honeybadger_auto_tagger=`
|
23
|
+
|
7
24
|
## [2.15.0] - 2023-03-07
|
8
25
|
### Added
|
9
26
|
- Added support for ActionMailer 7.x
|
@@ -109,6 +126,7 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
109
126
|
### Changed
|
110
127
|
- No longer depends on hobo_support. Uses invoca-utils 0.3 instead.
|
111
128
|
|
129
|
+
[2.16.0]: https://github.com/Invoca/exception_handling/compare/v2.15.0...v2.16.0
|
112
130
|
[2.15.0]: https://github.com/Invoca/exception_handling/compare/v2.14.0...v2.15.0
|
113
131
|
[2.14.0]: https://github.com/Invoca/exception_handling/compare/v2.13.0...v2.14.0
|
114
132
|
[2.13.0]: https://github.com/Invoca/exception_handling/compare/v2.12.0...v2.13.0
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
exception_handling (2.
|
4
|
+
exception_handling (2.17.0.pre.tstarck.1)
|
5
5
|
actionmailer (>= 5.2)
|
6
6
|
actionpack (>= 5.2)
|
7
7
|
activesupport (>= 5.2)
|
@@ -15,135 +15,158 @@ PATH
|
|
15
15
|
GEM
|
16
16
|
remote: https://rubygems.org/
|
17
17
|
specs:
|
18
|
-
actionmailer (6.
|
19
|
-
actionpack (= 6.
|
20
|
-
actionview (= 6.
|
21
|
-
activejob (= 6.
|
18
|
+
actionmailer (6.1.7.6)
|
19
|
+
actionpack (= 6.1.7.6)
|
20
|
+
actionview (= 6.1.7.6)
|
21
|
+
activejob (= 6.1.7.6)
|
22
|
+
activesupport (= 6.1.7.6)
|
22
23
|
mail (~> 2.5, >= 2.5.4)
|
23
24
|
rails-dom-testing (~> 2.0)
|
24
|
-
actionpack (6.
|
25
|
-
actionview (= 6.
|
26
|
-
activesupport (= 6.
|
27
|
-
rack (~> 2.0, >= 2.0.
|
25
|
+
actionpack (6.1.7.6)
|
26
|
+
actionview (= 6.1.7.6)
|
27
|
+
activesupport (= 6.1.7.6)
|
28
|
+
rack (~> 2.0, >= 2.0.9)
|
28
29
|
rack-test (>= 0.6.3)
|
29
30
|
rails-dom-testing (~> 2.0)
|
30
31
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
31
|
-
actionview (6.
|
32
|
-
activesupport (= 6.
|
32
|
+
actionview (6.1.7.6)
|
33
|
+
activesupport (= 6.1.7.6)
|
33
34
|
builder (~> 3.1)
|
34
35
|
erubi (~> 1.4)
|
35
36
|
rails-dom-testing (~> 2.0)
|
36
37
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
37
|
-
activejob (6.
|
38
|
-
activesupport (= 6.
|
38
|
+
activejob (6.1.7.6)
|
39
|
+
activesupport (= 6.1.7.6)
|
39
40
|
globalid (>= 0.3.6)
|
40
|
-
activesupport (6.
|
41
|
+
activesupport (6.1.7.6)
|
41
42
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
42
|
-
i18n (>=
|
43
|
-
minitest (
|
44
|
-
tzinfo (~>
|
45
|
-
zeitwerk (~> 2.
|
46
|
-
appraisal (2.
|
43
|
+
i18n (>= 1.6, < 2)
|
44
|
+
minitest (>= 5.1)
|
45
|
+
tzinfo (~> 2.0)
|
46
|
+
zeitwerk (~> 2.3)
|
47
|
+
appraisal (2.5.0)
|
47
48
|
bundler
|
48
49
|
rake
|
49
50
|
thor (>= 0.14.0)
|
50
|
-
ast (2.4.
|
51
|
+
ast (2.4.2)
|
51
52
|
builder (3.2.4)
|
52
53
|
byebug (11.1.3)
|
53
|
-
coderay (1.1.
|
54
|
-
concurrent-ruby (1.
|
55
|
-
contextual_logger (1.
|
56
|
-
activesupport
|
54
|
+
coderay (1.1.3)
|
55
|
+
concurrent-ruby (1.2.3)
|
56
|
+
contextual_logger (1.3.0)
|
57
|
+
activesupport (< 7.1)
|
57
58
|
json
|
58
59
|
crass (1.0.6)
|
59
|
-
|
60
|
-
|
60
|
+
date (3.3.4)
|
61
|
+
diff-lcs (1.5.1)
|
62
|
+
erubi (1.12.0)
|
61
63
|
escalate (0.3.0)
|
62
64
|
eventmachine (1.2.7)
|
63
|
-
globalid (1.
|
64
|
-
activesupport (>=
|
65
|
-
honeybadger (4.
|
66
|
-
i18n (1.
|
65
|
+
globalid (1.2.1)
|
66
|
+
activesupport (>= 6.1)
|
67
|
+
honeybadger (4.12.2)
|
68
|
+
i18n (1.14.1)
|
67
69
|
concurrent-ruby (~> 1.0)
|
68
70
|
invoca-utils (0.5.1)
|
69
71
|
activesupport (>= 5.0)
|
70
|
-
|
71
|
-
|
72
|
-
loofah (2.
|
72
|
+
json (2.7.1)
|
73
|
+
language_server-protocol (3.17.0.3)
|
74
|
+
loofah (2.22.0)
|
73
75
|
crass (~> 1.0.2)
|
74
|
-
nokogiri (>= 1.
|
75
|
-
mail (2.
|
76
|
+
nokogiri (>= 1.12.0)
|
77
|
+
mail (2.8.1)
|
76
78
|
mini_mime (>= 0.1.1)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
net-imap
|
80
|
+
net-pop
|
81
|
+
net-smtp
|
82
|
+
method_source (1.0.0)
|
83
|
+
mini_mime (1.1.5)
|
84
|
+
mini_portile2 (2.8.5)
|
85
|
+
minitest (5.22.2)
|
86
|
+
net-imap (0.4.10)
|
87
|
+
date
|
88
|
+
net-protocol
|
89
|
+
net-pop (0.1.2)
|
90
|
+
net-protocol
|
91
|
+
net-protocol (0.2.2)
|
82
92
|
timeout
|
83
|
-
net-smtp (0.
|
93
|
+
net-smtp (0.4.0.1)
|
84
94
|
net-protocol
|
85
|
-
nokogiri (1.
|
86
|
-
mini_portile2 (~> 2.8.
|
95
|
+
nokogiri (1.15.5)
|
96
|
+
mini_portile2 (~> 2.8.2)
|
87
97
|
racc (~> 1.4)
|
88
|
-
parallel (1.
|
89
|
-
parser (
|
90
|
-
ast (~> 2.4.
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
98
|
+
parallel (1.24.0)
|
99
|
+
parser (3.3.0.5)
|
100
|
+
ast (~> 2.4.1)
|
101
|
+
racc
|
102
|
+
power_assert (2.0.3)
|
103
|
+
pry (0.14.2)
|
104
|
+
coderay (~> 1.1)
|
105
|
+
method_source (~> 1.0)
|
106
|
+
pry-byebug (3.10.1)
|
96
107
|
byebug (~> 11.0)
|
97
|
-
pry (
|
108
|
+
pry (>= 0.13, < 0.15)
|
98
109
|
psych (3.3.4)
|
99
|
-
racc (1.
|
100
|
-
rack (2.2.
|
101
|
-
rack-test (
|
102
|
-
rack (>= 1.
|
103
|
-
rails-dom-testing (2.0
|
104
|
-
activesupport (>=
|
110
|
+
racc (1.7.3)
|
111
|
+
rack (2.2.8)
|
112
|
+
rack-test (2.1.0)
|
113
|
+
rack (>= 1.3)
|
114
|
+
rails-dom-testing (2.2.0)
|
115
|
+
activesupport (>= 5.0.0)
|
116
|
+
minitest
|
105
117
|
nokogiri (>= 1.6)
|
106
|
-
rails-html-sanitizer (1.
|
107
|
-
loofah (~> 2.
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
rspec-
|
116
|
-
|
118
|
+
rails-html-sanitizer (1.6.0)
|
119
|
+
loofah (~> 2.21)
|
120
|
+
nokogiri (~> 1.14)
|
121
|
+
rainbow (3.1.1)
|
122
|
+
rake (13.1.0)
|
123
|
+
regexp_parser (2.9.0)
|
124
|
+
rexml (3.2.6)
|
125
|
+
rspec (3.13.0)
|
126
|
+
rspec-core (~> 3.13.0)
|
127
|
+
rspec-expectations (~> 3.13.0)
|
128
|
+
rspec-mocks (~> 3.13.0)
|
129
|
+
rspec-core (3.13.0)
|
130
|
+
rspec-support (~> 3.13.0)
|
131
|
+
rspec-expectations (3.13.0)
|
117
132
|
diff-lcs (>= 1.2.0, < 2.0)
|
118
|
-
rspec-support (~> 3.
|
119
|
-
rspec-mocks (3.
|
133
|
+
rspec-support (~> 3.13.0)
|
134
|
+
rspec-mocks (3.13.0)
|
120
135
|
diff-lcs (>= 1.2.0, < 2.0)
|
121
|
-
rspec-support (~> 3.
|
122
|
-
rspec-support (3.
|
123
|
-
rspec_junit_formatter (0.
|
136
|
+
rspec-support (~> 3.13.0)
|
137
|
+
rspec-support (3.13.0)
|
138
|
+
rspec_junit_formatter (0.6.0)
|
124
139
|
rspec-core (>= 2, < 4, != 2.12.0)
|
125
|
-
rubocop (
|
126
|
-
|
140
|
+
rubocop (1.60.2)
|
141
|
+
json (~> 2.3)
|
142
|
+
language_server-protocol (>= 3.17.0)
|
127
143
|
parallel (~> 1.10)
|
128
|
-
parser (>= 2
|
144
|
+
parser (>= 3.3.0.2)
|
129
145
|
rainbow (>= 2.2.2, < 4.0)
|
146
|
+
regexp_parser (>= 1.8, < 3.0)
|
147
|
+
rexml (>= 3.2.5, < 4.0)
|
148
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
130
149
|
ruby-progressbar (~> 1.7)
|
131
|
-
unicode-display_width (>=
|
132
|
-
|
133
|
-
|
150
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
151
|
+
rubocop-ast (1.30.0)
|
152
|
+
parser (>= 3.2.1.0)
|
153
|
+
ruby-progressbar (1.13.0)
|
154
|
+
test-unit (3.6.1)
|
134
155
|
power_assert
|
135
|
-
thor (1.0
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
zeitwerk (2.5.4)
|
156
|
+
thor (1.3.0)
|
157
|
+
timeout (0.4.1)
|
158
|
+
tzinfo (2.0.6)
|
159
|
+
concurrent-ruby (~> 1.0)
|
160
|
+
unicode-display_width (2.5.0)
|
161
|
+
zeitwerk (2.6.13)
|
142
162
|
|
143
163
|
PLATFORMS
|
144
164
|
ruby
|
145
165
|
|
146
166
|
DEPENDENCIES
|
167
|
+
actionmailer (~> 6.0)
|
168
|
+
actionpack (~> 6.0)
|
169
|
+
activesupport (~> 6.0)
|
147
170
|
appraisal (~> 2.2)
|
148
171
|
exception_handling!
|
149
172
|
honeybadger (~> 4.11)
|
@@ -156,4 +179,4 @@ DEPENDENCIES
|
|
156
179
|
test-unit
|
157
180
|
|
158
181
|
BUNDLED WITH
|
159
|
-
2.
|
182
|
+
2.3.22
|
data/README.md
CHANGED
@@ -25,24 +25,27 @@ Or install it yourself as:
|
|
25
25
|
Add some code to initialize the settings in your application.
|
26
26
|
For example:
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
```ruby
|
29
|
+
require "exception_handling"
|
30
|
+
|
31
|
+
# required
|
32
|
+
ExceptionHandling.server_name = Cluster['server_name']
|
33
|
+
ExceptionHandling.sender_address = %("Exceptions" <exceptions@example.com>)
|
34
|
+
ExceptionHandling.exception_recipients = ['exceptions@example.com']
|
35
|
+
ExceptionHandling.logger = Rails.logger
|
36
|
+
|
37
|
+
# optional
|
38
|
+
ExceptionHandling.escalation_recipients = ['escalation@example.com']
|
39
|
+
ExceptionHandling.filter_list_filename = "#{Rails.root}/config/exception_filters.yml"
|
40
|
+
ExceptionHandling.email_environment = Rails.env
|
41
|
+
ExceptionHandling.eventmachine_safe = false
|
42
|
+
ExceptionHandling.eventmachine_synchrony = false
|
43
|
+
ExceptionHandling.sensu_host = "127.0.0.1"
|
44
|
+
ExceptionHandling.sensu_port = 3030
|
45
|
+
ExceptionHandling.sensu_prefix = ""
|
46
|
+
ExceptionHandling.honeybadger_auto_tagger = ->(exception) { [] } # See "Automatically Tagging Exceptions" section below for examples
|
47
|
+
ExceptionHandling.add_honeybadger_tag_from_log_context("tag-name", path: ["path", "in", "log", "context"])
|
48
|
+
```
|
46
49
|
|
47
50
|
## Usage
|
48
51
|
|
@@ -62,6 +65,68 @@ Then call any method available in the `ExceptionHandling::Methods` mixin:
|
|
62
65
|
flash.now['error'] = "A specific error occurred. Support has been notified."
|
63
66
|
end
|
64
67
|
|
68
|
+
### Tagging Exceptions in Honeybadger
|
69
|
+
|
70
|
+
⚠️ Honeybadger differentiates tags by spaces and/or commas, so you should **not** include spaces or commas in your tags.
|
71
|
+
|
72
|
+
⚠️ Tags are case-sensitive.
|
73
|
+
|
74
|
+
#### Manually Tagging Exceptions
|
75
|
+
|
76
|
+
Add `:honeybadger_tags` to your `log_context` usage with an array of strings.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
log_error(ex, "A specific error occurred.", honeybadger_tags: ["critical", "sequoia"])
|
80
|
+
```
|
81
|
+
|
82
|
+
**Note**: Manual tags will be merged with any automatic tags.
|
83
|
+
|
84
|
+
#### Automatically Tagging Exceptions via Proc (`honeybadger_auto_tagger=`)
|
85
|
+
|
86
|
+
Configure exception handling so that you can automatically apply multiple tags to exceptions sent to honeybadger.
|
87
|
+
|
88
|
+
The Proc must accept an `exception` argument that will be the exception in question and must always return an array of strings (the array can be empty).
|
89
|
+
|
90
|
+
Example to enable auto-tagging:
|
91
|
+
```ruby
|
92
|
+
ExceptionHandling.honeybadger_auto_tagger = ->(exception) do
|
93
|
+
exception.message.match?(/fire/) ? ["high-urgency", "danger"] : ["low-urgency"]
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
Example to disable auto-tagging:
|
98
|
+
```ruby
|
99
|
+
ExceptionHandling.honeybadger_auto_tagger = nil
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Automatically Tagging Exceptions from Log Context (`add_honeybadger_tag_from_log_context`)
|
103
|
+
|
104
|
+
Add a tag to exceptions sent to honeybadger based on a value in the log context.
|
105
|
+
|
106
|
+
To configure this, use the `add_honeybadger_tag_from_log_context` method.
|
107
|
+
```ruby
|
108
|
+
ExceptionHandling.add_honeybadger_tag_from_log_context("kubernetes_context", path: ["kubernetes", "context"])
|
109
|
+
```
|
110
|
+
|
111
|
+
This will add a tag to the exception if the log context contains a value at the specified path: "kubernetes" => { "context" => "value" }.
|
112
|
+
|
113
|
+
For example:
|
114
|
+
```ruby
|
115
|
+
ExceptionHandling.logger.with_context("kubernetes" => { "context" => "local" }) do
|
116
|
+
log_error(ex, "A specific error occurred.")
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
This will add the following tag to the exception sent to honeybadger:
|
121
|
+
```
|
122
|
+
kubernetes_context:local
|
123
|
+
```
|
124
|
+
|
125
|
+
To clear all automated tagging from the log context, use the `clear_honeybadger_tags_from_log_context` method.
|
126
|
+
```ruby
|
127
|
+
ExceptionHandling.clear_honeybadger_tags_from_log_context
|
128
|
+
```
|
129
|
+
|
65
130
|
## Custom Hooks
|
66
131
|
|
67
132
|
### custom_data_hook
|
data/exception_handling.gemspec
CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
"allowed_push_host" => "https://rubygems.org"
|
21
21
|
}
|
22
22
|
|
23
|
+
spec.required_ruby_version = '>= 2.7.0'
|
24
|
+
|
23
25
|
spec.add_dependency 'actionmailer', '>= 5.2'
|
24
26
|
spec.add_dependency 'actionpack', '>= 5.2'
|
25
27
|
spec.add_dependency 'activesupport', '>= 5.2'
|
data/lib/exception_handling.rb
CHANGED
@@ -110,10 +110,12 @@ module ExceptionHandling # never included
|
|
110
110
|
attr_accessor :sensu_host
|
111
111
|
attr_accessor :sensu_port
|
112
112
|
attr_accessor :sensu_prefix
|
113
|
+
attr_reader :honeybadger_log_context_tags
|
113
114
|
|
114
115
|
attr_reader :filter_list_filename
|
115
116
|
attr_reader :eventmachine_safe
|
116
117
|
attr_reader :eventmachine_synchrony
|
118
|
+
attr_reader :honeybadger_auto_tagger
|
117
119
|
|
118
120
|
@filter_list_filename = "./config/exception_filters.yml"
|
119
121
|
@email_environment = ""
|
@@ -154,6 +156,30 @@ module ExceptionHandling # never included
|
|
154
156
|
@exception_catalog ||= ExceptionCatalog.new(@filter_list_filename)
|
155
157
|
end
|
156
158
|
|
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
|
+
|
157
183
|
#
|
158
184
|
# internal settings (don't set directly)
|
159
185
|
#
|
@@ -270,9 +296,10 @@ module ExceptionHandling # never included
|
|
270
296
|
def send_exception_to_honeybadger(exception_info)
|
271
297
|
exception = exception_info.exception
|
272
298
|
exception_description = exception_info.exception_description
|
299
|
+
|
273
300
|
# Note: Both commas and spaces are treated as delimiters for the :tags string. Space-delimiters are not officially documented.
|
274
301
|
# https://github.com/honeybadger-io/honeybadger-ruby/pull/422
|
275
|
-
tags = exception_info.
|
302
|
+
tags = tags_for_honeybadger(exception_info).join(' ')
|
276
303
|
response = Honeybadger.notify(error_class: exception_description ? exception_description.filter_name : exception.class.name,
|
277
304
|
error_message: exception.message.to_s,
|
278
305
|
exception: exception,
|
@@ -434,6 +461,41 @@ module ExceptionHandling # never included
|
|
434
461
|
|
435
462
|
private
|
436
463
|
|
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
|
+
|
437
499
|
def execute_custom_log_error_callback(exception_data, exception, treat_like_warning, external_notification_results)
|
438
500
|
if ExceptionHandling.post_log_error_hook
|
439
501
|
honeybadger_status = external_notification_results[:honeybadger_status] || :skipped
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,7 @@ require 'rspec/mocks'
|
|
5
5
|
require 'rspec_junit_formatter'
|
6
6
|
|
7
7
|
require 'pry'
|
8
|
+
require 'pry-byebug'
|
8
9
|
require 'honeybadger'
|
9
10
|
require 'contextual_logger'
|
10
11
|
|
@@ -22,20 +23,28 @@ class LoggerStub
|
|
22
23
|
clear
|
23
24
|
end
|
24
25
|
|
25
|
-
def debug(message, log_context
|
26
|
-
|
26
|
+
def debug(message, **log_context)
|
27
|
+
super.tap do
|
28
|
+
logged << { message: message, context: log_context, severity: 'DEBUG' }
|
29
|
+
end
|
27
30
|
end
|
28
31
|
|
29
|
-
def info(message, log_context
|
30
|
-
|
32
|
+
def info(message, **log_context)
|
33
|
+
super.tap do
|
34
|
+
logged << { message: message, context: log_context, severity: 'INFO' }
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
|
-
def warn(message, log_context
|
34
|
-
|
38
|
+
def warn(message, **log_context)
|
39
|
+
super.tap do
|
40
|
+
logged << { message: message, context: log_context, severity: 'WARN' }
|
41
|
+
end
|
35
42
|
end
|
36
43
|
|
37
|
-
def fatal(message, log_context
|
38
|
-
|
44
|
+
def fatal(message, **log_context)
|
45
|
+
super.tap do
|
46
|
+
logged << { message: message, context: log_context, severity: 'FATAL' }
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
50
|
def clear
|
@@ -107,6 +107,12 @@ describe ExceptionHandling do
|
|
107
107
|
class SmtpClientErrbackStub < SmtpClientStub
|
108
108
|
end
|
109
109
|
|
110
|
+
before(:each) do
|
111
|
+
# Reset this for every test since they are applied to the class
|
112
|
+
ExceptionHandling.honeybadger_auto_tagger = nil
|
113
|
+
ExceptionHandling.clear_honeybadger_tags_from_log_context
|
114
|
+
end
|
115
|
+
|
110
116
|
context "with warn and honeybadger notify stubbed" do
|
111
117
|
before do
|
112
118
|
allow(ExceptionHandling).to receive(:warn).with(any_args)
|
@@ -149,6 +155,14 @@ describe ExceptionHandling do
|
|
149
155
|
expect(service_name: 'exception_handling').to eq(logged_excluding_reload_filter.last[:context])
|
150
156
|
end
|
151
157
|
|
158
|
+
it "passes :honeybadger_tags in log context to honeybadger" do
|
159
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: " , awesome , totallytubular, " }))
|
160
|
+
ExceptionHandling.log_error('This is an Error', 'This is the prefix context', honeybadger_tags: ' , awesome , totallytubular, ')
|
161
|
+
|
162
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: " cool neat" }))
|
163
|
+
ExceptionHandling.log_error('This is an Error', 'This is the prefix context', honeybadger_tags: [" ", " cool ", "neat"])
|
164
|
+
end
|
165
|
+
|
152
166
|
it "logs with Severity::FATAL" do
|
153
167
|
ExceptionHandling.log_error('This is a Warning', service_name: 'exception_handling')
|
154
168
|
expect('FATAL').to eq(logged_excluding_reload_filter.last[:severity])
|
@@ -1245,6 +1259,156 @@ describe ExceptionHandling do
|
|
1245
1259
|
expect(logged_excluding_reload_filter.size).to eq(3)
|
1246
1260
|
end
|
1247
1261
|
end
|
1262
|
+
|
1263
|
+
context "#honeybadger_auto_tagger=" do
|
1264
|
+
context "with proc that runs successfully" do
|
1265
|
+
before do
|
1266
|
+
ExceptionHandling.honeybadger_auto_tagger =
|
1267
|
+
->(exception) do
|
1268
|
+
if exception.message =~ /donuts/
|
1269
|
+
['donut-error', 'high-urgency']
|
1270
|
+
else
|
1271
|
+
['low-urgency']
|
1272
|
+
end
|
1273
|
+
end
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
context "without manually passed tags" do
|
1277
|
+
let(:exception) { StandardError.new("We are out of chocolate milk") }
|
1278
|
+
|
1279
|
+
it "adds tags from autotagger" do
|
1280
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "low-urgency" }))
|
1281
|
+
ExceptionHandling.log_error(exception, nil)
|
1282
|
+
end
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
context "with manually passed tags" do
|
1286
|
+
let(:exception) { StandardError.new("The donuts are burning") }
|
1287
|
+
|
1288
|
+
it "merges tags from autotagger with manually passed tags" do
|
1289
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "donut-error high-urgency upset-customers" }))
|
1290
|
+
ExceptionHandling.log_error(exception, nil, honeybadger_tags: ["upset-customers"])
|
1291
|
+
end
|
1292
|
+
end
|
1293
|
+
end
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
context "with proc that raises an exception" do
|
1297
|
+
let(:exception) { StandardError.new("Something else occurred") }
|
1298
|
+
|
1299
|
+
before do
|
1300
|
+
ExceptionHandling.honeybadger_auto_tagger = ->(_exception) { raise StandardError, "boom" }
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
it "logs a message and returns [] for the tags" do
|
1304
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "some-other-tag" }))
|
1305
|
+
expect(ExceptionHandling).to receive(:log_info).with(/Unable to execute honeybadger_auto_tags callback. boom/)
|
1306
|
+
ExceptionHandling.log_error(exception, nil, honeybadger_tags: ["some-other-tag"])
|
1307
|
+
end
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
describe "#add_honeybadger_tag_from_log_context" do
|
1311
|
+
subject(:add_hb_tag) { ExceptionHandling.add_honeybadger_tag_from_log_context(tag_name, path: path) }
|
1312
|
+
let(:tag_name) { "sample-tag" }
|
1313
|
+
let(:path) { ["sample", "path"] }
|
1314
|
+
|
1315
|
+
it "sets the honeybadger log context tags to the tag name and path" do
|
1316
|
+
add_hb_tag
|
1317
|
+
expect(ExceptionHandling.honeybadger_log_context_tags).to include("sample-tag" => ["sample", "path"])
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
context "when path is not an array" do
|
1321
|
+
let(:path) { "not an array" }
|
1322
|
+
|
1323
|
+
it "raises an argument error" do
|
1324
|
+
expect { add_hb_tag }.to raise_error(ArgumentError, /path must be an Array/)
|
1325
|
+
end
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
context "when tag_name is not a string" do
|
1329
|
+
let(:tag_name) { 1 }
|
1330
|
+
|
1331
|
+
it "raises an argument error" do
|
1332
|
+
expect { add_hb_tag }.to raise_error(ArgumentError, /tag_name must be a String/)
|
1333
|
+
end
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
context "when there already exists a tag with the same name" do
|
1337
|
+
before(:each) do
|
1338
|
+
ExceptionHandling.add_honeybadger_tag_from_log_context(tag_name, path: ["other", "path"])
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
it "overwrites the existing tag to the new one" do
|
1342
|
+
add_hb_tag
|
1343
|
+
expect(ExceptionHandling.honeybadger_log_context_tags).to include("sample-tag" => ["sample", "path"])
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
it "logs a warning" do
|
1347
|
+
expect(ExceptionHandling.logger).to receive(:warn).with(/Overwriting existing tag path for 'sample-tag'/, **{})
|
1348
|
+
add_hb_tag
|
1349
|
+
end
|
1350
|
+
end
|
1351
|
+
end
|
1352
|
+
|
1353
|
+
describe "honey badger tags" do
|
1354
|
+
context "with log context tags" do
|
1355
|
+
before(:each) do
|
1356
|
+
ExceptionHandling.add_honeybadger_tag_from_log_context("kubernetes_context", path: ["kubernetes", "context"])
|
1357
|
+
end
|
1358
|
+
|
1359
|
+
context "when error is logged within a log context that matches the path" do
|
1360
|
+
it "notifies honeybadger with the tags from the log context" do
|
1361
|
+
ExceptionHandling.logger.with_context("kubernetes" => { "context" => "local" }) do
|
1362
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "kubernetes_context:local" }))
|
1363
|
+
ExceptionHandling.log_error(StandardError.new("Error"), nil)
|
1364
|
+
end
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
context "when error is logged within a log context that doesn't match the path" do
|
1369
|
+
it "does not specify any tags in the honeybadger notify" do
|
1370
|
+
ExceptionHandling.logger.with_context("kubernetes" => { "pod" => "frontend-abc" }) do
|
1371
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "" }))
|
1372
|
+
ExceptionHandling.log_error(StandardError.new("Error"), nil)
|
1373
|
+
end
|
1374
|
+
end
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
context "when error is logged outside of a log context block" do
|
1378
|
+
it "does not specify any tags in the honeybadger notify" do
|
1379
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "" }))
|
1380
|
+
ExceptionHandling.log_error(StandardError.new("Error"), nil)
|
1381
|
+
end
|
1382
|
+
end
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
context "with all different honeybadger tagging" do
|
1386
|
+
subject(:log_error) { ExceptionHandling.log_error(StandardError.new("Error"), nil, honeybadger_tags: inline_tags) }
|
1387
|
+
let(:inline_tags) { ["inline-tag"] }
|
1388
|
+
before(:each) do
|
1389
|
+
ExceptionHandling.honeybadger_auto_tagger = ->(_exception) { ["auto-tag"] }
|
1390
|
+
ExceptionHandling.add_honeybadger_tag_from_log_context("log-context", path: ["inside", "context"])
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
it "combines all the tags from different sources" do
|
1394
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "auto-tag inline-tag log-context:tag" }))
|
1395
|
+
ExceptionHandling.logger.with_context("inside" => { "context" => "tag" }) do
|
1396
|
+
log_error
|
1397
|
+
end
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
context "when there are duplicate tags" do
|
1401
|
+
let(:inline_tags) { ["auto-tag"] }
|
1402
|
+
|
1403
|
+
it "notifies honeybadger with the set of tags" do
|
1404
|
+
expect(Honeybadger).to receive(:notify).with(hash_including({ tags: "auto-tag log-context:tag" }))
|
1405
|
+
ExceptionHandling.logger.with_context("inside" => { "context" => "tag" }) do
|
1406
|
+
log_error
|
1407
|
+
end
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
end
|
1411
|
+
end
|
1248
1412
|
end
|
1249
1413
|
|
1250
1414
|
context "ExceptionHandling < 3.0 " do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exception_handling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.17.0.pre.tstarck.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Invoca
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionmailer
|
@@ -204,14 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
204
204
|
requirements:
|
205
205
|
- - ">="
|
206
206
|
- !ruby/object:Gem::Version
|
207
|
-
version:
|
207
|
+
version: 2.7.0
|
208
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
209
209
|
requirements:
|
210
|
-
- - "
|
210
|
+
- - ">"
|
211
211
|
- !ruby/object:Gem::Version
|
212
|
-
version:
|
212
|
+
version: 1.3.1
|
213
213
|
requirements: []
|
214
|
-
rubygems_version: 3.4.
|
214
|
+
rubygems_version: 3.4.12
|
215
215
|
signing_key:
|
216
216
|
specification_version: 4
|
217
217
|
summary: Invoca's exception handling logger/emailer layer, based on exception_notifier.
|