exception-track 0.6.2 → 1.3.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
2
  SHA256:
3
- metadata.gz: b096b42d1e359c95d02180e76597932827bf0552887c98c30ab4c5655c014d86
4
- data.tar.gz: 47f461e204a87e35cf4c0bad912fa2b99e38662ff12678e21f3faa9ffd0bd13c
3
+ metadata.gz: 71a2bc45d225661a466bdd4fe3ae8227253cf0e4e48430a3f3db33605c04aed7
4
+ data.tar.gz: fbf989949bd59b5ac8ea1b44c159cae09ded01832c21c42193729a95b20f3015
5
5
  SHA512:
6
- metadata.gz: ecd0dfa7ebc4a8ec10622ee01f3109f140b6174288fb23cc90cca5f8f1539e0c7cf40a4340211486e3cafd5f41da32201144c969abf0e1f5d14bd35df33af1bc
7
- data.tar.gz: ee57578ba6af00e75eb92200434de9d4c3bdd96f49f68ba3bca44221c14831f771757059217c4bd0a8dd3bb9210b9ddf32e197be3389c5392ee2a11a571a6017
6
+ metadata.gz: a7b776ccbda802c32ca77f60ec4257e198d2e9e96c611ccc03c14fb00efc1fb5f127a60e9df627b985ddef347d1e1ceb2f04c8919894ab73da3ac796fe8cc0c5
7
+ data.tar.gz: 14a4f70638b02742170ff3138d553624a8c379b2c0480624f178354fd0324dbcb58d5d75627e78f24026338fbeb750478431034ac76eb3b7cb3f8cd42df4dc9e
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- ExceptionTrack
2
- --------------
1
+ ## ExceptionTrack
3
2
 
4
3
  Tracking exceptions for Rails application store them in database.
5
4
 
