exception-track 0.6.2 → 1.3.0

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
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