exception_notification 4.1.0.rc1 → 4.1.0.rc2
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 +7 -0
- data/Appraisals +5 -1
- data/CHANGELOG.rdoc +7 -1
- data/Gemfile.lock +10 -7
- data/README.md +94 -0
- data/examples/sinatra/sinatra_app.rb +4 -0
- data/exception_notification.gemspec +5 -4
- data/gemfiles/rails3_1.gemfile +1 -1
- data/gemfiles/rails3_2.gemfile +1 -1
- data/gemfiles/rails4_0.gemfile +2 -2
- data/gemfiles/rails4_1.gemfile +7 -0
- data/lib/exception_notification/rack.rb +16 -2
- data/lib/exception_notifier.rb +3 -0
- data/lib/exception_notifier/email_notifier.rb +9 -9
- data/lib/exception_notifier/hipchat_notifier.rb +4 -1
- data/lib/exception_notifier/modules/backtrace_cleaner.rb +11 -0
- data/lib/exception_notifier/slack_notifier.rb +65 -0
- data/test/dummy/Gemfile.lock +1 -1
- data/test/dummy/db/schema.rb +5 -5
- data/test/exception_notification/rack_test.rb +20 -0
- data/test/exception_notifier/hipchat_notifier_test.rb +28 -3
- data/test/exception_notifier/slack_notifier_test.rb +117 -0
- data/test/test_helper.rb +0 -1
- metadata +58 -65
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2cbef6207c6476c2eccdb903add9e4709515d88c
|
4
|
+
data.tar.gz: c95e04ddf9ba60ff638438e5b8f162376c1f20bc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 433055525f4f5da401496349dc7739241f545edc4e936eef873c7aa1c16f0be2d9a68a0ec4487375557867378b5b90f6b173395b48cdca9328a673061315c962
|
7
|
+
data.tar.gz: b799cedfc4a17b08151180a62d6ae3bcaae300660bb295fa4f54806d586b4b7e52da1cae8c1988f8759dc1eb6439f2fb6100ba3246f62afbed9bc281ea2f4cbc
|
data/Appraisals
CHANGED
data/CHANGELOG.rdoc
CHANGED
@@ -1,13 +1,19 @@
|
|
1
|
-
==
|
1
|
+
== 4.1.0
|
2
2
|
|
3
3
|
* enhancements
|
4
4
|
* Add support for Sidekiq 3.0 (by @mbrictson)
|
5
5
|
* Add IRC notifier (by @nathanjsharpe)
|
6
6
|
* Add ActionController::UnknownFormat to default ignored exceptions (by @rezwyi)
|
7
7
|
* Add message_template option to HipChat notifier (by @makimoto)
|
8
|
+
* Add support for HipChat APIv2 (by @michaelherold)
|
9
|
+
* Add Slack notifier (by @martin1keogh)
|
10
|
+
* Add option for notifying on `X-Cascade` header (by @etipton)
|
11
|
+
* Improve backtrace data (by @munkius)
|
8
12
|
|
9
13
|
* bug fixes
|
10
14
|
* Fix `Rails.root` exception (by @hovatterz)
|
15
|
+
* Fix email notifier in Sinatra (by @betesh)
|
16
|
+
|
11
17
|
== 4.0.1
|
12
18
|
|
13
19
|
* enhancements
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
exception_notification (4.1.0.
|
4
|
+
exception_notification (4.1.0.rc2)
|
5
5
|
actionmailer (>= 3.0.4)
|
6
6
|
activesupport (>= 3.0.4)
|
7
7
|
|
@@ -36,9 +36,10 @@ GEM
|
|
36
36
|
i18n (~> 0.6)
|
37
37
|
multi_json (~> 1.0)
|
38
38
|
addressable (2.3.5)
|
39
|
-
appraisal (0.
|
39
|
+
appraisal (1.0.0)
|
40
40
|
bundler
|
41
41
|
rake
|
42
|
+
thor (>= 0.14.0)
|
42
43
|
arel (3.0.2)
|
43
44
|
builder (3.0.0)
|
44
45
|
carrier-pigeon (0.7.0)
|
@@ -61,7 +62,7 @@ GEM
|
|
61
62
|
faraday (>= 0.7.4, < 0.9)
|
62
63
|
hashie (1.2.0)
|
63
64
|
hike (1.2.1)
|
64
|
-
hipchat (
|
65
|
+
hipchat (1.2.0)
|
65
66
|
httparty
|
66
67
|
http_parser.rb (0.5.3)
|
67
68
|
httparty (0.10.2)
|
@@ -78,8 +79,8 @@ GEM
|
|
78
79
|
mime-types (1.19)
|
79
80
|
mocha (0.13.3)
|
80
81
|
metaclass (~> 0.0.1)
|
81
|
-
multi_json (1.
|
82
|
-
multi_xml (0.5.
|
82
|
+
multi_json (1.10.1)
|
83
|
+
multi_xml (0.5.5)
|
83
84
|
multipart-post (1.2.0)
|
84
85
|
polyglot (0.3.3)
|
85
86
|
rack (1.4.1)
|
@@ -126,6 +127,7 @@ GEM
|
|
126
127
|
multi_json (~> 1.0)
|
127
128
|
simplecov-html (~> 0.7.1)
|
128
129
|
simplecov-html (0.7.1)
|
130
|
+
slack-notifier (1.0.0)
|
129
131
|
sprockets (2.1.3)
|
130
132
|
hike (~> 1.2)
|
131
133
|
rack (~> 1.0)
|
@@ -157,15 +159,16 @@ PLATFORMS
|
|
157
159
|
ruby
|
158
160
|
|
159
161
|
DEPENDENCIES
|
160
|
-
appraisal
|
162
|
+
appraisal (~> 1.0.0)
|
161
163
|
carrier-pigeon (>= 0.7.0)
|
162
164
|
coveralls (~> 0.6.5)
|
163
165
|
exception_notification!
|
164
|
-
hipchat (>= 0.
|
166
|
+
hipchat (>= 1.0.0)
|
165
167
|
httparty (~> 0.10.2)
|
166
168
|
mocha (>= 0.13.0)
|
167
169
|
rails (>= 3.0.4)
|
168
170
|
resque (~> 1.2.0)
|
169
171
|
sidekiq (~> 3.0)
|
172
|
+
slack-notifier (>= 1.0.0)
|
170
173
|
sqlite3 (>= 1.3.4)
|
171
174
|
tinder (~> 1.8)
|
data/README.md
CHANGED
@@ -549,6 +549,89 @@ Join a channel. Default : false.
|
|
549
549
|
|
550
550
|
Nicks to include in the message. Default: []
|
551
551
|
|
552
|
+
### Slack notifier
|
553
|
+
|
554
|
+
This notifier sends notifications to a slack channel using the slack-notifier gem.
|
555
|
+
|
556
|
+
#### Usage
|
557
|
+
|
558
|
+
Just add the [slack-notifier](https://github.com/stevenosloan/slack-notifier) gem to your `Gemfile`:
|
559
|
+
|
560
|
+
```ruby
|
561
|
+
gem 'slack-notifier'
|
562
|
+
```
|
563
|
+
|
564
|
+
To configure it, you need to set at least the 'webhook_url' option, like this:
|
565
|
+
|
566
|
+
```ruby
|
567
|
+
Whatever::Application.config.middleware.use ExceptionNotification::Rack,
|
568
|
+
:email => {
|
569
|
+
:email_prefix => "[Whatever] ",
|
570
|
+
:sender_address => %{"notifier" <notifier@example.com>},
|
571
|
+
:exception_recipients => %w{exceptions@example.com}
|
572
|
+
},
|
573
|
+
:slack => {
|
574
|
+
:webhook_url => "[Your webhook url]",
|
575
|
+
:channel => "#exceptions",
|
576
|
+
:additional_parameters => {
|
577
|
+
:icon_url => "http://image.jpg",
|
578
|
+
:mrkdwn => true
|
579
|
+
}
|
580
|
+
}
|
581
|
+
```
|
582
|
+
|
583
|
+
The slack notification will include any data saved under `env["exception_notifier.exception_data"]`. If you find this too verbose, you can determine to exclude certain information by doing the following:
|
584
|
+
|
585
|
+
```ruby
|
586
|
+
Whatever::Application.config.middleware.use ExceptionNotification::Rack,
|
587
|
+
:slack => {
|
588
|
+
:webhook_url => "[Your webhook url]",
|
589
|
+
:channel => "#exceptions",
|
590
|
+
:additional_parameters => {
|
591
|
+
:icon_url => "http://image.jpg",
|
592
|
+
:mrkdwn => true
|
593
|
+
},
|
594
|
+
:ignore_data_if => lambda {|key, value|
|
595
|
+
"#{key}" == 'key_to_ignore' || value.is_a?(ClassToBeIgnored)
|
596
|
+
}
|
597
|
+
}
|
598
|
+
```
|
599
|
+
|
600
|
+
Any evaluation to `true` will cause the key / value pair not be be sent along to Slack.
|
601
|
+
|
602
|
+
#### Options
|
603
|
+
|
604
|
+
##### webhook_url
|
605
|
+
|
606
|
+
*String, required*
|
607
|
+
|
608
|
+
The Incoming WebHook URL on slack.
|
609
|
+
|
610
|
+
##### channel
|
611
|
+
|
612
|
+
*String, optional*
|
613
|
+
|
614
|
+
Message will appear in this channel. Defaults to the channel you set as such on slack.
|
615
|
+
|
616
|
+
##### username
|
617
|
+
|
618
|
+
*String, optional*
|
619
|
+
|
620
|
+
Username of the bot. Defaults to the name you set as such on slack
|
621
|
+
|
622
|
+
##### custom_hook
|
623
|
+
|
624
|
+
*String, optional*
|
625
|
+
|
626
|
+
Custom hook name. See [slack-notifier](https://github.com/stevenosloan/slack-notifier#custom-hook-name) for
|
627
|
+
more information. Default: 'incoming-webhook'
|
628
|
+
|
629
|
+
##### additional_parameters
|
630
|
+
|
631
|
+
*Hash of strings, optional*
|
632
|
+
|
633
|
+
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: '{}'
|
634
|
+
|
552
635
|
### Custom notifier
|
553
636
|
|
554
637
|
Simply put, notifiers are objects which respond to `#call(exception, options)` method. Thus, a lambda can be used as a notifier as follow:
|
@@ -656,6 +739,17 @@ Whatever::Application.config.middleware.use ExceptionNotification::Rack,
|
|
656
739
|
|
657
740
|
You can make use of both the environment and the exception inside the lambda to decide wether to avoid or not sending the notification.
|
658
741
|
|
742
|
+
## Rack X-Cascade Header
|
743
|
+
|
744
|
+
Some rack apps (Rails in particular) utilize the "X-Cascade" header to pass the request-handling responsibility to the next middleware in the stack.
|
745
|
+
|
746
|
+
Rails' routing middleware uses this strategy, rather than raising an exception, to handle routing errors (e.g. 404s); to be notified whenever a 404 occurs, set this option to "false."
|
747
|
+
|
748
|
+
### :ignore_cascade_pass
|
749
|
+
|
750
|
+
*Boolean, default: true*
|
751
|
+
|
752
|
+
Set to false to trigger notifications when another rack middleware sets the "X-Cascade" header to "pass."
|
659
753
|
|
660
754
|
## Background Notifications
|
661
755
|
|
@@ -4,6 +4,10 @@ require 'sinatra/base'
|
|
4
4
|
require 'exception_notification'
|
5
5
|
|
6
6
|
class SinatraApp < Sinatra::Base
|
7
|
+
use Rack::Config do |env|
|
8
|
+
env["action_dispatch.parameter_filter"] = [:password] # This is highly recommended. It will prevent the ExceptionNotification email from including your users' passwords
|
9
|
+
end
|
10
|
+
|
7
11
|
use ExceptionNotification::Rack,
|
8
12
|
:email => {
|
9
13
|
:email_prefix => "[Example] ",
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'exception_notification'
|
3
|
-
s.version = '4.1.0.
|
3
|
+
s.version = '4.1.0.rc2'
|
4
4
|
s.authors = ["Jamis Buck", "Josh Peek"]
|
5
|
-
s.date = %q{
|
5
|
+
s.date = %q{2015-03-25}
|
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"
|
@@ -27,7 +27,8 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency "mocha", ">= 0.13.0"
|
28
28
|
s.add_development_dependency "sqlite3", ">= 1.3.4"
|
29
29
|
s.add_development_dependency "coveralls", "~> 0.6.5"
|
30
|
-
s.add_development_dependency "appraisal", "
|
31
|
-
s.add_development_dependency "hipchat", ">= 0.
|
30
|
+
s.add_development_dependency "appraisal", "~> 1.0.0"
|
31
|
+
s.add_development_dependency "hipchat", ">= 1.0.0"
|
32
32
|
s.add_development_dependency "carrier-pigeon", ">= 0.7.0"
|
33
|
+
s.add_development_dependency "slack-notifier", ">= 1.0.0"
|
33
34
|
end
|
data/gemfiles/rails3_1.gemfile
CHANGED
data/gemfiles/rails3_2.gemfile
CHANGED
data/gemfiles/rails4_0.gemfile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module ExceptionNotification
|
2
2
|
class Rack
|
3
|
+
class CascadePassException < Exception; end
|
4
|
+
|
3
5
|
def initialize(app, options = {})
|
4
6
|
@app = app
|
5
7
|
|
@@ -19,18 +21,30 @@ module ExceptionNotification
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
24
|
+
@ignore_cascade_pass = options.delete(:ignore_cascade_pass) { true }
|
25
|
+
|
22
26
|
options.each do |notifier_name, options|
|
23
27
|
ExceptionNotifier.register_exception_notifier(notifier_name, options)
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def call(env)
|
28
|
-
@app.call(env)
|
32
|
+
_, headers, _ = response = @app.call(env)
|
33
|
+
|
34
|
+
if !@ignore_cascade_pass && headers['X-Cascade'] == 'pass'
|
35
|
+
msg = "This exception means that the preceding Rack middleware set the 'X-Cascade' header to 'pass' -- in " <<
|
36
|
+
"Rails, this often means that the route was not found (404 error)."
|
37
|
+
raise CascadePassException, msg
|
38
|
+
end
|
39
|
+
|
40
|
+
response
|
29
41
|
rescue Exception => exception
|
30
42
|
if ExceptionNotifier.notify_exception(exception, :env => env)
|
31
43
|
env['exception_notifier.delivered'] = true
|
32
44
|
end
|
33
|
-
|
45
|
+
|
46
|
+
raise exception unless exception.is_a?(CascadePassException)
|
47
|
+
response
|
34
48
|
end
|
35
49
|
|
36
50
|
private
|
data/lib/exception_notifier.rb
CHANGED
@@ -4,12 +4,15 @@ require 'active_support/core_ext/module/attribute_accessors'
|
|
4
4
|
|
5
5
|
module ExceptionNotifier
|
6
6
|
|
7
|
+
autoload :BacktraceCleaner, 'exception_notifier/modules/backtrace_cleaner'
|
8
|
+
|
7
9
|
autoload :Notifier, 'exception_notifier/notifier'
|
8
10
|
autoload :EmailNotifier, 'exception_notifier/email_notifier'
|
9
11
|
autoload :CampfireNotifier, 'exception_notifier/campfire_notifier'
|
10
12
|
autoload :HipchatNotifier, 'exception_notifier/hipchat_notifier'
|
11
13
|
autoload :WebhookNotifier, 'exception_notifier/webhook_notifier'
|
12
14
|
autoload :IrcNotifier, 'exception_notifier/irc_notifier'
|
15
|
+
autoload :SlackNotifier, 'exception_notifier/slack_notifier'
|
13
16
|
|
14
17
|
class UndefinedNotifierError < StandardError; end
|
15
18
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "active_support/core_ext/hash/reverse_merge"
|
1
2
|
require 'action_mailer'
|
2
3
|
require 'action_dispatch'
|
3
4
|
require 'pp'
|
@@ -16,6 +17,8 @@ module ExceptionNotifier
|
|
16
17
|
|
17
18
|
def self.extended(base)
|
18
19
|
base.class_eval do
|
20
|
+
base.include BacktraceCleaner
|
21
|
+
|
19
22
|
# Append application view path to the ExceptionNotifier lookup context.
|
20
23
|
self.append_view_path "#{File.dirname(__FILE__)}/views"
|
21
24
|
|
@@ -64,14 +67,6 @@ module ExceptionNotifier
|
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
67
|
-
def clean_backtrace(exception)
|
68
|
-
if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
|
69
|
-
Rails.backtrace_cleaner.send(:filter, exception.backtrace)
|
70
|
-
else
|
71
|
-
exception.backtrace
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
70
|
helper_method :inspect_object
|
76
71
|
|
77
72
|
def inspect_object(object)
|
@@ -145,7 +140,12 @@ module ExceptionNotifier
|
|
145
140
|
end
|
146
141
|
|
147
142
|
def call(exception, options={})
|
148
|
-
create_email(exception, options)
|
143
|
+
message = create_email(exception, options)
|
144
|
+
if message.respond_to?(:deliver_now)
|
145
|
+
message.deliver_now
|
146
|
+
else
|
147
|
+
message.deliver
|
148
|
+
end
|
149
149
|
end
|
150
150
|
|
151
151
|
def create_email(exception, options={})
|
@@ -9,8 +9,11 @@ module ExceptionNotifier
|
|
9
9
|
begin
|
10
10
|
api_token = options.delete(:api_token)
|
11
11
|
room_name = options.delete(:room_name)
|
12
|
+
opts = {
|
13
|
+
:api_version => options.delete(:api_version) || 'v1'
|
14
|
+
}
|
12
15
|
@from = options.delete(:from) || 'Exception'
|
13
|
-
@room = HipChat::Client.new(api_token)[room_name]
|
16
|
+
@room = HipChat::Client.new(api_token, opts)[room_name]
|
14
17
|
@message_template = options.delete(:message_template) || ->(exception) {
|
15
18
|
"A new exception occurred: '#{exception.message}' on '#{exception.backtrace.first}'"
|
16
19
|
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ExceptionNotifier
|
2
|
+
class SlackNotifier
|
3
|
+
include BacktraceCleaner
|
4
|
+
|
5
|
+
attr_accessor :notifier
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
begin
|
9
|
+
@ignore_data_if = options[:ignore_data_if]
|
10
|
+
|
11
|
+
webhook_url = options.fetch(:webhook_url)
|
12
|
+
@message_opts = options.fetch(:additional_parameters, {})
|
13
|
+
@notifier = Slack::Notifier.new webhook_url, options
|
14
|
+
rescue
|
15
|
+
@notifier = nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(exception, options={})
|
20
|
+
message = "An exception occurred: '#{exception.message}' on '#{exception.backtrace.first}'"
|
21
|
+
|
22
|
+
message = enrich_message_with_data(message, options)
|
23
|
+
message = enrich_message_with_backtrace(message, exception)
|
24
|
+
|
25
|
+
@notifier.ping(message, @message_opts) if valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def valid?
|
31
|
+
!@notifier.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def enrich_message_with_data(message, options)
|
35
|
+
def deep_reject(hash, block)
|
36
|
+
hash.each do |k, v|
|
37
|
+
if v.is_a?(Hash)
|
38
|
+
deep_reject(v, block)
|
39
|
+
end
|
40
|
+
|
41
|
+
if block.call(k, v)
|
42
|
+
hash.delete(k)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
data = ((options[:env] || {})['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
|
48
|
+
deep_reject(data, @ignore_data_if) if @ignore_data_if.is_a?(Proc)
|
49
|
+
text = data.map{|k,v| "#{k}: #{v}"}.join(', ')
|
50
|
+
|
51
|
+
if text.present?
|
52
|
+
text = ['*Data:*', text].join("\n")
|
53
|
+
[message, text].join("\n")
|
54
|
+
else
|
55
|
+
message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def enrich_message_with_backtrace(message, exception)
|
60
|
+
backtrace = clean_backtrace(exception).first(10).join("\n")
|
61
|
+
[message, ['*Backtrace:*', backtrace]].join("\n")
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
data/test/dummy/Gemfile.lock
CHANGED
data/test/dummy/db/schema.rb
CHANGED
@@ -9,16 +9,16 @@
|
|
9
9
|
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
10
|
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
11
|
#
|
12
|
-
# It's strongly recommended
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:
|
14
|
+
ActiveRecord::Schema.define(version: 20110729022608) do
|
15
15
|
|
16
|
-
create_table "posts", :
|
16
|
+
create_table "posts", force: true do |t|
|
17
17
|
t.string "title"
|
18
18
|
t.text "body"
|
19
19
|
t.string "secret"
|
20
|
-
t.datetime "created_at"
|
21
|
-
t.datetime "updated_at"
|
20
|
+
t.datetime "created_at"
|
21
|
+
t.datetime "updated_at"
|
22
22
|
end
|
23
23
|
|
24
24
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RackTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
@pass_app = Object.new
|
7
|
+
@pass_app.stubs(:call).returns([nil, { 'X-Cascade' => 'pass' }, nil])
|
8
|
+
end
|
9
|
+
|
10
|
+
test "should ignore \"X-Cascade\" header by default" do
|
11
|
+
ExceptionNotifier.expects(:notify_exception).never
|
12
|
+
ExceptionNotification::Rack.new(@pass_app).call({})
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should notify on \"X-Cascade\" = \"pass\" if ignore_cascade_pass option is false" do
|
16
|
+
ExceptionNotifier.expects(:notify_exception).once
|
17
|
+
ExceptionNotification::Rack.new(@pass_app, :ignore_cascade_pass => false).call({})
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -35,7 +35,7 @@ class HipchatNotifierTest < ActiveSupport::TestCase
|
|
35
35
|
:room_name => 'test_room'
|
36
36
|
}
|
37
37
|
|
38
|
-
HipChat::Client.stubs(:new).with('bad_token').returns(nil)
|
38
|
+
HipChat::Client.stubs(:new).with('bad_token', {:api_version => 'v1'}).returns(nil)
|
39
39
|
|
40
40
|
hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
|
41
41
|
assert_nil hipchat.room
|
@@ -44,7 +44,7 @@ class HipchatNotifierTest < ActiveSupport::TestCase
|
|
44
44
|
test "should not send hipchat notification if api_key is missing" do
|
45
45
|
wrong_params = {:room_name => 'test_room'}
|
46
46
|
|
47
|
-
HipChat::Client.stubs(:new).with(nil).returns(nil)
|
47
|
+
HipChat::Client.stubs(:new).with(nil, {:api_version => 'v1'}).returns(nil)
|
48
48
|
|
49
49
|
hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
|
50
50
|
assert_nil hipchat.room
|
@@ -53,7 +53,7 @@ class HipchatNotifierTest < ActiveSupport::TestCase
|
|
53
53
|
test "should not send hipchat notification if room_name is missing" do
|
54
54
|
wrong_params = {:api_token => 'good_token'}
|
55
55
|
|
56
|
-
HipChat::Client.stubs(:new).with('good_token').returns({})
|
56
|
+
HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v1'}).returns({})
|
57
57
|
|
58
58
|
hipchat = ExceptionNotifier::HipchatNotifier.new(wrong_params)
|
59
59
|
assert_nil hipchat.room
|
@@ -73,6 +73,31 @@ class HipchatNotifierTest < ActiveSupport::TestCase
|
|
73
73
|
hipchat.call(fake_exception)
|
74
74
|
end
|
75
75
|
|
76
|
+
test "should use APIv1 if api_version is not specified" do
|
77
|
+
options = {
|
78
|
+
:api_token => 'good_token',
|
79
|
+
:room_name => 'room_name',
|
80
|
+
}
|
81
|
+
|
82
|
+
HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v1'}).returns({})
|
83
|
+
|
84
|
+
hipchat = ExceptionNotifier::HipchatNotifier.new(options)
|
85
|
+
hipchat.call(fake_exception)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "should use APIv2 when specified" do
|
89
|
+
options = {
|
90
|
+
:api_token => 'good_token',
|
91
|
+
:room_name => 'room_name',
|
92
|
+
:api_version => 'v2',
|
93
|
+
}
|
94
|
+
|
95
|
+
HipChat::Client.stubs(:new).with('good_token', {:api_version => 'v2'}).returns({})
|
96
|
+
|
97
|
+
hipchat = ExceptionNotifier::HipchatNotifier.new(options)
|
98
|
+
hipchat.call(fake_exception)
|
99
|
+
end
|
100
|
+
|
76
101
|
private
|
77
102
|
|
78
103
|
def fake_body
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'slack-notifier'
|
3
|
+
|
4
|
+
class SlackNotifierTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@exception = fake_exception
|
8
|
+
@exception.stubs(:backtrace).returns(["backtrace line 1", "backtrace line 2"])
|
9
|
+
@exception.stubs(:message).returns('exception message')
|
10
|
+
end
|
11
|
+
|
12
|
+
test "should send a slack notification if properly configured" do
|
13
|
+
options = {
|
14
|
+
webhook_url: "http://slack.webhook.url"
|
15
|
+
}
|
16
|
+
|
17
|
+
Slack::Notifier.any_instance.expects(:ping).with(fake_notification, {})
|
18
|
+
|
19
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
20
|
+
slack_notifier.call(@exception)
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should send the notification to the specified channel" do
|
24
|
+
options = {
|
25
|
+
webhook_url: "http://slack.webhook.url",
|
26
|
+
channel: "channel"
|
27
|
+
}
|
28
|
+
|
29
|
+
Slack::Notifier.any_instance.expects(:ping).with(fake_notification, {})
|
30
|
+
|
31
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
32
|
+
slack_notifier.call(@exception)
|
33
|
+
|
34
|
+
assert_equal slack_notifier.notifier.channel, options[:channel]
|
35
|
+
end
|
36
|
+
|
37
|
+
test "should send the notification to the specified username" do
|
38
|
+
options = {
|
39
|
+
webhook_url: "http://slack.webhook.url",
|
40
|
+
username: "username"
|
41
|
+
}
|
42
|
+
|
43
|
+
Slack::Notifier.any_instance.expects(:ping).with(fake_notification, {})
|
44
|
+
|
45
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
46
|
+
slack_notifier.call(@exception)
|
47
|
+
|
48
|
+
assert_equal slack_notifier.notifier.username, options[:username]
|
49
|
+
end
|
50
|
+
|
51
|
+
test "should pass the additional parameters to Slack::Notifier.ping" do
|
52
|
+
options = {
|
53
|
+
webhook_url: "http://slack.webhook.url",
|
54
|
+
username: "test",
|
55
|
+
custom_hook: "hook",
|
56
|
+
additional_parameters: {
|
57
|
+
icon_url: "icon",
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
Slack::Notifier.any_instance.expects(:ping).with(fake_notification, {icon_url: "icon"})
|
62
|
+
|
63
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
64
|
+
slack_notifier.call(@exception)
|
65
|
+
end
|
66
|
+
|
67
|
+
test "shouldn't send a slack notification if webhook url is missing" do
|
68
|
+
options = {}
|
69
|
+
|
70
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
71
|
+
|
72
|
+
assert_nil slack_notifier.notifier
|
73
|
+
assert_nil slack_notifier.call(fake_exception)
|
74
|
+
end
|
75
|
+
|
76
|
+
test "should pass along environment data" do
|
77
|
+
options = {
|
78
|
+
webhook_url: "http://slack.webhook.url",
|
79
|
+
ignore_data_if: lambda {|k,v|
|
80
|
+
"#{k}" == 'key_to_be_ignored' || v.is_a?(Hash)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
notification_options = {
|
85
|
+
env: {
|
86
|
+
'exception_notifier.exception_data' => {foo: 'bar', john: 'doe'}
|
87
|
+
},
|
88
|
+
data: {
|
89
|
+
'user_id' => 5,
|
90
|
+
'key_to_be_ignored' => 'whatever',
|
91
|
+
'ignore_as_well' => {what: 'ever'}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
expected_data_string = 'foo: bar, john: doe, user_id: 5'
|
96
|
+
|
97
|
+
Slack::Notifier.any_instance.expects(:ping).with(fake_notification(@exception, expected_data_string), {})
|
98
|
+
slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
|
99
|
+
slack_notifier.call(@exception, notification_options)
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def fake_exception
|
105
|
+
begin
|
106
|
+
5/0
|
107
|
+
rescue Exception => e
|
108
|
+
e
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def fake_notification(exception=@exception, data_string=nil)
|
113
|
+
message = "An exception occurred: '#{exception.message}' on '#{exception.backtrace.first}'\n"
|
114
|
+
message += "*Data:*\n#{data_string}\n" unless data_string.nil?
|
115
|
+
message += "*Backtrace:*\n" + exception.backtrace.join("\n")
|
116
|
+
end
|
117
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -12,7 +12,6 @@ require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
|
12
12
|
require "rails/test_help"
|
13
13
|
require File.expand_path("../dummy/test/test_helper.rb", __FILE__)
|
14
14
|
|
15
|
-
require "test/unit"
|
16
15
|
require "mocha/setup"
|
17
16
|
|
18
17
|
Rails.backtrace_cleaner.remove_silencers!
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exception_notification
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.0.
|
5
|
-
prerelease: 6
|
4
|
+
version: 4.1.0.rc2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jamis Buck
|
@@ -10,216 +9,204 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2015-03-25 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: actionmailer
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - ">="
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: 3.0.4
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - ">="
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: 3.0.4
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: activesupport
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - ">="
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: 3.0.4
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - ">="
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: 3.0.4
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rails
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - ">="
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: 3.0.4
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - ">="
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: 3.0.4
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: resque
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- - ~>
|
60
|
+
- - "~>"
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: 1.2.0
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- - ~>
|
67
|
+
- - "~>"
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: 1.2.0
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: sidekiq
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- - ~>
|
74
|
+
- - "~>"
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '3.0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- - ~>
|
81
|
+
- - "~>"
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '3.0'
|
95
84
|
- !ruby/object:Gem::Dependency
|
96
85
|
name: tinder
|
97
86
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
87
|
requirements:
|
100
|
-
- - ~>
|
88
|
+
- - "~>"
|
101
89
|
- !ruby/object:Gem::Version
|
102
90
|
version: '1.8'
|
103
91
|
type: :development
|
104
92
|
prerelease: false
|
105
93
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
94
|
requirements:
|
108
|
-
- - ~>
|
95
|
+
- - "~>"
|
109
96
|
- !ruby/object:Gem::Version
|
110
97
|
version: '1.8'
|
111
98
|
- !ruby/object:Gem::Dependency
|
112
99
|
name: httparty
|
113
100
|
requirement: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
101
|
requirements:
|
116
|
-
- - ~>
|
102
|
+
- - "~>"
|
117
103
|
- !ruby/object:Gem::Version
|
118
104
|
version: 0.10.2
|
119
105
|
type: :development
|
120
106
|
prerelease: false
|
121
107
|
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
108
|
requirements:
|
124
|
-
- - ~>
|
109
|
+
- - "~>"
|
125
110
|
- !ruby/object:Gem::Version
|
126
111
|
version: 0.10.2
|
127
112
|
- !ruby/object:Gem::Dependency
|
128
113
|
name: mocha
|
129
114
|
requirement: !ruby/object:Gem::Requirement
|
130
|
-
none: false
|
131
115
|
requirements:
|
132
|
-
- -
|
116
|
+
- - ">="
|
133
117
|
- !ruby/object:Gem::Version
|
134
118
|
version: 0.13.0
|
135
119
|
type: :development
|
136
120
|
prerelease: false
|
137
121
|
version_requirements: !ruby/object:Gem::Requirement
|
138
|
-
none: false
|
139
122
|
requirements:
|
140
|
-
- -
|
123
|
+
- - ">="
|
141
124
|
- !ruby/object:Gem::Version
|
142
125
|
version: 0.13.0
|
143
126
|
- !ruby/object:Gem::Dependency
|
144
127
|
name: sqlite3
|
145
128
|
requirement: !ruby/object:Gem::Requirement
|
146
|
-
none: false
|
147
129
|
requirements:
|
148
|
-
- -
|
130
|
+
- - ">="
|
149
131
|
- !ruby/object:Gem::Version
|
150
132
|
version: 1.3.4
|
151
133
|
type: :development
|
152
134
|
prerelease: false
|
153
135
|
version_requirements: !ruby/object:Gem::Requirement
|
154
|
-
none: false
|
155
136
|
requirements:
|
156
|
-
- -
|
137
|
+
- - ">="
|
157
138
|
- !ruby/object:Gem::Version
|
158
139
|
version: 1.3.4
|
159
140
|
- !ruby/object:Gem::Dependency
|
160
141
|
name: coveralls
|
161
142
|
requirement: !ruby/object:Gem::Requirement
|
162
|
-
none: false
|
163
143
|
requirements:
|
164
|
-
- - ~>
|
144
|
+
- - "~>"
|
165
145
|
- !ruby/object:Gem::Version
|
166
146
|
version: 0.6.5
|
167
147
|
type: :development
|
168
148
|
prerelease: false
|
169
149
|
version_requirements: !ruby/object:Gem::Requirement
|
170
|
-
none: false
|
171
150
|
requirements:
|
172
|
-
- - ~>
|
151
|
+
- - "~>"
|
173
152
|
- !ruby/object:Gem::Version
|
174
153
|
version: 0.6.5
|
175
154
|
- !ruby/object:Gem::Dependency
|
176
155
|
name: appraisal
|
177
156
|
requirement: !ruby/object:Gem::Requirement
|
178
|
-
none: false
|
179
157
|
requirements:
|
180
|
-
- -
|
158
|
+
- - "~>"
|
181
159
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
160
|
+
version: 1.0.0
|
183
161
|
type: :development
|
184
162
|
prerelease: false
|
185
163
|
version_requirements: !ruby/object:Gem::Requirement
|
186
|
-
none: false
|
187
164
|
requirements:
|
188
|
-
- -
|
165
|
+
- - "~>"
|
189
166
|
- !ruby/object:Gem::Version
|
190
|
-
version:
|
167
|
+
version: 1.0.0
|
191
168
|
- !ruby/object:Gem::Dependency
|
192
169
|
name: hipchat
|
193
170
|
requirement: !ruby/object:Gem::Requirement
|
194
|
-
none: false
|
195
171
|
requirements:
|
196
|
-
- -
|
172
|
+
- - ">="
|
197
173
|
- !ruby/object:Gem::Version
|
198
|
-
version: 0.
|
174
|
+
version: 1.0.0
|
199
175
|
type: :development
|
200
176
|
prerelease: false
|
201
177
|
version_requirements: !ruby/object:Gem::Requirement
|
202
|
-
none: false
|
203
178
|
requirements:
|
204
|
-
- -
|
179
|
+
- - ">="
|
205
180
|
- !ruby/object:Gem::Version
|
206
|
-
version: 0.
|
181
|
+
version: 1.0.0
|
207
182
|
- !ruby/object:Gem::Dependency
|
208
183
|
name: carrier-pigeon
|
209
184
|
requirement: !ruby/object:Gem::Requirement
|
210
|
-
none: false
|
211
185
|
requirements:
|
212
|
-
- -
|
186
|
+
- - ">="
|
213
187
|
- !ruby/object:Gem::Version
|
214
188
|
version: 0.7.0
|
215
189
|
type: :development
|
216
190
|
prerelease: false
|
217
191
|
version_requirements: !ruby/object:Gem::Requirement
|
218
|
-
none: false
|
219
192
|
requirements:
|
220
|
-
- -
|
193
|
+
- - ">="
|
221
194
|
- !ruby/object:Gem::Version
|
222
195
|
version: 0.7.0
|
196
|
+
- !ruby/object:Gem::Dependency
|
197
|
+
name: slack-notifier
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: 1.0.0
|
203
|
+
type: :development
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - ">="
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: 1.0.0
|
223
210
|
description:
|
224
211
|
email: smartinez87@gmail.com
|
225
212
|
executables: []
|
@@ -244,6 +231,7 @@ files:
|
|
244
231
|
- gemfiles/rails3_1.gemfile
|
245
232
|
- gemfiles/rails3_2.gemfile
|
246
233
|
- gemfiles/rails4_0.gemfile
|
234
|
+
- gemfiles/rails4_1.gemfile
|
247
235
|
- lib/exception_notification.rb
|
248
236
|
- lib/exception_notification/rack.rb
|
249
237
|
- lib/exception_notification/rails.rb
|
@@ -254,7 +242,9 @@ files:
|
|
254
242
|
- lib/exception_notifier/email_notifier.rb
|
255
243
|
- lib/exception_notifier/hipchat_notifier.rb
|
256
244
|
- lib/exception_notifier/irc_notifier.rb
|
245
|
+
- lib/exception_notifier/modules/backtrace_cleaner.rb
|
257
246
|
- lib/exception_notifier/notifier.rb
|
247
|
+
- lib/exception_notifier/slack_notifier.rb
|
258
248
|
- lib/exception_notifier/views/exception_notifier/_backtrace.html.erb
|
259
249
|
- lib/exception_notifier/views/exception_notifier/_backtrace.text.erb
|
260
250
|
- lib/exception_notifier/views/exception_notifier/_data.html.erb
|
@@ -329,38 +319,39 @@ files:
|
|
329
319
|
- test/dummy/test/fixtures/posts.yml
|
330
320
|
- test/dummy/test/functional/posts_controller_test.rb
|
331
321
|
- test/dummy/test/test_helper.rb
|
322
|
+
- test/exception_notification/rack_test.rb
|
332
323
|
- test/exception_notifier/campfire_notifier_test.rb
|
333
324
|
- test/exception_notifier/email_notifier_test.rb
|
334
325
|
- test/exception_notifier/hipchat_notifier_test.rb
|
335
326
|
- test/exception_notifier/irc_notifier_test.rb
|
336
327
|
- test/exception_notifier/sidekiq_test.rb
|
328
|
+
- test/exception_notifier/slack_notifier_test.rb
|
337
329
|
- test/exception_notifier/webhook_notifier_test.rb
|
338
330
|
- test/exception_notifier_test.rb
|
339
331
|
- test/test_helper.rb
|
340
332
|
homepage: http://smartinez87.github.com/exception_notification
|
341
333
|
licenses:
|
342
334
|
- MIT
|
335
|
+
metadata: {}
|
343
336
|
post_install_message:
|
344
337
|
rdoc_options: []
|
345
338
|
require_paths:
|
346
339
|
- lib
|
347
340
|
required_ruby_version: !ruby/object:Gem::Requirement
|
348
|
-
none: false
|
349
341
|
requirements:
|
350
|
-
- -
|
342
|
+
- - ">="
|
351
343
|
- !ruby/object:Gem::Version
|
352
344
|
version: 1.9.3
|
353
345
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
354
|
-
none: false
|
355
346
|
requirements:
|
356
|
-
- -
|
347
|
+
- - ">="
|
357
348
|
- !ruby/object:Gem::Version
|
358
349
|
version: 1.8.11
|
359
350
|
requirements: []
|
360
351
|
rubyforge_project:
|
361
|
-
rubygems_version:
|
352
|
+
rubygems_version: 2.2.0
|
362
353
|
signing_key:
|
363
|
-
specification_version:
|
354
|
+
specification_version: 4
|
364
355
|
summary: Exception notification for Rails apps
|
365
356
|
test_files:
|
366
357
|
- test/dummy/.gitignore
|
@@ -418,11 +409,13 @@ test_files:
|
|
418
409
|
- test/dummy/test/fixtures/posts.yml
|
419
410
|
- test/dummy/test/functional/posts_controller_test.rb
|
420
411
|
- test/dummy/test/test_helper.rb
|
412
|
+
- test/exception_notification/rack_test.rb
|
421
413
|
- test/exception_notifier/campfire_notifier_test.rb
|
422
414
|
- test/exception_notifier/email_notifier_test.rb
|
423
415
|
- test/exception_notifier/hipchat_notifier_test.rb
|
424
416
|
- test/exception_notifier/irc_notifier_test.rb
|
425
417
|
- test/exception_notifier/sidekiq_test.rb
|
418
|
+
- test/exception_notifier/slack_notifier_test.rb
|
426
419
|
- test/exception_notifier/webhook_notifier_test.rb
|
427
420
|
- test/exception_notifier_test.rb
|
428
421
|
- test/test_helper.rb
|