@@ -7,7 +6,7 @@ This gem is base on [exception_notification](https://github.com/smartinez87/exce
7
6
 
8
7
  [中文介绍和使用说明](https://ruby-china.org/topics/32325)
9
8
 
10
- [![Gem Version](https://badge.fury.io/rb/exception-track.svg)](https://badge.fury.io/rb/exception-track) [![Build Status](https://travis-ci.org/rails-engine/exception-track.svg)](https://travis-ci.org/rails-engine/exception-track) [![Code Climate](https://codeclimate.com/github/rails-engine/exception-track/badges/gpa.svg)](https://codeclimate.com/github/rails-engine/exception-track) [![codecov.io](https://codecov.io/github/rails-engine/exception-track/coverage.svg?branch=master)](https://codecov.io/github/rails-engine/exception-track?branch=master) [![](http://inch-ci.org/github/rails-engine/exception-track.svg?branch=master)](http://inch-ci.org/github/rails-engine/exception-track?branch=master)
9
+ [![Gem Version](https://badge.fury.io/rb/exception-track.svg)](https://badge.fury.io/rb/exception-track) [![build](https://github.com/rails-engine/exception-track/workflows/build/badge.svg)](https://github.com/rails-engine/exception-track/actions?query=workflow%3Abuild) [![codecov.io](https://codecov.io/github/rails-engine/exception-track/coverage.svg?branch=master)](https://codecov.io/github/rails-engine/exception-track?branch=master)
11
10
 
12
11
  ![2017-02-17 12 35 18](https://cloud.githubusercontent.com/assets/5518/23052599/8e267c02-f50d-11e6-8d6e-cef0cc1991b7.png)
13
12
 
@@ -41,6 +40,12 @@ Rails.application.routes.draw do
41
40
  end
42
41
  ```
43
42
 
43
+ Migrate database:
44
+
45
+ ```shell
46
+ bundle exec rails db:migrate
47
+ ```
48
+
44
49
  Now you can open: http://localhost:3000/exception-track
45
50
 
46
51
  ## Configuration
File without changes
@@ -1,27 +1,78 @@
1
+ :root {
2
+ --body-background-color: #eee;
3
+ --card-background-color: #fff;
4
+ --card-border-color: #fff;
5
+ --card-shadow-color: rgba(200, 200, 200, 0.26);
6
+ --text-color: #333;
7
+ --text-color1: #666;
8
+ --text-color2: #999;
9
+ --link-color: #364cc9;
10
+ --table-background-color1: #f5f5f5;
11
+ --table-border-color: #f0f0f0;
12
+ --input-border-color: #ddd;
13
+ --button-background-color: #fff;
14
+ --button-border-color: #eee;
15
+ --button-text-color: #555;
16
+ --button-hover-background-color: #f7f7f7;
17
+ --button-hover-border-color: #eee;
18
+ --button-danger-color: #f85149;
19
+ --button-danger-hover-background-color: #f85149;
20
+ --button-danger-hover-color: #fff;
21
+ --pre-background-color: #f7f7f7;
22
+ --notice-color: #fff;
23
+ --notice-background-color: #3CBD46;
24
+ }
25
+
26
+ @media (prefers-color-scheme: dark) {
27
+ :root {
28
+ --body-background-color: #0d1117;
29
+ --card-background-color: rgba(200, 200, 200, 0.02);
30
+ --card-border-color: #30363d;
31
+ --card-shadow-color: rgba(0, 0, 0, 0.16);
32
+ --text-color: #c9d1d9;
33
+ --text-color1: #999;
34
+ --text-color2: #888;
35
+ --link-color: #58a6ff;
36
+ --table-background-color1: #161b22;
37
+ --table-border-color: #30363d;
38
+ --input-border-color: #333;
39
+ --button-background-color: #21262d;
40
+ --button-border-color: #30363d;
41
+ --button-text-color: #c9d1d9;
42
+ --button-hover-background-color: #30363d;
43
+ --button-hover-border-color: #8b949e;
44
+ --pre-background-color: #161b22;
45
+ --notice-color: #3CBD46;
46
+ --notice-background-color: #3cbd4621;
47
+ }
48
+ }
1
49
 
2
50
  body {
3
51
  margin: 0;
4
52
  padding: 20px 0;
5
- background-color: #eee;
53
+ background-color: var(--body-background-color);
6
54
  }
7
55
 
8
56
  body, textarea {
9
57
  font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, Helvetica, sans-serif;
10
58
  font-size: 14px;
11
59
  line-height: 1.4;
12
- color: #333;
60
+ color: var(--text-color);
13
61
  }
14
62
 
15
63
  .footer {
16
64
  padding: 15px;
17
65
  text-align: center;
18
- color: #999;
66
+ color: var(--text-color2);
67
+ }
68
+
69
+ .footer a:link, .footer a:visited {
70
+ color: var(--text-color1);
71
+ text-decoration: underline;
19
72
  }
20
- .footer a:link,
21
- .footer a:visited { color: #666; text-decoration: underline;}
22
73
 
23
74
  a, a:visited, a:active {
24
- color: #364cc9;
75
+ color: var(--link-color);
25
76
  text-decoration: none;
26
77
  }
27
78
 
@@ -34,15 +85,15 @@ table {
34
85
  border-collapse: collapse;
35
86
  border-spacing: 0;
36
87
  margin-bottom: 20px;
88
+ border: 1px solid var(--table-border-color);
89
+ border-radius: 3px;
37
90
  }
38
91
 
39
- th {
40
- text-align: left;
41
- border-bottom: solid 1px #e0e0e0;
92
+ td.date {
93
+ width: 170px;
94
+ font-size: 12px;
42
95
  }
43
96
 
44
- td.date { width: 150px; font-size: 12px; }
45
-
46
97
  h1 {
47
98
  margin-top: 0;
48
99
  font-size: 20px;
@@ -66,29 +117,28 @@ ul {
66
117
  table td, table th {
67
118
  padding: 10px 15px;
68
119
  }
69
- th { background: #f5f5f5; border-bottom: 1px solid #e0e0e0; }
70
- td {
71
- border-top: solid 1px #e0e0e0;
120
+
121
+ th {
122
+ text-align: left;
123
+ background: var(--table-background-color1);
124
+ border-bottom: 1px solid var(--table-border-color);
72
125
  }
73
126
 
74
- pre {
75
- background-color: #eee;
76
- padding: 10px;
77
- white-space: pre-wrap;
78
- word-break: break-word;
127
+ td {
128
+ border-top: solid 1px var(--table-border-color);
79
129
  }
80
130
 
81
131
  textarea {
82
132
  width: 100%;
83
133
  height: 100px;
84
- border: solid 1px #ddd;
134
+ border: solid 1px var(--input-border-color);
85
135
  padding: 10px;
86
136
  }
87
137
 
88
138
  hr {
89
139
  border: none;
90
140
  height: 0;
91
- border-top: solid 1px #ddd;
141
+ border-top: solid 1px var(--input-border-color);
92
142
  margin-bottom: 15px;
93
143
  }
94
144
 
@@ -107,16 +157,29 @@ hr {
107
157
  -ms-user-select: none;
108
158
  user-select: none;
109
159
  border-radius: 3px;
110
- border: 1px solid #ccc;
160
+ transition: .2s cubic-bezier(.3, 0, .5, 1);
161
+ transition-property: color, background-color, border-color;
162
+ border: 1px solid var(--button-border-color);
111
163
  padding: 6px 16px;
112
- color: #555 !important;
164
+ color: var(--button-text-color) !important;
113
165
  outline: 0 !important;
114
- background: #FFF;
166
+ background: var(--button-background-color);
115
167
  }
116
- .btn:hover { text-decoration: none !important; background: #f7f7f7; }
117
- .btn-danger { background: #fff; color: #E33F00 !important; border-color: #E33F00;}
168
+
169
+ .btn:hover {
170
+ text-decoration: none !important;
171
+ background: var(--button-hover-background-color);
172
+ }
173
+
174
+ .btn-danger {
175
+ background: var(--button-background-color);
176
+ color: var(--button-danger-color) !important;
177
+ border-color: var(--button-border-color);
178
+ }
179
+
118
180
  .btn-danger:hover {
119
- background: #FCEDEC;
181
+ background: var(--button-danger-hover-background-color);
182
+ color: var(--button-danger-hover-color) !important;
120
183
  }
121
184
 
122
185
  .container {
@@ -124,8 +187,9 @@ hr {
124
187
  margin-left: auto;
125
188
  margin-right: auto;
126
189
  padding: 20px;
127
- background-color: #fff;
128
- box-shadow: 0 1px 8px rgba(200, 200, 200, 0.26);
190
+ background-color: var(--card-background-color);
191
+ box-shadow: 0 1px 8px var(--card-shadow-color);
192
+ border: 1px solid var(--card-border-color);
129
193
  border-radius: 3px;
130
194
  }
131
195
 
@@ -140,49 +204,67 @@ hr {
140
204
  height: 34px;
141
205
  line-height: 34px;
142
206
  }
143
- .toolbar form { display: inline; }
144
- .toolbar .pull-right { float: right; }
207
+
208
+ .toolbar form {
209
+ display: inline;
210
+ }
211
+
212
+ .toolbar .pull-right {
213
+ float: right;
214
+ }
145
215
 
146
216
  #notice {
147
217
  padding: 8px 15px;
148
- background: #3CBD46;
149
- color: #fff;
218
+ background: var(--notice-background-color);
219
+ color: var(--notice-color);
150
220
  margin-bottom: 15px;
151
221
  border-radius: 3px;
152
222
  }
153
223
 
154
224
  pre {
155
- background: #f7f7f7;
225
+ white-space: pre-wrap;
226
+ word-break: break-word;
227
+ background: var(--pre-background-color);
156
228
  padding: 25px;
157
229
  border-radius: 3px;
158
230
  font-size: 12px;
159
231
  font-family: Menlo, Monaco, Consolas, monospace;
160
232
  }
161
233
 
162
- h1 { font-size: 16px; }
234
+ h1 {
235
+ font-size: 16px;
236
+ }
163
237
 
164
238
  .pagination {
165
239
  padding-bottom: 15px;
166
240
  font-size: 14px;
167
241
  }
168
242
 
169
- .pagination li { display: inline; }
243
+ .pagination li {
244
+ display: inline;
245
+ }
170
246
 
171
247
  .pagination a {
172
248
  display: inline-block;
173
249
  padding: 5px 10px;
174
- border: 1px solid #eee;
175
- color: #555;
250
+ border-radius: 3px;
251
+ border: 1px solid var(--button-border-color);
252
+ color: var(--button-text-color);
253
+ background: var(--button-background-color);
176
254
  text-decoration: none;
177
255
  }
256
+
178
257
  .pagination a:hover {
179
- background: #f7f7f7;
258
+ background: var(--button-hover-background-color);
259
+ color: var(--button-hover-color);
260
+ border-color: var(--button-hover-border-color);
180
261
  }
181
- .pagination em,
182
- .pagination .current {
262
+
263
+ .pagination em, .pagination .current {
264
+ border-radius: 3px;
183
265
  display: inline-block;
184
266
  padding: 5px 10px;
185
- border: 1px solid #f0f0f0;
186
- background: #f0f0f0;
267
+ border: 1px solid var(--button-hover-border-color);
268
+ background: var(--button-hover-background-color);
187
269
  font-style: normal;
188
- }
270
+ }
@@ -3,7 +3,7 @@
3
3
  module ExceptionTrack
4
4
  class LogsController < ActionController::Base
5
5
  layout "exception-track/application"
6
- before_action :set_log, only: %i[show destroy]
6
+ before_action :set_log, only: :show
7
7
 
8
8
  # GET /exception_logs
9
9
  def index
@@ -12,7 +12,7 @@ module ExceptionTrack
12
12
 
13
13
  def export
14
14
  @logs = Log.order("id desc").where("created_at >= ?", 3.months.ago)
15
- send_data JSON.pretty_generate(@logs.as_json(only: [:title, :body, :created_at, :updated_at])), filename: "#{Date.current}.json", disposition: "attachment"
15
+ send_data JSON.pretty_generate(@logs.as_json(only: %i[title body created_at updated_at])), filename: "#{Date.current}.json", disposition: "attachment"
16
16
  end
17
17
 
18
18
  # GET /exception_logs/1
@@ -25,7 +25,6 @@ module ExceptionTrack
25
25
  end
26
26
 
27
27
  private
28
-
29
28
  # Use callbacks to share common setup or constraints between actions.
30
29
  def set_log
31
30
  @log = Log.find(params[:id])
@@ -6,7 +6,7 @@
6
6
  }
7
7
  </script>
8
8
  <div class="toolbar">
9
- <%= @logs.total_count %> exceptions
9
+ <a class="btn" href="/">Back to App</a>
10
10
 
11
11
  <div class="pull-right">
12
12
  <%= form_tag(export_logs_path, method: 'post') do %>
@@ -21,6 +21,7 @@
21
21
  <% if @logs.blank? %>
22
22
  <div class="no-record">No exceptions.</div>
23
23
  <% else %>
24
+ <h1><%= pluralize(@logs.total_count, 'exception') %></h1>
24
25
  <%= paginate @logs %>
25
26
 
26
27
  <table class="table table-borded tabl">
@@ -9,10 +9,15 @@ ExceptionTrack.configure do
9
9
  end
10
10
 
11
11
  # ExceptionNotification.configure do |config|
12
- # config.ignored_exceptions += %w(ActionView::TemplateError
13
- # ActionController::InvalidAuthenticityToken
14
- # ActionController::BadRequest
15
- # ActionView::MissingTemplate
16
- # ActionController::UrlGenerationError
17
- # ActionController::UnknownFormat)
12
+ # config.ignored_exceptions += %w[
13
+ # ActionView::TemplateError
14
+ # ActionController::InvalidAuthenticityToken
15
+ # ActionController::BadRequest
16
+ # ActionView::MissingTemplate
17
+ # ActionController::UrlGenerationError
18
+ # ActionController::UnknownFormat
19
+ # ActionController::InvalidCrossOriginRequest
20
+ # ActionController::ParameterMissing
21
+ # Mime::Type::InvalidMimeType
22
+ # ]
18
23
  # end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateExceptionTrackLogs < ActiveRecord::Migration[5.0]
3
+ class CreateExceptionTrackLogs < ActiveRecord::Migration[5.2]
4
4
  def change
5
5
  create_table :exception_tracks do |t|
6
6
  t.string :title
7
- t.text :body, limit: 16777215
7
+ t.text :body, limit: 16_777_215
8
8
 
9
9
  t.timestamps
10
10
  end
@@ -8,6 +8,7 @@ module ExceptionTrack
8
8
 
9
9
  def enabled_env?(env)
10
10
  return false if env.blank?
11
+
11
12
  environments.include?(env.to_sym)
12
13
  end
13
14
  end
@@ -5,7 +5,9 @@ module ExceptionTrack
5
5
  isolate_namespace ExceptionTrack
6
6
 
7
7
  initializer "exception-track.assets.precompile", group: :all do |app|
8
- app.config.assets.precompile += %w( exception-track/application.css )
8
+ app.config.assets.precompile += %w[exception-track/application.css]
9
9
  end
10
+
11
+ ExceptionTrack::LogSubscriber.attach_to :exception_track
10
12
  end
11
13
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionTrack
4
+ class LogSubscriber < ActiveSupport::LogSubscriber
5
+ # ActiveSupport::Notifications.instrument('track.exception_track', action: action)
6
+ def track(event)
7
+ prefix = color("ExceptionTrack", CYAN)
8
+ title = color(event.payload[:title], RED)
9
+ debug " #{prefix} track db (#{event.duration.round(1)}ms)"
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExceptionTrack
4
- VERSION = "0.6.2"
4
+ VERSION = "1.3.0"
5
5
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  require "exception-track/version"
4
4
  require "exception-track/configuration"
5
+ require "exception-track/log_subscriber"
5
6
  require "exception-track/engine"
6
7
 
7
8
  require "exception_notification"
8
9
  require "exception_notification/rails"
9
- require "exception_notifier/exception_track_notifier"
10
10
 
11
11
  require "kaminari"
12
12
 
@@ -14,17 +14,18 @@ module ExceptionTrack
14
14
  class << self
15
15
  def config
16
16
  return @config if defined?(@config)
17
+
17
18
  @config = Configuration.new
18
19
  @config.environments = %i[development production]
19
20
  @config
20
21
  end
21
22
 
22
23
  def configure(&block)
23
- config.instance_exec(&block)
24
+ config.instance_eval(&block)
24
25
  end
25
26
  end
26
27
  end
27
28
 
28
29
  ExceptionNotification.configure do |config|
29
- config.add_notifier :exception_track, {}
30
+ config.add_notifier :db, {}
30
31
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionNotification
4
+ class Rack
5
+ class CascadePassException < RuntimeError; end
6
+
7
+ def initialize(app, options = {})
8
+ @app = app
9
+
10
+ ExceptionNotifier.tap do |en|
11
+ en.ignored_exceptions = options.delete(:ignore_exceptions) if options.key?(:ignore_exceptions)
12
+ en.error_grouping = options.delete(:error_grouping) if options.key?(:error_grouping)
13
+ en.error_grouping_period = options.delete(:error_grouping_period) if options.key?(:error_grouping_period)
14
+ en.notification_trigger = options.delete(:notification_trigger) if options.key?(:notification_trigger)
15
+
16
+ if options.key?(:error_grouping_cache)
17
+ en.error_grouping_cache = options.delete(:error_grouping_cache)
18
+ elsif defined?(Rails) && Rails.respond_to?(:cache)
19
+ en.error_grouping_cache = Rails.cache
20
+ end
21
+ end
22
+
23
+ if options.key?(:ignore_if)
24
+ rack_ignore = options.delete(:ignore_if)
25
+ ExceptionNotifier.ignore_if do |exception, opts|
26
+ opts.key?(:env) && rack_ignore.call(opts[:env], exception)
27
+ end
28
+ end
29
+
30
+ if options.key?(:ignore_notifier_if)
31
+ rack_ignore_by_notifier = options.delete(:ignore_notifier_if)
32
+ rack_ignore_by_notifier.each do |notifier, proc|
33
+ ExceptionNotifier.ignore_notifier_if(notifier) do |exception, opts|
34
+ opts.key?(:env) && proc.call(opts[:env], exception)
35
+ end
36
+ end
37
+ end
38
+
39
+ ExceptionNotifier.ignore_crawlers(options.delete(:ignore_crawlers)) if options.key?(:ignore_crawlers)
40
+
41
+ @ignore_cascade_pass = options.delete(:ignore_cascade_pass) { true }
42
+
43
+ options.each do |notifier_name, opts|
44
+ ExceptionNotifier.register_exception_notifier(notifier_name, opts)
45
+ end
46
+ end
47
+
48
+ def call(env)
49
+ _, headers, = response = @app.call(env)
50
+
51
+ if !@ignore_cascade_pass && headers["X-Cascade"] == "pass"
52
+ msg = "This exception means that the preceding Rack middleware set the 'X-Cascade' header to 'pass' -- in " \
53
+ "Rails, this often means that the route was not found (404 error)."
54
+ raise CascadePassException, msg
55
+ end
56
+
57
+ response
58
+ rescue Exception => e
59
+ env["exception_notifier.delivered"] = true if ExceptionNotifier.notify_exception(e, env: env)
60
+
61
+ raise e unless e.is_a?(CascadePassException)
62
+
63
+ response
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionNotification
4
+ class Engine < ::Rails::Engine
5
+ config.exception_notification = ExceptionNotifier
6
+ config.exception_notification.logger = Rails.logger
7
+ config.exception_notification.error_grouping_cache = Rails.cache
8
+
9
+ config.app_middleware.use ExceptionNotification::Rack
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resque/failure/base"
4
+
5
+ module ExceptionNotification
6
+ class Resque < Resque::Failure::Base
7
+ def self.count
8
+ ::Resque::Stat[:failed]
9
+ end
10
+
11
+ def save
12
+ data = {
13
+ error_class: exception.class.name,
14
+ error_message: exception.message,
15
+ failed_at: Time.now.to_s,
16
+ payload: payload,
17
+ queue: queue,
18
+ worker: worker.to_s
19
+ }
20
+
21
+ ExceptionNotifier.notify_exception(exception, data: {resque: data})
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sidekiq"
4
+
5
+ # Note: this class is only needed for Sidekiq version < 3.
6
+ module ExceptionNotification
7
+ class Sidekiq
8
+ def call(_worker, msg, _queue)
9
+ yield
10
+ rescue Exception => e
11
+ ExceptionNotifier.notify_exception(e, data: {sidekiq: msg})
12
+ raise e
13
+ end
14
+ end
15
+ end
16
+
17
+ if ::Sidekiq::VERSION < "3"
18
+ ::Sidekiq.configure_server do |config|
19
+ config.server_middleware do |chain|
20
+ chain.add ::ExceptionNotification::Sidekiq
21
+ end
22
+ end
23
+ else
24
+ ::Sidekiq.configure_server do |config|
25
+ config.error_handlers << proc do |ex, context|
26
+ ExceptionNotifier.notify_exception(ex, data: {sidekiq: context})
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionNotification
4
+ VERSION = "4.5.0"
5
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "exception_notifier/notifier"
4
+ require "exception_notification/rack"
5
+ require "exception_notification/version"
6
+
7
+ module ExceptionNotification
8
+ # Alternative way to setup ExceptionNotification.
9
+ # Run 'rails generate exception_notification:install' to create
10
+ # a fresh initializer with all configuration values.
11
+ def self.configure
12
+ yield ExceptionNotifier
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionNotifier
4
+ class BaseNotifier
5
+ attr_accessor :base_options
6
+
7
+ def initialize(options = {})
8
+ @base_options = options
9
+ end
10
+
11
+ def send_notice(exception, options, message, message_opts = nil)
12
+ _pre_callback(exception, options, message, message_opts)
13
+ result = yield(message, message_opts)
14
+ _post_callback(exception, options, message, message_opts)
15
+ result
16
+ end
17
+
18
+ def _pre_callback(exception, options, message, message_opts)
19
+ return unless @base_options[:pre_callback].respond_to?(:call)
20
+
21
+ @base_options[:pre_callback].call(options, self, exception.backtrace, message, message_opts)
22
+ end
23
+
24
+ def _post_callback(exception, options, message, message_opts)
25
+ return unless @base_options[:post_callback].respond_to?(:call)
26
+
27
+ @base_options[:post_callback].call(options, self, exception.backtrace, message, message_opts)
28
+ end
29
+ end
30
+ end