Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add slack notifier

  • Loading branch information...
commit bde62bd7834e346be448bcdd251e8a54ea15c340 1 parent 2cf3c5e
Martin Keogh martin1keogh authored
2  Gemfile.lock
View
@@ -127,6 +127,7 @@ GEM
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
+ slack-notifier (0.5.0)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
@@ -168,5 +169,6 @@ DEPENDENCIES
rails (>= 3.0.4)
resque (~> 1.2.0)
sidekiq (~> 3.0)
+ slack-notifier (>= 0.5)
sqlite3 (>= 1.3.4)
tinder (~> 1.8)
61 README.md
View
@@ -549,6 +549,67 @@ Join a channel. Default : false.
Nicks to include in the message. Default: []
+### Slack notifier
+
+This notifier sends notifications to a slack channel using the slack-notifier gem.
+
+#### Usage
+
+Just add the [slack-notifier](https://github.com/stevenosloan/slack-notifier) gem to your `Gemfile`:
+
+```ruby
+gem 'slack-notifier'
+```
+
+To configure it, you need to set at least the 'team' and 'token' options, like this:
+
+```ruby
+Whatever::Application.config.middleware.use ExceptionNotification::Rack,
+ :email => {
+ :email_prefix => "[Whatever] ",
+ :sender_address => %{"notifier" <notifier@example.com>},
+ :exception_recipients => %w{exceptions@example.com}
+ },
+ :slack => {
+ :team => "myteam",
+ :token => "secret-token",
+ :channel => "#exceptions"
+ }
+```
+
+#### Options
+
+##### team
+
+*String, required*
+
+The name of your team on slack.
+
+##### token
+
+*String, required*
+
+The API token to access your slack team's account.
+
+##### channel
+
+*String, optional*
+
+Message will appear in this channel. Defaults to the channel you set as such on slack.
+
+##### username
+
+*String, optional*
+
+Username of the bot. Default: 'ExceptionNotifierBot'.
+
+##### custom_hook
+
+*String, optional*
+
+Custom hook name. See [slack-notifier](https://github.com/stevenosloan/slack-notifier#custom-hook-name) for
+more information. Default: 'incoming-webhook'
+
### Custom notifier
Simply put, notifiers are objects which respond to `#call(exception, options)` method. Thus, a lambda can be used as a notifier as follow:
1  exception_notification.gemspec
View
@@ -30,4 +30,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "appraisal", "~> 1.0.0"
s.add_development_dependency "hipchat", ">= 1.0.0"
s.add_development_dependency "carrier-pigeon", ">= 0.7.0"
+ s.add_development_dependency "slack-notifier", ">= 0.5"
end
1  lib/exception_notifier.rb
View
@@ -10,6 +10,7 @@ module ExceptionNotifier
autoload :HipchatNotifier, 'exception_notifier/hipchat_notifier'
autoload :WebhookNotifier, 'exception_notifier/webhook_notifier'
autoload :IrcNotifier, 'exception_notifier/irc_notifier'
+ autoload :SlackNotifier, 'exception_notifier/slack_notifier'
class UndefinedNotifierError < StandardError; end
34 lib/exception_notifier/slack_notifier.rb
View
@@ -0,0 +1,34 @@
+module ExceptionNotifier
+ class SlackNotifier
+
+ attr_accessor :notifier
+
+ def initialize(options)
+ begin
+ team = options.fetch(:team)
+ token = options.fetch(:token)
+ custom_hook = options.fetch(:custom_hook, nil)
+ options[:username] ||= 'ExceptionNotifierBot'
+
+ if custom_hook.nil?
+ @notifier = Slack::Notifier.new team, token, options
+ else
+ @notifier = Slack::Notifier.new team, token, custom_hook, options
+ end
+ rescue
+ @notifier = nil
+ end
+ end
+
+ def call(exception, options={})
+ message = "An exception occurred: '#{exception.message}' on '#{exception.backtrace.first}'"
+ @notifier.ping message if valid?
+ end
+
+ protected
+
+ def valid?
+ !@notifier.nil?
+ end
+ end
+end
98 test/exception_notifier/slack_notifier_test.rb
View
@@ -0,0 +1,98 @@
+require 'test_helper'
+require 'slack-notifier'
+
+class SlackNotifierTest < ActiveSupport::TestCase
+
+ test "should send a slack notification if properly configured" do
+ options = {
+ token: "token",
+ team: "team"
+ }
+
+ Slack::Notifier.any_instance.expects(:ping).with(fake_notification)
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+ slack_notifier.call(fake_exception)
+ end
+
+ test "should send a notification as the specified hook" do
+ options = {
+ token: "token",
+ team: "team",
+ custom_hook: "custom"
+ }
+
+ Slack::Notifier.any_instance.expects(:ping).with(fake_notification)
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+ slack_notifier.call(fake_exception)
+
+ assert_equal slack_notifier.notifier.hook_name, options[:custom_hook]
+ end
+
+ test "should send the notification to the specified channel" do
+ options = {
+ token: "token",
+ team: "team",
+ channel: "channel"
+ }
+
+ Slack::Notifier.any_instance.expects(:ping).with(fake_notification)
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+ slack_notifier.call(fake_exception)
+
+ assert_equal slack_notifier.notifier.channel, options[:channel]
+ end
+
+ test "should send the notification to the specified username" do
+ options = {
+ token: "token",
+ team: "team",
+ username: "username"
+ }
+
+ Slack::Notifier.any_instance.expects(:ping).with(fake_notification)
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+ slack_notifier.call(fake_exception)
+
+ assert_equal slack_notifier.notifier.username, options[:username]
+ end
+
+ test "shouldn't send a slack notification if token is missing" do
+ options = {
+ team: "test"
+ }
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+
+ assert_nil slack_notifier.notifier
+ assert_nil slack_notifier.call(fake_exception)
+ end
+
+ test "shouldn't send a slack notification if team is missing" do
+ options = {
+ token: "test"
+ }
+
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
+
+ assert_nil slack_notifier.notifier
+ assert_nil slack_notifier.call(fake_exception)
+ end
+
+ private
+
+ def fake_exception
+ begin
+ 5/0
+ rescue Exception => e
+ e
+ end
+ end
+
+ def fake_notification
+ "An exception occurred: '#{fake_exception.message}' on '#{fake_exception.backtrace.first}'"
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.