exception_notification 4.1.0.rc1 → 4.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|