exception_notification 4.1.2 → 4.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4eb16cddf2508b34a6a2dde7228376c70ed01025
4
- data.tar.gz: 667d58580ae06080b620d8938437155a6b9b0586
3
+ metadata.gz: 3696eecc7d4afcf68b5458d570f811a595b2e912
4
+ data.tar.gz: 1a5d379db9e9e9dff3d4e15c1b9e3f435daa41f3
5
5
  SHA512:
6
- metadata.gz: ca1acead20b24875e0cacdbf5574266bf4fa1d080a361eec0f877b794247773f1236854661698706e62fcdd18d47adeb2b64fb8d83c6d654d1cb43b941e32293
7
- data.tar.gz: fac6c6c82dc3eebcb635e92fd16f011845d97bcdd4ad080f3acdfc4ef2e65284d9496e027f3cbc5f1b4c4d445cc244162e0bfbfb1d3d8909cbc4fd5bd5ad73e3
6
+ metadata.gz: bde0dd2960675f710e0073d38f2f4e75bc7b783de92ea337337b83e67ce39a7650911a182743c2cd2200082b74fb113c0619e453e3817e2fa52b0796b841f3dd
7
+ data.tar.gz: 6caf354673c7e63c800fa9417d5bf9df72220257a891895326bbae110aaa4879770d87fb30113e555014b691094f9f4e47a7968bc619f3d6e18a60a3b09a3eae
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ == undefined
2
+
3
+ * enhancements
4
+ * Add a way to have a backtrace callback on notifiers (by @pcboy)
5
+
6
+ * bug fixes
7
+ * Fix incompatible character encodings error (by @san650)
8
+
1
9
  == 4.1.2
2
10
  * enhancements
3
11
  * Change format of Slack notifications (by @eldano)
data/README.md CHANGED
@@ -7,26 +7,21 @@
7
7
 
8
8
  **THIS README IS FOR THE MASTER BRANCH AND REFLECTS THE WORK CURRENTLY EXISTING ON THE MASTER BRANCH. IF YOU ARE WISHING TO USE A NON-MASTER BRANCH OF EXCEPTION NOTIFICATION, PLEASE CONSULT THAT BRANCH'S README AND NOT THIS ONE.**
9
9
 
