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 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
@@ -7,5 +7,9 @@ appraise "rails3_2" do
7
7
  end
8
8
 
9
9
  appraise "rails4_0" do
10
- gem 'rails', '4.0.0.rc2'
10
+ gem 'rails', '4.0.5'
11
+ end
12
+
13
+ appraise "rails4_1" do
14
+ gem 'rails', '~> 4.1.1'
11
15
  end
data/CHANGELOG.rdoc CHANGED
@@ -1,13 +1,19 @@
1
- == unreleased
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.rc1)
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.5.2)
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 (0.11.0)
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.3.6)
82
- multi_xml (0.5.3)
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.11.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.rc1'
3
+ s.version = '4.1.0.rc2'
4
4
  s.authors = ["Jamis Buck", "Josh Peek"]
5
- s.date = %q{2014-04-16}
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", ">= 0"
31
- s.add_development_dependency "hipchat", ">= 0.11.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
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.1.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path => "../"
@@ -4,4 +4,4 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rails", "~> 3.2.0"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path => "../"
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "4.0.0.rc2"
5
+ gem "rails", "4.0.5"
6
6
 
7
- gemspec :path=>"../"
7
+ gemspec :path => "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.1.1"
6
+
7
+ gemspec :path => "../"
@@ -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
- raise exception
45
+
46
+ raise exception unless exception.is_a?(CascadePassException)
47
+ response
34
48
  end
35
49
 
36
50
  private
@@ -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).deliver
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,11 @@
1
+ module BacktraceCleaner
2
+
3
+ def clean_backtrace(exception)
4
+ if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner)
5
+ Rails.backtrace_cleaner.send(:filter, exception.backtrace)
6
+ else
7
+ exception.backtrace
8
+ end
9
+ end
10
+
11
+ end
@@ -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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../../..
3
3
  specs:
4
- exception_notification (4.0.1)
4
+ exception_notification (4.1.0.rc1)
5
5
  actionmailer (>= 3.0.4)
6
6
  activesupport (>= 3.0.4)
7
7
 
@@ -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 to check this file into your version control system.
12
+ # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20110729022608) do
14
+ ActiveRecord::Schema.define(version: 20110729022608) do
15
15
 
16
- create_table "posts", :force => true do |t|
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", :null => false
21
- t.datetime "updated_at", :null => false
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.rc1
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: 2014-04-16 00:00:00.000000000 Z
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: '0'
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: '0'
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.11.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.11.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: 1.8.23
352
+ rubygems_version: 2.2.0
362
353
  signing_key:
363
- specification_version: 3
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