exception_handling 3.1.2 → 3.2.0.pre.dc.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 +4 -4
- data/.github/workflows/pipeline.yml +6 -25
- data/.gitignore +1 -0
- data/Appraisals +2 -15
- data/CHANGELOG.md +5 -0
- data/Gemfile +11 -1
- data/Gemfile.lock +28 -9
- data/README.md +16 -0
- data/catalog-info.yaml +39 -0
- data/gemfiles/rails_7_0.gemfile +10 -2
- data/gemfiles/rails_7_1.gemfile +10 -2
- data/gemfiles/rails_7_2.gemfile +25 -0
- data/gemfiles/rails_8_0.gemfile +25 -0
- data/lib/exception_handling/exception_description.rb +3 -1
- data/lib/exception_handling/exception_info.rb +8 -0
- data/lib/exception_handling/version.rb +1 -1
- data/lib/exception_handling.rb +35 -0
- data/spec/simplecov_helper.rb +23 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/exception_handling/exception_description_spec.rb +6 -0
- data/spec/unit/exception_handling/exception_info_spec.rb +42 -0
- data/spec/unit/exception_handling_spec.rb +133 -0
- metadata +8 -5
- data/gemfiles/rails_6_0.gemfile +0 -17
- data/gemfiles/rails_6_1.gemfile +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5a1419e36b2b184e6e49ad6b943537b1f5efaf54680aef66251093c242e93168
|
|
4
|
+
data.tar.gz: 641de9b2e454c20cb754469fce0f781136baefb14af6913ab25fce3f0263bae4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d3ba9e37ec6c14e508341b604df6ffaeed7c88106ca19305f69a2990f6eefcf03a8ae41a3fb6f7245165e00cb910940ae99842f6d73d9c641d8a9f9c2293a883
|
|
7
|
+
data.tar.gz: a9402fb31a6cce4d2181d9b304376412c7acbf63ffb4e592615da2a2bfd77330c8e6ef1a9bb4c3e1428f6dd9bec32295c5f572860117912cb4f34c6f9e49df27
|
|
@@ -1,28 +1,9 @@
|
|
|
1
|
-
---
|
|
2
1
|
name: Pipeline
|
|
3
|
-
on:
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '0 1 * * 1' # Every Monday at 1AM UTC
|
|
4
6
|
jobs:
|
|
5
7
|
tests:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
strategy:
|
|
9
|
-
fail-fast: false
|
|
10
|
-
matrix:
|
|
11
|
-
ruby: [2.7, '3.0', 3.1, 3.2, 3.3]
|
|
12
|
-
gemfile:
|
|
13
|
-
- Gemfile
|
|
14
|
-
- gemfiles/rails_6_0.gemfile
|
|
15
|
-
- gemfiles/rails_6_1.gemfile
|
|
16
|
-
- gemfiles/rails_7_0.gemfile
|
|
17
|
-
- gemfiles/rails_7_1.gemfile
|
|
18
|
-
env:
|
|
19
|
-
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v2
|
|
22
|
-
- uses: ruby/setup-ruby@v1
|
|
23
|
-
with:
|
|
24
|
-
ruby-version: ${{ matrix.ruby }}
|
|
25
|
-
bundler: 2.3.26
|
|
26
|
-
bundler-cache: true
|
|
27
|
-
- name: Unit tests
|
|
28
|
-
run: bundle exec rspec
|
|
8
|
+
uses: Invoca/ruby-test-matrix-workflow/.github/workflows/ruby-test-matrix.yml@main
|
|
9
|
+
secrets: inherit
|
data/.gitignore
CHANGED
data/Appraisals
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
appraise "rails-6-1" do
|
|
8
|
-
gem 'activesupport', '~> 6.1.0'
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
appraise "rails-7-0" do
|
|
12
|
-
gem 'activesupport', '~> 7.0.0'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
appraise "rails-7-1" do
|
|
16
|
-
gem 'activesupport', '~> 7.1.0'
|
|
17
|
-
end
|
|
3
|
+
require "appraisal/matrix"
|
|
4
|
+
appraisal_matrix(rails: "7.0")
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@ 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
|
+
## [3.2.0] - 2026-08-04
|
|
8
|
+
### Added
|
|
9
|
+
- Optional Sentry notifications from `send_external_notifications` when the `Sentry` constant is defined
|
|
10
|
+
- `send_to_sentry` exception filter flag (default `false`); filters with `send_to_honeybadger: true` also send to Sentry to ease migration
|
|
11
|
+
|
|
7
12
|
## [3.1.2] - 2024-05-08
|
|
8
13
|
### Fixed
|
|
9
14
|
- Fixed deprecation warnings that were coming from usage of `silence` when using this gem with Rails 7.1
|
data/Gemfile
CHANGED
|
@@ -5,7 +5,8 @@ source 'https://rubygems.org'
|
|
|
5
5
|
gemspec
|
|
6
6
|
|
|
7
7
|
gem 'activesupport'
|
|
8
|
-
gem 'appraisal'
|
|
8
|
+
gem 'appraisal'
|
|
9
|
+
gem 'appraisal-matrix'
|
|
9
10
|
gem 'gem-release'
|
|
10
11
|
gem 'honeybadger', '~> 4.11'
|
|
11
12
|
gem 'pry'
|
|
@@ -14,4 +15,13 @@ gem 'rake'
|
|
|
14
15
|
gem 'rspec'
|
|
15
16
|
gem 'rspec_junit_formatter'
|
|
16
17
|
gem 'rubocop'
|
|
18
|
+
gem 'simplecov', '~> 0.22'
|
|
19
|
+
gem 'simplecov-lcov', '~> 0.8'
|
|
17
20
|
gem 'test-unit'
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
gem "concurrent-ruby", "~> 1.3", "< 1.3.5"
|
|
24
|
+
|
|
25
|
+
gem "base64", ">= 0.2.0"
|
|
26
|
+
gem "bigdecimal", ">= 3.1"
|
|
27
|
+
gem "mutex_m", ">= 0.2.0"
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
exception_handling (3.
|
|
4
|
+
exception_handling (3.2.0.pre.dc.0)
|
|
5
5
|
activesupport (>= 5.2)
|
|
6
6
|
contextual_logger (~> 1.0)
|
|
7
7
|
escalate (~> 0.3)
|
|
@@ -25,25 +25,29 @@ GEM
|
|
|
25
25
|
bundler
|
|
26
26
|
rake
|
|
27
27
|
thor (>= 0.14.0)
|
|
28
|
+
appraisal-matrix (0.3.0)
|
|
29
|
+
appraisal (~> 2.2)
|
|
28
30
|
ast (2.4.2)
|
|
29
31
|
base64 (0.2.0)
|
|
30
32
|
bigdecimal (3.1.8)
|
|
31
33
|
byebug (11.1.3)
|
|
32
34
|
coderay (1.1.3)
|
|
33
|
-
concurrent-ruby (1.
|
|
35
|
+
concurrent-ruby (1.3.4)
|
|
34
36
|
connection_pool (2.4.1)
|
|
35
|
-
contextual_logger (1.
|
|
36
|
-
activesupport
|
|
37
|
+
contextual_logger (1.5.0)
|
|
38
|
+
activesupport (>= 6.0)
|
|
37
39
|
json
|
|
40
|
+
date (3.5.1)
|
|
38
41
|
diff-lcs (1.5.1)
|
|
42
|
+
docile (1.4.1)
|
|
39
43
|
drb (2.2.1)
|
|
40
44
|
escalate (0.3.0)
|
|
41
45
|
gem-release (2.2.2)
|
|
42
46
|
honeybadger (4.12.2)
|
|
43
47
|
i18n (1.14.5)
|
|
44
48
|
concurrent-ruby (~> 1.0)
|
|
45
|
-
invoca-utils (0.
|
|
46
|
-
activesupport (>=
|
|
49
|
+
invoca-utils (0.7.0)
|
|
50
|
+
activesupport (>= 6.0)
|
|
47
51
|
json (2.7.2)
|
|
48
52
|
language_server-protocol (3.17.0.3)
|
|
49
53
|
method_source (1.1.0)
|
|
@@ -60,7 +64,8 @@ GEM
|
|
|
60
64
|
pry-byebug (3.10.1)
|
|
61
65
|
byebug (~> 11.0)
|
|
62
66
|
pry (>= 0.13, < 0.15)
|
|
63
|
-
psych (5.
|
|
67
|
+
psych (5.4.0)
|
|
68
|
+
date
|
|
64
69
|
stringio
|
|
65
70
|
racc (1.7.3)
|
|
66
71
|
rainbow (3.1.1)
|
|
@@ -96,7 +101,14 @@ GEM
|
|
|
96
101
|
rubocop-ast (1.31.3)
|
|
97
102
|
parser (>= 3.3.1.0)
|
|
98
103
|
ruby-progressbar (1.13.0)
|
|
99
|
-
|
|
104
|
+
simplecov (0.22.0)
|
|
105
|
+
docile (~> 1.1)
|
|
106
|
+
simplecov-html (~> 0.11)
|
|
107
|
+
simplecov_json_formatter (~> 0.1)
|
|
108
|
+
simplecov-html (0.13.2)
|
|
109
|
+
simplecov-lcov (0.9.0)
|
|
110
|
+
simplecov_json_formatter (0.1.4)
|
|
111
|
+
stringio (3.2.0)
|
|
100
112
|
test-unit (3.6.2)
|
|
101
113
|
power_assert
|
|
102
114
|
thor (1.3.1)
|
|
@@ -109,16 +121,23 @@ PLATFORMS
|
|
|
109
121
|
|
|
110
122
|
DEPENDENCIES
|
|
111
123
|
activesupport
|
|
112
|
-
appraisal
|
|
124
|
+
appraisal
|
|
125
|
+
appraisal-matrix
|
|
126
|
+
base64 (>= 0.2.0)
|
|
127
|
+
bigdecimal (>= 3.1)
|
|
128
|
+
concurrent-ruby (~> 1.3, < 1.3.5)
|
|
113
129
|
exception_handling!
|
|
114
130
|
gem-release
|
|
115
131
|
honeybadger (~> 4.11)
|
|
132
|
+
mutex_m (>= 0.2.0)
|
|
116
133
|
pry
|
|
117
134
|
pry-byebug
|
|
118
135
|
rake
|
|
119
136
|
rspec
|
|
120
137
|
rspec_junit_formatter
|
|
121
138
|
rubocop
|
|
139
|
+
simplecov (~> 0.22)
|
|
140
|
+
simplecov-lcov (~> 0.8)
|
|
122
141
|
test-unit
|
|
123
142
|
|
|
124
143
|
BUNDLED WITH
|
data/README.md
CHANGED
|
@@ -39,6 +39,22 @@ ExceptionHandling.honeybadger_auto_tagger = ->(exception) { [] } # See "Automati
|
|
|
39
39
|
ExceptionHandling.add_honeybadger_tag_from_log_context("tag-name", path: ["path", "in", "log", "context"])
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
### External error trackers (Honeybadger / Sentry)
|
|
43
|
+
|
|
44
|
+
ExceptionHandling notifies configured external services from `log_error` (and related paths):
|
|
45
|
+
|
|
46
|
+
- **Honeybadger** — when the `Honeybadger` constant is defined
|
|
47
|
+
- **Sentry** — when the `Sentry` constant is defined (for example after initializing the Sentry Ruby SDK in your app)
|
|
48
|
+
|
|
49
|
+
Both can run at the same time. This gem does not depend on `sentry-ruby`; initialize Sentry in the host application.
|
|
50
|
+
|
|
51
|
+
Matched exception filters in `exception_filters.yml` control delivery:
|
|
52
|
+
|
|
53
|
+
- `send_to_honeybadger: true` — send to Honeybadger (and also to Sentry during migration)
|
|
54
|
+
- `send_to_sentry: true` — send to Sentry
|
|
55
|
+
- Unmatched exceptions are sent when the corresponding service is defined
|
|
56
|
+
- Matched filters with both flags false skip both services
|
|
57
|
+
|
|
42
58
|
## Usage
|
|
43
59
|
|
|
44
60
|
Mixin the `ExceptionHandling::Methods` module into your controllers, models or classes. The example below adds it to all the controllers in you rails application:
|
data/catalog-info.yaml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# This file is partially auto-generated by the invoca-backstage-tools gem
|
|
2
|
+
# The following fields should not be edited manually as they are auto-generated
|
|
3
|
+
# based on the contents of the repo:
|
|
4
|
+
# - metadata.name
|
|
5
|
+
# - metadata.title
|
|
6
|
+
# - metadata.description
|
|
7
|
+
# - annotations.github.com/project-slug
|
|
8
|
+
# - invoca.com/version-repository-location
|
|
9
|
+
# - invoca.com/version-repository-name
|
|
10
|
+
# - spec.type
|
|
11
|
+
# - spec.owner
|
|
12
|
+
---
|
|
13
|
+
apiVersion: backstage.io/v1alpha1
|
|
14
|
+
kind: Component
|
|
15
|
+
metadata:
|
|
16
|
+
name: exception_handling-gem
|
|
17
|
+
title: ExceptionHandling
|
|
18
|
+
annotations:
|
|
19
|
+
buildkite.com/project-slug: Invoca/exception_handling
|
|
20
|
+
github.com/project-slug: Invoca/exception_handling
|
|
21
|
+
invoca.com/version-repository-location: rubygems
|
|
22
|
+
invoca.com/version-repository-name: exception_handling
|
|
23
|
+
endoflife.date/products: ruby@3.3
|
|
24
|
+
tags:
|
|
25
|
+
- ruby
|
|
26
|
+
- open-source
|
|
27
|
+
- gem
|
|
28
|
+
- public
|
|
29
|
+
- rails-dependent
|
|
30
|
+
description: Exception handling logger
|
|
31
|
+
spec:
|
|
32
|
+
type: library
|
|
33
|
+
lifecycle: production
|
|
34
|
+
owner: octothorpe
|
|
35
|
+
system: platform-observability
|
|
36
|
+
dependsOn:
|
|
37
|
+
- component:escalate-gem
|
|
38
|
+
- component:invoca-utils-gem
|
|
39
|
+
- component:contextual_logger-gem
|
data/gemfiles/rails_7_0.gemfile
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "activesupport"
|
|
6
|
-
gem "appraisal"
|
|
5
|
+
gem "activesupport"
|
|
6
|
+
gem "appraisal"
|
|
7
|
+
gem "appraisal-matrix"
|
|
7
8
|
gem "gem-release"
|
|
8
9
|
gem "honeybadger", "~> 4.11"
|
|
9
10
|
gem "pry"
|
|
@@ -13,5 +14,12 @@ gem "rspec"
|
|
|
13
14
|
gem "rspec_junit_formatter"
|
|
14
15
|
gem "rubocop"
|
|
15
16
|
gem "test-unit"
|
|
17
|
+
gem "concurrent-ruby", "~> 1.3", "< 1.3.5"
|
|
18
|
+
gem "base64", ">= 0.2.0"
|
|
19
|
+
gem "bigdecimal", ">= 3.1"
|
|
20
|
+
gem "mutex_m", ">= 0.2.0"
|
|
21
|
+
gem "rails", "~> 7.0.0"
|
|
22
|
+
gem "simplecov", "~> 0.22"
|
|
23
|
+
gem "simplecov-lcov", "~> 0.8"
|
|
16
24
|
|
|
17
25
|
gemspec path: "../"
|
data/gemfiles/rails_7_1.gemfile
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "activesupport"
|
|
6
|
-
gem "appraisal"
|
|
5
|
+
gem "activesupport"
|
|
6
|
+
gem "appraisal"
|
|
7
|
+
gem "appraisal-matrix"
|
|
7
8
|
gem "gem-release"
|
|
8
9
|
gem "honeybadger", "~> 4.11"
|
|
9
10
|
gem "pry"
|
|
@@ -13,5 +14,12 @@ gem "rspec"
|
|
|
13
14
|
gem "rspec_junit_formatter"
|
|
14
15
|
gem "rubocop"
|
|
15
16
|
gem "test-unit"
|
|
17
|
+
gem "concurrent-ruby", "~> 1.3", "< 1.3.5"
|
|
18
|
+
gem "base64", ">= 0.2.0"
|
|
19
|
+
gem "bigdecimal", ">= 3.1"
|
|
20
|
+
gem "mutex_m", ">= 0.2.0"
|
|
21
|
+
gem "rails", "~> 7.1.0"
|
|
22
|
+
gem "simplecov", "~> 0.22"
|
|
23
|
+
gem "simplecov-lcov", "~> 0.8"
|
|
16
24
|
|
|
17
25
|
gemspec path: "../"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "activesupport"
|
|
6
|
+
gem "appraisal"
|
|
7
|
+
gem "appraisal-matrix"
|
|
8
|
+
gem "gem-release"
|
|
9
|
+
gem "honeybadger", "~> 4.11"
|
|
10
|
+
gem "pry"
|
|
11
|
+
gem "pry-byebug"
|
|
12
|
+
gem "rake"
|
|
13
|
+
gem "rspec"
|
|
14
|
+
gem "rspec_junit_formatter"
|
|
15
|
+
gem "rubocop"
|
|
16
|
+
gem "test-unit"
|
|
17
|
+
gem "concurrent-ruby", "~> 1.3", "< 1.3.5"
|
|
18
|
+
gem "base64", ">= 0.2.0"
|
|
19
|
+
gem "bigdecimal", ">= 3.1"
|
|
20
|
+
gem "mutex_m", ">= 0.2.0"
|
|
21
|
+
gem "rails", "~> 7.2.0"
|
|
22
|
+
gem "simplecov", "~> 0.22"
|
|
23
|
+
gem "simplecov-lcov", "~> 0.8"
|
|
24
|
+
|
|
25
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "activesupport"
|
|
6
|
+
gem "appraisal"
|
|
7
|
+
gem "appraisal-matrix"
|
|
8
|
+
gem "gem-release"
|
|
9
|
+
gem "honeybadger", "~> 4.11"
|
|
10
|
+
gem "pry"
|
|
11
|
+
gem "pry-byebug"
|
|
12
|
+
gem "rake"
|
|
13
|
+
gem "rspec"
|
|
14
|
+
gem "rspec_junit_formatter"
|
|
15
|
+
gem "rubocop"
|
|
16
|
+
gem "test-unit"
|
|
17
|
+
gem "concurrent-ruby", "~> 1.3", "< 1.3.5"
|
|
18
|
+
gem "base64", ">= 0.2.0"
|
|
19
|
+
gem "bigdecimal", ">= 3.1"
|
|
20
|
+
gem "mutex_m", ">= 0.2.0"
|
|
21
|
+
gem "rails", "~> 8.0.0"
|
|
22
|
+
gem "simplecov", "~> 0.22"
|
|
23
|
+
gem "simplecov-lcov", "~> 0.8"
|
|
24
|
+
|
|
25
|
+
gemspec path: "../"
|
|
@@ -6,12 +6,13 @@ module ExceptionHandling
|
|
|
6
6
|
|
|
7
7
|
CONFIGURATION_SECTIONS = {
|
|
8
8
|
send_to_honeybadger: false, # should be sent to honeybadger?
|
|
9
|
+
send_to_sentry: false, # should be sent to sentry?
|
|
9
10
|
send_metric: true, # should the metric be sent.
|
|
10
11
|
metric_name: nil, # Will be derived from section name if not passed
|
|
11
12
|
notes: nil # Will be included in exception email if set, used to keep notes and relevant links
|
|
12
13
|
}.freeze
|
|
13
14
|
|
|
14
|
-
attr_reader :filter_name, :send_to_honeybadger, :send_metric, :metric_name, :notes
|
|
15
|
+
attr_reader :filter_name, :send_to_honeybadger, :send_to_sentry, :send_metric, :metric_name, :notes
|
|
15
16
|
|
|
16
17
|
def initialize(filter_name, configuration)
|
|
17
18
|
@filter_name = filter_name
|
|
@@ -21,6 +22,7 @@ module ExceptionHandling
|
|
|
21
22
|
|
|
22
23
|
@configuration = CONFIGURATION_SECTIONS.merge(configuration)
|
|
23
24
|
@send_to_honeybadger = @configuration[:send_to_honeybadger]
|
|
25
|
+
@send_to_sentry = @configuration[:send_to_sentry]
|
|
24
26
|
@send_metric = @configuration[:send_metric]
|
|
25
27
|
@metric_name = (@configuration[:metric_name] || @filter_name).to_s.gsub(" ", "_")
|
|
26
28
|
@notes = @configuration[:notes]
|
|
@@ -78,6 +78,14 @@ module ExceptionHandling
|
|
|
78
78
|
ExceptionHandling.honeybadger_defined? && (!exception_description || exception_description.send_to_honeybadger)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
def send_to_sentry?
|
|
82
|
+
ExceptionHandling.sentry_defined? && (
|
|
83
|
+
!exception_description ||
|
|
84
|
+
exception_description.send_to_sentry ||
|
|
85
|
+
exception_description.send_to_honeybadger
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
81
89
|
def honeybadger_context_data
|
|
82
90
|
@honeybadger_context_data ||= enhanced_data_to_honeybadger_context
|
|
83
91
|
end
|
data/lib/exception_handling.rb
CHANGED
|
@@ -211,6 +211,9 @@ module ExceptionHandling # never included
|
|
|
211
211
|
if honeybadger_defined?
|
|
212
212
|
results[:honeybadger_status] = send_exception_to_honeybadger_unless_filtered(exception_info)
|
|
213
213
|
end
|
|
214
|
+
if sentry_defined?
|
|
215
|
+
results[:sentry_status] = send_exception_to_sentry_unless_filtered(exception_info)
|
|
216
|
+
end
|
|
214
217
|
results
|
|
215
218
|
end
|
|
216
219
|
|
|
@@ -249,6 +252,31 @@ module ExceptionHandling # never included
|
|
|
249
252
|
:failure
|
|
250
253
|
end
|
|
251
254
|
|
|
255
|
+
# Returns :success or :failure or :skipped
|
|
256
|
+
def send_exception_to_sentry_unless_filtered(exception_info)
|
|
257
|
+
if exception_info.send_to_sentry?
|
|
258
|
+
send_exception_to_sentry(exception_info)
|
|
259
|
+
else
|
|
260
|
+
log_info("Filtered exception using '#{exception_info.exception_description.filter_name}'; not sending notification to Sentry")
|
|
261
|
+
:skipped
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
#
|
|
266
|
+
# Log exception to Sentry.
|
|
267
|
+
#
|
|
268
|
+
# Returns :success or :failure
|
|
269
|
+
#
|
|
270
|
+
def send_exception_to_sentry(exception_info)
|
|
271
|
+
exception = exception_info.exception
|
|
272
|
+
response = Sentry.capture_exception(exception)
|
|
273
|
+
response ? :success : :failure
|
|
274
|
+
rescue Exception => ex
|
|
275
|
+
warn("ExceptionHandling.send_exception_to_sentry rescued exception while logging #{exception_info.exception_context}:\n#{exception.class}: #{exception.message}:\n#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
|
|
276
|
+
write_exception_to_log(ex, "ExceptionHandling.send_exception_to_sentry rescued exception while logging #{exception_info.exception_context}:\n#{exception.class}: #{exception.message}", exception_info.timestamp)
|
|
277
|
+
:failure
|
|
278
|
+
end
|
|
279
|
+
|
|
252
280
|
#
|
|
253
281
|
# Check if Honeybadger defined.
|
|
254
282
|
#
|
|
@@ -256,6 +284,13 @@ module ExceptionHandling # never included
|
|
|
256
284
|
Object.const_defined?("Honeybadger")
|
|
257
285
|
end
|
|
258
286
|
|
|
287
|
+
#
|
|
288
|
+
# Check if Sentry defined.
|
|
289
|
+
#
|
|
290
|
+
def sentry_defined?
|
|
291
|
+
Object.const_defined?("Sentry")
|
|
292
|
+
end
|
|
293
|
+
|
|
259
294
|
#
|
|
260
295
|
# Expects passed in hash to only include keys which be directly set on the Honeybadger config
|
|
261
296
|
#
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
unless ENV["NO_COVERAGE"] == "true"
|
|
4
|
+
require "simplecov"
|
|
5
|
+
|
|
6
|
+
SimpleCov.start do
|
|
7
|
+
add_filter "/spec/"
|
|
8
|
+
track_files "lib/**/*.rb"
|
|
9
|
+
|
|
10
|
+
if ENV["GITHUB_ACTIONS"]
|
|
11
|
+
require "simplecov-lcov"
|
|
12
|
+
|
|
13
|
+
SimpleCov::Formatter::LcovFormatter.config do |config|
|
|
14
|
+
config.report_with_single_file = true
|
|
15
|
+
config.single_report_path = "coverage/lcov.info"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
formatter SimpleCov::Formatter::LcovFormatter
|
|
19
|
+
else
|
|
20
|
+
formatter SimpleCov::Formatter::HTMLFormatter
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -35,6 +35,12 @@ module ExceptionHandling
|
|
|
35
35
|
expect(!ExceptionDescription.new(:filter1, error: "my error message").send_to_honeybadger).to be_truthy
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
it "allow send_to_sentry to be specified and have it disabled by default" do
|
|
39
|
+
expect(ExceptionDescription.new(:filter1, error: "my error message", send_to_sentry: false).send_to_sentry).to eq(false)
|
|
40
|
+
expect(ExceptionDescription.new(:filter1, error: "my error message", send_to_sentry: true).send_to_sentry).to eq(true)
|
|
41
|
+
expect(ExceptionDescription.new(:filter1, error: "my error message").send_to_sentry).to eq(false)
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
it "allow send_metric to be configured" do
|
|
39
45
|
expect(!ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).send_metric).to be_truthy
|
|
40
46
|
expect(ExceptionDescription.new(:filter1, error: "my error message").send_metric).to be_truthy
|
|
@@ -452,6 +452,48 @@ module ExceptionHandling
|
|
|
452
452
|
end
|
|
453
453
|
end
|
|
454
454
|
|
|
455
|
+
context "send_to_sentry?" do
|
|
456
|
+
it "be enabled when Sentry is defined and exception is not in the filter list" do
|
|
457
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(true)
|
|
458
|
+
exception_info = ExceptionInfo.new(StandardError.new("something went wrong"), nil, Time.now)
|
|
459
|
+
expect(exception_info.exception_description).to be_nil
|
|
460
|
+
expect(exception_info.send_to_sentry?).to eq(true)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "be enabled when Sentry is defined and filter has send_to_sentry true" do
|
|
464
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(true)
|
|
465
|
+
exception = StandardError.new("No route matches")
|
|
466
|
+
exception_info = ExceptionInfo.new(exception, nil, Time.now)
|
|
467
|
+
allow(exception_info.exception_description).to receive(:send_to_sentry).and_return(true)
|
|
468
|
+
allow(exception_info.exception_description).to receive(:send_to_honeybadger).and_return(false)
|
|
469
|
+
expect(exception_info.send_to_sentry?).to eq(true)
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
it "be enabled when Sentry is defined and filter has send_to_honeybadger true only" do
|
|
473
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(true)
|
|
474
|
+
exception = StandardError.new("No route matches")
|
|
475
|
+
exception_info = ExceptionInfo.new(exception, nil, Time.now)
|
|
476
|
+
allow(exception_info.exception_description).to receive(:send_to_sentry).and_return(false)
|
|
477
|
+
allow(exception_info.exception_description).to receive(:send_to_honeybadger).and_return(true)
|
|
478
|
+
expect(exception_info.send_to_sentry?).to eq(true)
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it "be disabled when Sentry is defined and both filter flags are false" do
|
|
482
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(true)
|
|
483
|
+
exception = StandardError.new("No route matches")
|
|
484
|
+
exception_info = ExceptionInfo.new(exception, nil, Time.now)
|
|
485
|
+
allow(exception_info.exception_description).to receive(:send_to_sentry).and_return(false)
|
|
486
|
+
allow(exception_info.exception_description).to receive(:send_to_honeybadger).and_return(false)
|
|
487
|
+
expect(exception_info.send_to_sentry?).to eq(false)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
it "be disabled when Sentry is not defined" do
|
|
491
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(false)
|
|
492
|
+
exception_info = ExceptionInfo.new(StandardError.new("something went wrong"), nil, Time.now)
|
|
493
|
+
expect(exception_info.send_to_sentry?).to eq(false)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
455
497
|
context "honeybadger_context_data" do
|
|
456
498
|
before do
|
|
457
499
|
allow(ExceptionHandling.logger).to receive(:current_context_for_thread).and_return({ cuid: 'ABCD' })
|
|
@@ -690,6 +690,139 @@ describe ExceptionHandling do
|
|
|
690
690
|
end
|
|
691
691
|
end
|
|
692
692
|
|
|
693
|
+
context "Sentry integration" do
|
|
694
|
+
context "with Sentry not defined" do
|
|
695
|
+
before do
|
|
696
|
+
allow(ExceptionHandling).to receive(:sentry_defined?).and_return(false)
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
it "not invoke send_exception_to_sentry when log_error is executed" do
|
|
700
|
+
expect(ExceptionHandling).to_not receive(:send_exception_to_sentry)
|
|
701
|
+
ExceptionHandling.log_error(exception_1)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
it "not invoke send_exception_to_sentry when ensure_safe is executed" do
|
|
705
|
+
expect(ExceptionHandling).to_not receive(:send_exception_to_sentry)
|
|
706
|
+
ExceptionHandling.ensure_safe { raise exception_1 }
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
context "with Sentry defined" do
|
|
711
|
+
let(:sentry_module) do
|
|
712
|
+
Module.new do
|
|
713
|
+
def self.capture_exception(_exception); end
|
|
714
|
+
end
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
before do
|
|
718
|
+
stub_const("Sentry", sentry_module)
|
|
719
|
+
allow(Sentry).to receive(:capture_exception).and_return(Object.new)
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
it "not send_exception_to_sentry when log_warning is executed" do
|
|
723
|
+
expect(ExceptionHandling).to_not receive(:send_exception_to_sentry)
|
|
724
|
+
ExceptionHandling.log_warning("This should not go to sentry")
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
it "not send_exception_to_sentry when log_error is called with a Warning" do
|
|
728
|
+
expect(ExceptionHandling).to_not receive(:send_exception_to_sentry)
|
|
729
|
+
ExceptionHandling.log_error(ExceptionHandling::Warning.new("This should not go to sentry"))
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
it "invoke send_exception_to_sentry when log_error is executed" do
|
|
733
|
+
expect(ExceptionHandling).to receive(:send_exception_to_sentry).with(any_args).and_call_original
|
|
734
|
+
ExceptionHandling.log_error(exception_1)
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
it "invoke send_exception_to_sentry when log_error_rack is executed" do
|
|
738
|
+
expect(ExceptionHandling).to receive(:send_exception_to_sentry).with(any_args).and_call_original
|
|
739
|
+
ExceptionHandling.log_error_rack(exception_1, {}, nil)
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
it "invoke send_exception_to_sentry when ensure_safe is executed" do
|
|
743
|
+
expect(ExceptionHandling).to receive(:send_exception_to_sentry).with(any_args).and_call_original
|
|
744
|
+
ExceptionHandling.ensure_safe { raise exception_1 }
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
it "call Sentry.capture_exception with the exception" do
|
|
748
|
+
expect(Sentry).to receive(:capture_exception).with(exception_1)
|
|
749
|
+
ExceptionHandling.log_error(exception_1)
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
it "also notify Honeybadger when both are defined" do
|
|
753
|
+
expect(Honeybadger).to receive(:notify).with(any_args).and_return("hb-id")
|
|
754
|
+
expect(Sentry).to receive(:capture_exception).with(exception_1).and_return(Object.new)
|
|
755
|
+
ExceptionHandling.log_error(exception_1)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
it "not send to Sentry when filter has both flags false" do
|
|
759
|
+
filter_list = {
|
|
760
|
+
NoSentry: {
|
|
761
|
+
error: "suppress Sentry notification",
|
|
762
|
+
send_to_honeybadger: false,
|
|
763
|
+
send_to_sentry: false
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
allow(File).to receive(:mtime) { incrementing_mtime }
|
|
767
|
+
expect(YAML).to receive(:load_file).with(any_args) { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }.at_least(1)
|
|
768
|
+
|
|
769
|
+
expect(ExceptionHandling).to receive(:send_exception_to_sentry_unless_filtered).with(any_args).exactly(1).and_call_original
|
|
770
|
+
expect(Sentry).to_not receive(:capture_exception)
|
|
771
|
+
ExceptionHandling.log_error(StandardError.new("suppress Sentry notification"))
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
it "send to Sentry when filter has send_to_honeybadger true only" do
|
|
775
|
+
filter_list = {
|
|
776
|
+
HoneybadgerOnly: {
|
|
777
|
+
error: "honeybadger only filter",
|
|
778
|
+
send_to_honeybadger: true,
|
|
779
|
+
send_to_sentry: false
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
allow(File).to receive(:mtime) { incrementing_mtime }
|
|
783
|
+
expect(YAML).to receive(:load_file).with(any_args) { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }.at_least(1)
|
|
784
|
+
|
|
785
|
+
expect(Sentry).to receive(:capture_exception).with(instance_of(StandardError))
|
|
786
|
+
ExceptionHandling.log_error(StandardError.new("honeybadger only filter"))
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
it "send to Sentry when filter has send_to_sentry true only" do
|
|
790
|
+
filter_list = {
|
|
791
|
+
SentryOnly: {
|
|
792
|
+
error: "sentry only filter",
|
|
793
|
+
send_to_honeybadger: false,
|
|
794
|
+
send_to_sentry: true
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
allow(File).to receive(:mtime) { incrementing_mtime }
|
|
798
|
+
expect(YAML).to receive(:load_file).with(any_args) { ActiveSupport::HashWithIndifferentAccess.new(filter_list) }.at_least(1)
|
|
799
|
+
|
|
800
|
+
expect(Sentry).to receive(:capture_exception).with(instance_of(StandardError))
|
|
801
|
+
ExceptionHandling.log_error(StandardError.new("sentry only filter"))
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
it "still complete log_error and notify Honeybadger if Sentry.capture_exception raises" do
|
|
805
|
+
expect(Honeybadger).to receive(:notify).with(any_args).and_return("hb-id")
|
|
806
|
+
expect(Sentry).to receive(:capture_exception).and_raise(StandardError, "Sentry Notification Failure")
|
|
807
|
+
expect { ExceptionHandling.log_error(exception_1) }.not_to raise_error
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
it "return :failure when Sentry.capture_exception returns nil" do
|
|
811
|
+
expect(Sentry).to receive(:capture_exception).and_return(nil)
|
|
812
|
+
expect(ExceptionHandling.send_exception_to_sentry(
|
|
813
|
+
ExceptionHandling::ExceptionInfo.new(exception_1, "", Time.now)
|
|
814
|
+
)).to eq(:failure)
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
it "return :success when Sentry.capture_exception returns an event" do
|
|
818
|
+
expect(Sentry).to receive(:capture_exception).and_return(Object.new)
|
|
819
|
+
expect(ExceptionHandling.send_exception_to_sentry(
|
|
820
|
+
ExceptionHandling::ExceptionInfo.new(exception_1, "", Time.now)
|
|
821
|
+
)).to eq(:success)
|
|
822
|
+
end
|
|
823
|
+
end
|
|
824
|
+
end
|
|
825
|
+
|
|
693
826
|
class EventResponse
|
|
694
827
|
def to_s
|
|
695
828
|
"message from to_s!"
|
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: 3.
|
|
4
|
+
version: 3.2.0.pre.dc.0
|
|
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: 2026-08-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -103,12 +103,13 @@ files:
|
|
|
103
103
|
- LICENSE
|
|
104
104
|
- README.md
|
|
105
105
|
- Rakefile
|
|
106
|
+
- catalog-info.yaml
|
|
106
107
|
- config/exception_filters.yml
|
|
107
108
|
- exception_handling.gemspec
|
|
108
|
-
- gemfiles/rails_6_0.gemfile
|
|
109
|
-
- gemfiles/rails_6_1.gemfile
|
|
110
109
|
- gemfiles/rails_7_0.gemfile
|
|
111
110
|
- gemfiles/rails_7_1.gemfile
|
|
111
|
+
- gemfiles/rails_7_2.gemfile
|
|
112
|
+
- gemfiles/rails_8_0.gemfile
|
|
112
113
|
- lib/exception_handling.rb
|
|
113
114
|
- lib/exception_handling/escalate_callback.rb
|
|
114
115
|
- lib/exception_handling/exception_catalog.rb
|
|
@@ -121,6 +122,7 @@ files:
|
|
|
121
122
|
- spec/helpers/controller_helpers.rb
|
|
122
123
|
- spec/helpers/exception_helpers.rb
|
|
123
124
|
- spec/rake_test_warning_false.rb
|
|
125
|
+
- spec/simplecov_helper.rb
|
|
124
126
|
- spec/spec_helper.rb
|
|
125
127
|
- spec/unit/exception_handling/escalate_callback_spec.rb
|
|
126
128
|
- spec/unit/exception_handling/exception_catalog_spec.rb
|
|
@@ -149,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
149
151
|
- !ruby/object:Gem::Version
|
|
150
152
|
version: '0'
|
|
151
153
|
requirements: []
|
|
152
|
-
rubygems_version: 3.
|
|
154
|
+
rubygems_version: 3.5.10
|
|
153
155
|
signing_key:
|
|
154
156
|
specification_version: 4
|
|
155
157
|
summary: Invoca's exception handling logger layer, based on exception_notifier.
|
|
@@ -157,6 +159,7 @@ test_files:
|
|
|
157
159
|
- spec/helpers/controller_helpers.rb
|
|
158
160
|
- spec/helpers/exception_helpers.rb
|
|
159
161
|
- spec/rake_test_warning_false.rb
|
|
162
|
+
- spec/simplecov_helper.rb
|
|
160
163
|
- spec/spec_helper.rb
|
|
161
164
|
- spec/unit/exception_handling/escalate_callback_spec.rb
|
|
162
165
|
- spec/unit/exception_handling/exception_catalog_spec.rb
|
data/gemfiles/rails_6_0.gemfile
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "activesupport", "~> 6.0.0"
|
|
6
|
-
gem "appraisal", "~> 2.2"
|
|
7
|
-
gem "gem-release"
|
|
8
|
-
gem "honeybadger", "~> 4.11"
|
|
9
|
-
gem "pry"
|
|
10
|
-
gem "pry-byebug"
|
|
11
|
-
gem "rake"
|
|
12
|
-
gem "rspec"
|
|
13
|
-
gem "rspec_junit_formatter"
|
|
14
|
-
gem "rubocop"
|
|
15
|
-
gem "test-unit"
|
|
16
|
-
|
|
17
|
-
gemspec path: "../"
|
data/gemfiles/rails_6_1.gemfile
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# This file was generated by Appraisal
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
gem "activesupport", "~> 6.1.0"
|
|
6
|
-
gem "appraisal", "~> 2.2"
|
|
7
|
-
gem "gem-release"
|
|
8
|
-
gem "honeybadger", "~> 4.11"
|
|
9
|
-
gem "pry"
|
|
10
|
-
gem "pry-byebug"
|
|
11
|
-
gem "rake"
|
|
12
|
-
gem "rspec"
|
|
13
|
-
gem "rspec_junit_formatter"
|
|
14
|
-
gem "rubocop"
|
|
15
|
-
gem "test-unit"
|
|
16
|
-
|
|
17
|
-
gemspec path: "../"
|