10
- -
11
-
12
- The Exception Notification gem provides a set of [notifiers](#notifiers) for sending notifications when errors occur in a Rack/Rails application.
13
-
14
- The built-in notifiers can deliver notifications by [email](#email-notifier), [campfire rooms](#campfire-notifier) or via [webhooks](#webhook-notifier).
10
+ ---
15
11
 
12
+ The Exception Notification gem provides a set of [notifiers](#notifiers) for sending notifications when errors occur in a Rack/Rails application. The built-in notifiers can deliver notifications by [email](#email-notifier), [Campfire](#campfire-notifier), [HipChat](#hipchat-notifier), [Slack](#slack-notifier), [IRC](#irc-notifier) or via custom [WebHooks](#webhook-notifier).
16
13
 
17
14
  There's a great [Railscast about Exception Notification](http://railscasts.com/episodes/104-exception-notifications-revised) you can see that may help you getting started.
18
15
 
19
16
  [Follow us on Twitter](https://twitter.com/exception_notif) to get updates and notices about new releases.
20
17
 
21
-
22
18
  ## Requirements
23
19
 
24
- * Ruby 1.9.3 or greater
25
- * Rails 3.1 or greater, Sinatra or another Rack-based application.
20
+ * Ruby 2.0 or greater
21
+ * Rails 4.0 or greater, Sinatra or another Rack-based application.
26
22
 
27
23
  For previous releases, please checkout [this](#versions).
28
24
 
29
-
30
25
  ## Getting Started
31
26
 
32
27
  Add the following line to your application's Gemfile:
@@ -35,7 +30,9 @@ Add the following line to your application's Gemfile:
35
30
  gem 'exception_notification'
36
31
  ```
37
32
 
38
- As of Rails 3 ExceptionNotification is used as a rack middleware, or in the environment you want it to run. In most cases you would want ExceptionNotification to run on production. Thus, you can make it work by putting the following lines in your `config/environments/production.rb`:
33
+ ### Rails
34
+
35
+ ExceptionNotification is used as a rack middleware, or in the environment you want it to run. In most cases you would want ExceptionNotification to run on production. Thus, you can make it work by putting the following lines in your `config/environments/production.rb`:
39
36
 
40
37
  ```ruby
41
38
  Rails.application.config.middleware.use ExceptionNotification::Rack,
@@ -46,24 +43,38 @@ Rails.application.config.middleware.use ExceptionNotification::Rack,
46
43
  }
47
44
  ```
48
45
 
49
- > **Note**: In order to enable delivery notifications by email make sure you have [ActionMailer configured](#actionmailer-configuration).
46
+ **Note**: In order to enable delivery notifications by email make sure you have [ActionMailer configured](#actionmailer-configuration).
50
47
 
48
+ ### Rack/Sinatra
51
49
 
52
50
  In order to use ExceptionNotification with Sinatra, please take a look in the [example application](https://github.com/smartinez87/exception_notification/tree/master/examples/sinatra).
53
51
 
52
+ ## Notifiers
53
+
54
+ ExceptionNotification relies on notifiers to deliver notifications when errors occur in your applications. By default, six notifiers are available:
54
55
 
55
- ### Upgrading to 4.x version
56
+ * [Campfire notifier](#campfire-notifier)
57
+ * [Email notifier](#email-notifier)
58
+ * [HipChat notifier](#hipchat-notifier)
59
+ * [IRC notifier](#irc-notifier)
60
+ * [Slack notifier](#slack-notifier)
61
+ * [WebHook notifier](#webhook-notifier)
56
62
 
57
- As of 4.x version the configuration syntax has changed. All email related options MUST BE nested under the `:email` key. Thus, previous configuration like:
63
+ But, you also can easily implement your own [custom notifier](#custom-notifier).
64
+
65
+ ### Campfire notifier
66
+
67
+ This notifier sends notifications to your Campfire room.
68
+
69
+ #### Usage
70
+
71
+ Just add the [tinder](https://github.com/collectiveidea/tinder) gem to your `Gemfile`:
58
72
 
59
73
  ```ruby
60
- Rails.application.config.middleware.use ExceptionNotifier,
61
- :email_prefix => "[PREFIX] ",
62
- :sender_address => %{"notifier" <notifier@example.com>},
63
- :exception_recipients => %w{exceptions@example.com}
74
+ gem 'tinder'
64
75
  ```
65
76
 
66
- becomes:
77
+ To configure it, you need to set the `subdomain`, `token` and `room_name` options, like this:
67
78
 
68
79
  ```ruby
69
80
  Rails.application.config.middleware.use ExceptionNotification::Rack,
@@ -71,21 +82,42 @@ Rails.application.config.middleware.use ExceptionNotification::Rack,
71
82
  :email_prefix => "[PREFIX] ",
72
83
  :sender_address => %{"notifier" <notifier@example.com>},
73
84
  :exception_recipients => %w{exceptions@example.com}
85
+ },
86
+ :campfire => {
87
+ :subdomain => 'my_subdomain',
88
+ :token => 'my_token',
89
+ :room_name => 'my_room'
74
90
  }
75
91
  ```
76
92
 
77
- Beside that, the rack middleware was renamed to `ExceptionNotification::Rack`.
93
+ #### Options
78
94
 
79
- ## Notifiers
95
+ ##### subdomain
80
96
 
81
- ExceptionNotification relies on notifiers to deliver notifications when errors occur in your applications. By default, three notifiers are available: [email notifier](#email-notifier), [campfire notifier](#campfire-notifier) and [webhook notifier](#webhook-notifier). But, you also can easily implement your own [custom notifier](#custom-notifier).
97
+ *String, required*
82
98
 
99
+ Your subdomain at Campfire.
100
+
101
+ ##### room_name
102
+
103
+ *String, required*
104
+
105
+ The Campfire room where the notifications must be published to.
106
+
107
+ ##### token
108
+
109
+ *String, required*
110
+
111
+ The API token to allow access to your Campfire account.
112
+
113
+
114
+ For more options to set Campfire, like _ssl_, check [here](https://github.com/collectiveidea/tinder/blob/master/lib/tinder/campfire.rb#L17).
83
115
 
84
116
  ### Email notifier
85
117
 
86
118
  The Email notifier sends notifications by email. The notifications/emails sent includes information about the current request, session, and environment, and also gives a backtrace of the exception.
87
119
 
88
- After an exception notification has been delivered the rack environment variable 'exception_notifier.delivered' will be set to true.
120
+ After an exception notification has been delivered the rack environment variable `exception_notifier.delivered` will be set to true.
89
121
 
90
122
  #### ActionMailer configuration
91
123
 
@@ -110,21 +142,18 @@ config.action_mailer.raise_delivery_errors = true
110
142
 
111
143
  Who the message is from.
112
144
 
113
-
114
145
  ##### exception_recipients
115
146
 
116
147
  *String/Array of strings, default: []*
117
148
 
118
149
  Who the message is destined for, can be a string of addresses, or an array of addresses.
119
150
 
120
-
121
151
  ##### email_prefix
122
152
 
123
153
  *String, default: [ERROR]*
124
154
 
125
155
  The subject's prefix of the message.
126
156
 
127
-
128
157
  ##### sections
129
158
 
130
159
  *Array of strings, default: %w(request session environment backtrace)*
@@ -174,7 +203,6 @@ end
174
203
 
175
204
  In the above case, `@document` and `@person` would be made available to the email renderer, allowing your new section(s) to access and display them. See the existing sections defined by the plugin for examples of how to write your own.
176
205
 
177
-
178
206
  ##### background_sections
179
207
 
180
208
  *Array of strings, default: %w(backtrace data)*
@@ -191,7 +219,6 @@ Rails.application.config.middleware.use ExceptionNotification::Rack,
191
219
  }
192
220
  ```
193
221
 
194
-
195
222
  ##### email_headers
196
223
 
197
224
  *Hash of strings, default: {}*
@@ -208,28 +235,24 @@ Rails.application.config.middleware.use ExceptionNotification::Rack,
208
235
  }
209
236
  ```
210
237
 
211
-
212
238
  ##### verbose_subject
213
239
 
214
240
  *Boolean, default: true*
215
241
 
216
242
  If enabled, include the exception message in the subject. Use `:verbose_subject => false` to exclude it.
217
243
 
218
-
219
244
  ##### normalize_subject
220
245
 
221
246
  *Boolean, default: false*
222
247
 
223
248
  If enabled, remove numbers from subject so they thread as a single one. Use `:normalize_subject => true` to enable it.
224
249
 
225
-
226
250
  ##### email_format
227
251
 
228
252
  *Symbol, default: :text*
229
253
 
230
254
  By default, ExceptionNotification sends emails in plain text, in order to sends multipart notifications (aka HTML emails) use `:email_format => :html`.
231
255
 
232
-
233
256
  ##### delivery_method
234
257
 
235
258
  *Symbol, default: :smtp*
@@ -267,73 +290,18 @@ Rails.application.config.middleware.use ExceptionNotification::Rack,
267
290
 
268
291
  A complete list of `smtp_settings` options can be found in the [ActionMailer Configuration documentation](http://api.rubyonrails.org/classes/ActionMailer/Base.html#class-ActionMailer::Base-label-Configuration+options).
269
292
 
270
-
271
293
  ##### mailer_parent
272
294
 
273
295
  *String, default: ActionMailer::Base*
274
296
 
275
297
  The parent mailer which ExceptionNotification mailer inherit from.
276
298
 
277
-
278
299
  ##### deliver_with
279
300
 
280
301
  *Symbol, default: :deliver_now
281
302
 
282
303
  The method name to send emalis using ActionMailer.
283
304
 
284
-
285
- ### Campfire notifier
286
-
287
- This notifier sends notifications to your Campfire room.
288
-
289
- #### Usage
290
-
291
- Just add the [tinder](https://github.com/collectiveidea/tinder) gem to your `Gemfile`:
292
-
293
- ```ruby
294
- gem 'tinder'
295
- ```
296
-
297
- To configure it, you need to set the `subdomain`, `token` and `room_name` options, like this:
298
-
299
- ```ruby
300
- Rails.application.config.middleware.use ExceptionNotification::Rack,
301
- :email => {
302
- :email_prefix => "[PREFIX] ",
303
- :sender_address => %{"notifier" <notifier@example.com>},
304
- :exception_recipients => %w{exceptions@example.com}
305
- },
306
- :campfire => {
307
- :subdomain => 'my_subdomain',
308
- :token => 'my_token',
309
- :room_name => 'my_room'
310
- }
311
- ```
312
-
313
- #### Options
314
-
315
- ##### subdomain
316
-
317
- *String, required*
318
-
319
- Your subdomain at Campfire.
320
-
321
- ##### room_name
322
-
323
- *String, required*
324
-
325
- The Campfire room where the notifications must be published to.
326
-
327
- ##### token
328
-
329
- *String, required*
330
-
331
- The API token to allow access to your Campfire account.
332
-
333
-
334
- For more options to set Campfire, like _ssl_, check [here](https://github.com/collectiveidea/tinder/blob/master/lib/tinder/campfire.rb#L17).
335
-
336
-
337
305
  ### HipChat notifier
338
306
 
339
307
  This notifier sends notifications to your Hipchat room.
@@ -395,67 +363,6 @@ Message will appear from this nickname. Default : 'Exception'.
395
363
 
396
364
  For all options & possible values see [Hipchat API](https://www.hipchat.com/docs/api/method/rooms/message).
397
365
 
398
- ### Webhook notifier
399
-
400
- This notifier ships notifications over the HTTP protocol.
401
-
402
- #### Usage
403
-
404
- Just add the [HTTParty](https://github.com/jnunemaker/httparty) gem to your `Gemfile`:
405
-
406
- ```ruby
407
- gem 'httparty'
408
- ```
409
-
410
- To configure it, you need to set the `url` option, like this:
411
-
412
- ```ruby
413
- Rails.application.config.middleware.use ExceptionNotification::Rack,
414
- :email => {
415
- :email_prefix => "[PREFIX] ",
416
- :sender_address => %{"notifier" <notifier@example.com>},
417
- :exception_recipients => %w{exceptions@example.com}
418
- },
419
- :webhook => {
420
- :url => 'http://domain.com:5555/hubot/path'
421
- }
422
- ```
423
-
424
- By default, the WebhookNotifier will call the URLs using the POST method. But, you can change this using the `http_method` option.
425
-
426
- ```ruby
427
- Rails.application.config.middleware.use ExceptionNotification::Rack,
428
- :email => {
429
- :email_prefix => "[PREFIX] ",
430
- :sender_address => %{"notifier" <notifier@example.com>},
431
- :exception_recipients => %w{exceptions@example.com}
432
- },
433
- :webhook => {
434
- :url => 'http://domain.com:5555/hubot/path',
435
- :http_method => :get
436
- }
437
- ```
438
-
439
- Besides the `url` and `http_method` options, all the other options are passed directly to HTTParty. Thus, if the HTTP server requires authentication, you can include the following options:
440
-
441
- ```ruby
442
- Rails.application.config.middleware.use ExceptionNotification::Rack,
443
- :email => {
444
- :email_prefix => "[PREFIX] ",
445
- :sender_address => %{"notifier" <notifier@example.com>},
446
- :exception_recipients => %w{exceptions@example.com}
447
- },
448
- :webhook => {
449
- :url => 'http://domain.com:5555/hubot/path',
450
- :basic_auth => {
451
- :username => 'alice',
452
- :password => 'password'
453
- }
454
- }
455
- ```
456
-
457
- For more HTTParty options, check out the [documentation](https://github.com/jnunemaker/httparty).
458
-
459
366
  ### IRC notifier
460
367
 
461
368
  This notifier sends notifications to an IRC channel using the carrier-pigeon gem.
@@ -638,6 +545,68 @@ more information. Default: 'incoming-webhook'
638
545
 
639
546
  Contains additional payload for a message (e.g avatar, attachments, etc). See [slack-notifier](https://github.com/stevenosloan/slack-notifier#additional-parameters) for more information.. Default: '{}'
640
547
 
548
+
549
+ ### WebHook notifier
550
+
551
+ This notifier ships notifications over the HTTP protocol.
552
+
553
+ #### Usage
554
+
555
+ Just add the [HTTParty](https://github.com/jnunemaker/httparty) gem to your `Gemfile`:
556
+
557
+ ```ruby
558
+ gem 'httparty'
559
+ ```
560
+
561
+ To configure it, you need to set the `url` option, like this:
562
+
563
+ ```ruby
564
+ Rails.application.config.middleware.use ExceptionNotification::Rack,
565
+ :email => {
566
+ :email_prefix => "[PREFIX] ",
567
+ :sender_address => %{"notifier" <notifier@example.com>},
568
+ :exception_recipients => %w{exceptions@example.com}
569
+ },
570
+ :webhook => {
571
+ :url => 'http://domain.com:5555/hubot/path'
572
+ }
573
+ ```
574
+
575
+ By default, the WebhookNotifier will call the URLs using the POST method. But, you can change this using the `http_method` option.
576
+
577
+ ```ruby
578
+ Rails.application.config.middleware.use ExceptionNotification::Rack,
579
+ :email => {
580
+ :email_prefix => "[PREFIX] ",
581
+ :sender_address => %{"notifier" <notifier@example.com>},
582
+ :exception_recipients => %w{exceptions@example.com}
583
+ },
584
+ :webhook => {
585
+ :url => 'http://domain.com:5555/hubot/path',
586
+ :http_method => :get
587
+ }
588
+ ```
589
+
590
+ Besides the `url` and `http_method` options, all the other options are passed directly to HTTParty. Thus, if the HTTP server requires authentication, you can include the following options:
591
+
592
+ ```ruby
593
+ Rails.application.config.middleware.use ExceptionNotification::Rack,
594
+ :email => {
595
+ :email_prefix => "[PREFIX] ",
596
+ :sender_address => %{"notifier" <notifier@example.com>},
597
+ :exception_recipients => %w{exceptions@example.com}
598
+ },
599
+ :webhook => {
600
+ :url => 'http://domain.com:5555/hubot/path',
601
+ :basic_auth => {
602
+ :username => 'alice',
603
+ :password => 'password'
604
+ }
605
+ }
606
+ ```
607
+
608
+ For more HTTParty options, check out the [documentation](https://github.com/jnunemaker/httparty).
609
+
641
610
  ### Custom notifier
642
611
 
643
612
  Simply put, notifiers are objects which respond to `#call(exception, options)` method. Thus, a lambda can be used as a notifier as follow:
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'exception_notification'
3
- s.version = '4.1.2'
3
+ s.version = '4.1.3'
4
4
  s.authors = ["Jamis Buck", "Josh Peek"]
5
- s.date = %q{2015-12-04}
5
+ s.date = %q{2015-12-22}
6
6
  s.summary = "Exception notification for Rails apps"
7
7
  s.homepage = "http://smartinez87.github.com/exception_notification"
8
8
  s.email = "smartinez87@gmail.com"
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_development_dependency "rails", "~> 4.0"
23
23
  s.add_development_dependency "resque", "~> 1.2.0"
24
- # Sidekiq 3.2.2 does not support Ruby 1.9.
24
+ # Sidekiq 3.2.2 does not support Ruby 1.9.
25
25
  s.add_development_dependency "sidekiq", "~> 3.0.0", "< 3.2.2"
26
26
  s.add_development_dependency "tinder", "~> 1.8"
27
27
  s.add_development_dependency "httparty", "~> 0.10.2"
@@ -1,6 +1,7 @@
1
1
  require 'logger'
2
2
  require 'active_support/core_ext/string/inflections'
3
3
  require 'active_support/core_ext/module/attribute_accessors'
4
+ require 'exception_notifier/base_notifier'
4
5
 
5
6
  module ExceptionNotifier
6
7
 
@@ -0,0 +1,25 @@
1
+ module ExceptionNotifier
2
+ class BaseNotifier
3
+ attr_accessor :base_options
4
+
5
+ def initialize(options={})
6
+ @base_options = options
7
+ end
8
+
9
+ def send_notice(exception, options, message, message_opts=nil)
10
+ _pre_callback(exception, options, message, message_opts)
11
+ result = yield(message, message_opts)
12
+ _post_callback(exception, options, message, message_opts)
13
+ result
14
+ end
15
+
16
+ def _pre_callback(exception, options, message, message_opts)
17
+ @base_options[:pre_callback].call(base_options, self, exception.backtrace, message, message_opts) if @base_options[:pre_callback].respond_to?(:call)
18
+ end
19
+
20
+ def _post_callback(exception, options, message, message_opts)
21
+ @base_options[:post_callback].call(base_options, self, exception.backtrace, message, message_opts) if @base_options[:post_callback].respond_to?(:call)
22
+ end
23
+
24
+ end
25
+ end
@@ -1,11 +1,12 @@
1
1
  module ExceptionNotifier
2
- class CampfireNotifier
2
+ class CampfireNotifier < BaseNotifier
3
3
 
4
4
  attr_accessor :subdomain
5
5
  attr_accessor :token
6
6
  attr_accessor :room
7
7
 
8
8
  def initialize(options)
9
+ super
9
10
  begin
10
11
  subdomain = options.delete(:subdomain)
11
12
  room_name = options.delete(:room_name)
@@ -20,7 +21,9 @@ module ExceptionNotifier
20
21
  if active?
21
22
  message = "A new exception occurred: '#{exception.message}'"
22
23
  message += " on '#{exception.backtrace.first}'" if exception.backtrace
23
- @room.paste message message
24
+ send_notice(exception, options, message) do |msg, _|
25
+ @room.paste msg
26
+ end
24
27
  end
25
28
  end
26
29
 
@@ -4,7 +4,9 @@ require 'action_dispatch'
4
4
  require 'pp'
5
5
 
6
6
  module ExceptionNotifier
7
- class EmailNotifier < Struct.new(:sender_address, :exception_recipients,
7
+ class EmailNotifier < BaseNotifier
8
+ attr_accessor(:sender_address, :exception_recipients,
9
+ :pre_callback, :post_callback,
8
10
  :email_prefix, :email_format, :sections, :background_sections,
9
11
  :verbose_subject, :normalize_subject, :delivery_method, :mailer_settings,
10
12
  :email_headers, :mailer_parent, :template_path, :deliver_with)
@@ -78,6 +80,12 @@ module ExceptionNotifier
78
80
  end
79
81
  end
80
82
 
83
+ helper_method :safe_encode
84
+
85
+ def safe_encode(value)
86
+ value.encode("utf-8", invalid: :replace, undef: :replace, replace: "_")
87
+ end
88
+
81
89
  def html_mail?
82
90
  @options[:email_format] == :html
83
91
  end
@@ -115,20 +123,22 @@ module ExceptionNotifier
115
123
  end
116
124
 
117
125
  def initialize(options)
126
+ super
118
127
  delivery_method = (options[:delivery_method] || :smtp)
119
128
  mailer_settings_key = "#{delivery_method}_settings".to_sym
120
129
  options[:mailer_settings] = options.delete(mailer_settings_key)
121
130
 
122
- super(*options.reverse_merge(EmailNotifier.default_options).values_at(
131
+ options.reverse_merge(EmailNotifier.default_options).select{|k,v|[
123
132
  :sender_address, :exception_recipients,
133
+ :pre_callback, :post_callback,
124
134
  :email_prefix, :email_format, :sections, :background_sections,
125
135
  :verbose_subject, :normalize_subject, :delivery_method, :mailer_settings,
126
- :email_headers, :mailer_parent, :template_path, :deliver_with))
136
+ :email_headers, :mailer_parent, :template_path, :deliver_with].include?(k)}.each{|k,v| send("#{k}=", v)}
127
137
  end
128
138
 
129
139
  def options
130
140
  @options ||= {}.tap do |opts|
131
- each_pair { |k,v| opts[k] = v }
141
+ self.instance_variables.each { |var| opts[var[1..-1].to_sym] = self.instance_variable_get(var) }
132
142
  end
133
143
  end
134
144
 
@@ -147,9 +157,13 @@ module ExceptionNotifier
147
157
  env = options[:env]
148
158
  default_options = self.options
149
159
  if env.nil?
150
- mailer.background_exception_notification(exception, options, default_options)
160
+ send_notice(exception, options, nil, default_options) do |_, default_opts|
161
+ mailer.background_exception_notification(exception, options, default_opts)
162
+ end
151
163
  else
152
- mailer.exception_notification(env, exception, options, default_options)
164
+ send_notice(exception, options, nil, default_options) do |_, default_opts|
165
+ mailer.exception_notification(env, exception, options, default_opts)
166
+ end
153
167
  end
154
168
  end
155
169
 
@@ -1,11 +1,12 @@
1
1
  module ExceptionNotifier
2
- class HipchatNotifier
2
+ class HipchatNotifier < BaseNotifier
3
3
 
4
4
  attr_accessor :from
5
5
  attr_accessor :room
6
6
  attr_accessor :message_options
7
7
 
8
8
  def initialize(options)
9
+ super
9
10
  begin
10
11
  api_token = options.delete(:api_token)
11
12
  room_name = options.delete(:room_name)
@@ -30,7 +31,9 @@ module ExceptionNotifier
30
31
  return if !active?
31
32
 
32
33
  message = @message_template.call(exception)
33
- @room.send(@from, message, @message_options)
34
+ send_notice(exception, options, message, @message_options) do |msg, message_opts|
35
+ @room.send(@from, msg, message_opts)
36
+ end
34
37
  end
35
38
 
36
39
  private
@@ -1,6 +1,7 @@
1
1
  module ExceptionNotifier
2
- class IrcNotifier
2
+ class IrcNotifier < BaseNotifier
3
3
  def initialize(options)
4
+ super
4
5
  @config = OpenStruct.new
5
6
  parse_options(options)
6
7
  end
@@ -8,7 +9,11 @@ module ExceptionNotifier
8
9
  def call(exception, options={})
9
10
  message = "'#{exception.message}'"
10
11
  message += " on '#{exception.backtrace.first}'" if exception.backtrace
11
- send_message([*@config.prefix, *message].join(' ')) if active?
12
+ if active?
13
+ send_notice(exception, options, message) do |msg, _|
14
+ send_message([*@config.prefix, *msg].join(' '))
15
+ end
16
+ end
12
17
  end
13
18
 
14
19
  def send_message(message)
@@ -1,10 +1,11 @@
1
1
  module ExceptionNotifier
2
- class SlackNotifier
2
+ class SlackNotifier < BaseNotifier
3
3
  include ExceptionNotifier::BacktraceCleaner
4
4
 
5
5
  attr_accessor :notifier
6
6
 
7
7
  def initialize(options)
8
+ super
8
9
  begin
9
10
  @ignore_data_if = options[:ignore_data_if]
10
11
 
@@ -38,7 +39,11 @@ module ExceptionNotifier
38
39
 
39
40
  attchs = [color: 'danger', text: text, fields: fields, mrkdwn_in: %w(text fields)]
40
41
 
41
- @notifier.ping '', @message_opts.merge(attachments: attchs) if valid?
42
+ if valid?
43
+ send_notice(exception, options, clean_message, @message_opts.merge(attachments: attchs)) do |msg, message_opts|
44
+ @notifier.ping '', message_opts
45
+ end
46
+ end
42
47
  end
43
48
 
44
49
  protected
@@ -1,5 +1,5 @@
1
1
  <% filtered_env = @request.filtered_env -%>
2
2
  <% max = filtered_env.keys.map(&:to_s).max { |a, b| a.length <=> b.length } -%>
3
3
  <% filtered_env.keys.map(&:to_s).sort.each do |key| -%>
4
- * <%= raw("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
4
+ * <%= raw safe_encode("%-*s: %s" % [max.length, key, inspect_object(filtered_env[key])]) %>
5
5
  <% end -%>
@@ -1,7 +1,7 @@
1
- * URL : <%= raw @request.url %>
1
+ * URL : <%= raw safe_encode @request.url %>
2
2
  * HTTP Method: <%= raw @request.request_method %>
3
3
  * IP address : <%= raw @request.remote_ip %>
4
- * Parameters : <%= raw @request.filtered_parameters.inspect %>
4
+ * Parameters : <%= raw safe_encode @request.filtered_parameters.inspect %>
5
5
  * Timestamp : <%= raw Time.current %>
6
6
  * Server : <%= raw Socket.gethostname %>
7
7
  <% if defined?(Rails) && Rails.respond_to?(:root) %>
@@ -1,9 +1,10 @@
1
1
  require 'action_dispatch'
2
2
 
3
3
  module ExceptionNotifier
4
- class WebhookNotifier
4
+ class WebhookNotifier < BaseNotifier
5
5
 
6
6
  def initialize(options)
7
+ super
7
8
  @default_options = options
8
9
  end
9
10
 
@@ -23,7 +24,7 @@ module ExceptionNotifier
23
24
  options[:body][:exception] = {:error_class => exception.class.to_s,
24
25
  :message => exception.message.inspect,
25
26
  :backtrace => exception.backtrace}
26
- options[:body][:data] = (env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
27
+ options[:body][:data] = (env && env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
27
28
 
28
29
  unless env.nil?
29
30
  request = ActionDispatch::Request.new(env)
@@ -38,8 +39,9 @@ module ExceptionNotifier
38
39
  options[:body][:session] = request.session
39
40
  options[:body][:environment] = request.filtered_env
40
41
  end
41
-
42
- HTTParty.send(http_method, url, options)
42
+ send_notice(exception, options, nil, @default_options) do |msg, opts|
43
+ HTTParty.send(http_method, url, opts)
44
+ end
43
45
  end
44
46
  end
45
47
  end
@@ -8,7 +8,9 @@ Dummy::Application.config.middleware.use ExceptionNotification::Rack,
8
8
  :exception_recipients => %w{dummyexceptions@example.com},
9
9
  :email_headers => { "X-Custom-Header" => "foobar" },
10
10
  :sections => ['new_section', 'request', 'session', 'environment', 'backtrace'],
11
- :background_sections => %w(new_bkg_section backtrace data)
11
+ :background_sections => %w(new_bkg_section backtrace data),
12
+ :pre_callback => proc { |opts, notifier, backtrace, message, message_opts| message_opts[:pre_callback_called] = 1 },
13
+ :post_callback => proc { |opts, notifier, backtrace, message, message_opts| message_opts[:post_callback_called] = 1 }
12
14
  }
13
15
 
14
16
  # Initialize the rails application
@@ -46,6 +46,30 @@ class CampfireNotifierTest < ActiveSupport::TestCase
46
46
  assert_nil campfire.call(fake_exception)
47
47
  end
48
48
 
49
+ test "should call pre/post_callback if specified" do
50
+ pre_callback_called, post_callback_called = 0,0
51
+ Tinder::Campfire.stubs(:new).returns(Object.new)
52
+
53
+ campfire = ExceptionNotifier::CampfireNotifier.new(
54
+ {
55
+ :subdomain => 'test',
56
+ :token => 'test_token',
57
+ :room_name => 'test_room',
58
+ :pre_callback => proc { |opts, notifier, backtrace, message, message_opts|
59
+ pre_callback_called += 1
60
+ },
61
+ :post_callback => proc { |opts, notifier, backtrace, message, message_opts|
62
+ post_callback_called += 1
63
+ }
64
+ }
65
+ )
66
+ campfire.room = Object.new
67
+ campfire.room.stubs(:paste).returns(fake_notification)
68
+ campfire.call(fake_exception)
69
+ assert_equal(1, pre_callback_called)
70
+ assert_equal(1, post_callback_called)
71
+ end
72
+
49
73
  private
50
74
 
51
75
  def fake_notification
@@ -13,6 +13,11 @@ class EmailNotifierTest < ActiveSupport::TestCase
13
13
  end
14
14
  end
15
15
 
16
+ test "should call pre/post_callback if specified" do
17
+ assert_equal @email_notifier.options[:pre_callback_called], 1
18
+ assert_equal @email_notifier.options[:post_callback_called], 1
19
+ end
20
+
16
21
  test "should have default sender address overridden" do
17
22
  assert_equal @email_notifier.sender_address, %("Dummy Notifier" <dummynotifier@example.com>)
18
23
  end
@@ -150,6 +155,26 @@ class EmailNotifierTest < ActiveSupport::TestCase
150
155
  assert_nil @ignored_mail
151
156
  end
152
157
 
158
+ test "should encode environment strings" do
159
+ email_notifier = ExceptionNotifier::EmailNotifier.new(
160
+ :sender_address => "<dummynotifier@example.com>",
161
+ :exception_recipients => %w{dummyexceptions@example.com},
162
+ :deliver_with => :deliver_now
163
+ )
164
+
165
+ mail = email_notifier.create_email(
166
+ @exception,
167
+ :env => {
168
+ "REQUEST_METHOD" => "GET",
169
+ "rack.input" => "",
170
+ "invalid_encoding" => "R\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::ASCII),
171
+ },
172
+ :email_format => :text
173
+ )
174
+
175
+ assert_match /invalid_encoding\s+: R__sum__/, mail.encoded
176
+ end
177
+
153
178
  if defined?(Rails) && ('4.2'...'5.0').cover?(Rails.version)
154
179
  test "should be able to specify ActionMailer::MessageDelivery method" do
155
180
  email_notifier = ExceptionNotifier::EmailNotifier.new(
@@ -16,6 +16,24 @@ class HipchatNotifierTest < ActiveSupport::TestCase
16
16
  hipchat.call(fake_exception)
17
17
  end
18
18
 
19
+ test "should call pre/post_callback if specified" do
20
+ pre_callback_called, post_callback_called = 0,0
21
+ options = {
22
+ :api_token => 'good_token',
23
+ :room_name => 'room_name',
24
+ :color => 'yellow',
25
+ :pre_callback => proc { |*| pre_callback_called += 1},
26
+ :post_callback => proc { |*| post_callback_called += 1}
27
+ }
28
+
29
+ HipChat::Room.any_instance.expects(:send).with('Exception', fake_body, { :color => 'yellow' }.merge(options.except(:api_token, :room_name)))
30
+
31
+ hipchat = ExceptionNotifier::HipchatNotifier.new(options)
32
+ hipchat.call(fake_exception)
33
+ assert_equal(1, pre_callback_called)
34
+ assert_equal(1, post_callback_called)
35
+ end
36
+
19
37
  test "should send hipchat notification without backtrace info if properly configured" do
20
38
  options = {
21
39
  :api_token => 'good_token',
@@ -16,6 +16,25 @@ class IrcNotifierTest < ActiveSupport::TestCase
16
16
  irc.call(fake_exception)
17
17
  end
18
18
 
19
+ test "should call pre/post_callback if specified" do
20
+ pre_callback_called, post_callback_called = 0,0
21
+
22
+ options = {
23
+ :domain => 'irc.example.com',
24
+ :pre_callback => proc { |*| pre_callback_called += 1},
25
+ :post_callback => proc { |*| post_callback_called += 1}
26
+ }
27
+
28
+ CarrierPigeon.expects(:send).with(has_key(:uri)) do |v|
29
+ /divided by 0/.match(v[:message])
30
+ end
31
+
32
+ irc = ExceptionNotifier::IrcNotifier.new(options)
33
+ irc.call(fake_exception)
34
+ assert_equal(1, pre_callback_called)
35
+ assert_equal(1, post_callback_called)
36
+ end
37
+
19
38
  test "should send irc notification without backtrace info if properly configured" do
20
39
  options = {
21
40
  :domain => 'irc.example.com'
@@ -110,6 +110,35 @@ class SlackNotifierTest < ActiveSupport::TestCase
110
110
  slack_notifier.call(@exception, notification_options)
111
111
  end
112
112
 
113
+ test "should call pre/post_callback proc if specified" do
114
+ post_callback_called = 0
115
+ options = {
116
+ webhook_url: "http://slack.webhook.url",
117
+ username: "test",
118
+ custom_hook: "hook",
119
+ :pre_callback => proc { |opts, notifier, backtrace, message, message_opts|
120
+ (message_opts[:attachments] = []) << { text: "#{backtrace.join("\n")}", color: 'danger' }
121
+ },
122
+ :post_callback => proc { |opts, notifier, backtrace, message, message_opts|
123
+ post_callback_called = 1
124
+ },
125
+ additional_parameters: {
126
+ icon_url: "icon",
127
+ }
128
+ }
129
+
130
+ Slack::Notifier.any_instance.expects(:ping).with('',
131
+ {:icon_url => 'icon',
132
+ :attachments => [
133
+ {:text => "backtrace line 1\nbacktrace line 2",
134
+ :color => 'danger'}
135
+ ]})
136
+
137
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
138
+ slack_notifier.call(@exception)
139
+ assert_equal(post_callback_called, 1)
140
+ end
141
+
113
142
  private
114
143
 
115
144
  def fake_exception
@@ -25,6 +25,12 @@ class WebhookNotifierTest < ActiveSupport::TestCase
25
25
  assert response[:body][:data][:extra_data].has_key?(:data_item1)
26
26
  end
27
27
 
28
+ test "should call pre/post_callback if specified" do
29
+ HTTParty.stubs(:send).returns(fake_response)
30
+ webhook = ExceptionNotifier::WebhookNotifier.new({:url => 'http://localhost:8000'})
31
+ webhook.call(fake_exception)
32
+ end
33
+
28
34
  private
29
35
 
30
36
  def fake_response
@@ -98,4 +98,5 @@ class ExceptionNotifierTest < ActiveSupport::TestCase
98
98
 
99
99
  ExceptionNotifier.unregister_exception_notifier(:test)
100
100
  end
101
+
101
102
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exception_notification
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.2
4
+ version: 4.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamis Buck
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-12-04 00:00:00.000000000 Z
12
+ date: 2015-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionmailer
@@ -242,6 +242,7 @@ files:
242
242
  - lib/exception_notification/resque.rb
243
243
  - lib/exception_notification/sidekiq.rb
244
244
  - lib/exception_notifier.rb
245
+ - lib/exception_notifier/base_notifier.rb
245
246
  - lib/exception_notifier/campfire_notifier.rb
246
247
  - lib/exception_notifier/email_notifier.rb
247
248
  - lib/exception_notifier/hipchat_notifier.rb
@@ -353,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
354
  version: 1.8.11
354
355
  requirements: []
355
356
  rubyforge_project:
356
- rubygems_version: 2.4.5
357
+ rubygems_version: 2.4.5.1
357
358
  signing_key:
358
359
  specification_version: 4
359
360
  summary: Exception notification for Rails apps