Commit b30649f358f894990bdad4024ce5092dff77965b

Authored by Sergey Nartimov
1 parent 3cce72f0
Exists in master and in 1 other branch production

hipchat nofications

@@ -33,6 +33,7 @@ gem 'rack-ssl-enforcer' @@ -33,6 +33,7 @@ gem 'rack-ssl-enforcer'
33 gem 'fabrication', "~> 1.3.0" # Both for tests, and loading demo data 33 gem 'fabrication', "~> 1.3.0" # Both for tests, and loading demo data
34 gem 'rails_autolink', '~> 1.0.9' 34 gem 'rails_autolink', '~> 1.0.9'
35 gem 'campy' 35 gem 'campy'
  36 +gem 'hipchat'
36 37
37 # Please don't update this to airbrake - We override the send_notice method 38 # Please don't update this to airbrake - We override the send_notice method
38 # to handle internal errors. 39 # to handle internal errors.
@@ -97,10 +97,15 @@ GEM @@ -97,10 +97,15 @@ GEM
97 hashie (1.2.0) 97 hashie (1.2.0)
98 highline (1.6.13) 98 highline (1.6.13)
99 hike (1.2.1) 99 hike (1.2.1)
  100 + hipchat (0.4.1)
  101 + httparty
100 hoptoad_notifier (2.4.11) 102 hoptoad_notifier (2.4.11)
101 activesupport 103 activesupport
102 builder 104 builder
103 htmlentities (4.3.1) 105 htmlentities (4.3.1)
  106 + httparty (0.9.0)
  107 + multi_json (~> 1.0)
  108 + multi_xml
104 httpauth (0.1) 109 httpauth (0.1)
105 i18n (0.6.1) 110 i18n (0.6.1)
106 inherited_resources (1.3.1) 111 inherited_resources (1.3.1)
@@ -144,6 +149,7 @@ GEM @@ -144,6 +149,7 @@ GEM
144 rails (>= 3.0.0) 149 rails (>= 3.0.0)
145 railties (>= 3.0.0) 150 railties (>= 3.0.0)
146 multi_json (1.3.6) 151 multi_json (1.3.6)
  152 + multi_xml (0.5.1)
147 multipart-post (1.1.5) 153 multipart-post (1.1.5)
148 net-scp (1.0.4) 154 net-scp (1.0.4)
149 net-ssh (>= 1.99.1) 155 net-ssh (>= 1.99.1)
@@ -309,6 +315,7 @@ DEPENDENCIES @@ -309,6 +315,7 @@ DEPENDENCIES
309 execjs 315 execjs
310 fabrication (~> 1.3.0) 316 fabrication (~> 1.3.0)
311 haml 317 haml
  318 + hipchat
312 hoptoad_notifier (~> 2.4) 319 hoptoad_notifier (~> 2.4)
313 htmlentities (~> 4.3.0) 320 htmlentities (~> 4.3.0)
314 inherited_resources 321 inherited_resources
app/assets/images/hipchat_create.png 0 → 100644

2.05 KB

app/assets/images/hipchat_goto.png 0 → 100644

2.05 KB

app/assets/images/hipchat_inactive.png 0 → 100644

1.16 KB

app/models/notice_observer.rb
@@ -2,13 +2,13 @@ class NoticeObserver < Mongoid::Observer @@ -2,13 +2,13 @@ class NoticeObserver < Mongoid::Observer
2 observe :notice 2 observe :notice
3 3
4 def after_create notice 4 def after_create notice
5 - return unless should_notify? notice  
6 -  
7 - # if the app has a notficiation service, fire it off 5 + # if the app has a notification service, fire it off
8 if notice.app.notification_service_configured? 6 if notice.app.notification_service_configured?
9 notice.app.notification_service.create_notification(notice.problem) 7 notice.app.notification_service.create_notification(notice.problem)
10 end 8 end
11 9
  10 + return unless should_notify? notice
  11 +
12 Mailer.err_notification(notice).deliver 12 Mailer.err_notification(notice).deliver
13 end 13 end
14 14
app/models/notification_service.rb
1 class NotificationService 1 class NotificationService
2 include Mongoid::Document 2 include Mongoid::Document
3 3
  4 + include Rails.application.routes.url_helpers
  5 + default_url_options[:host] = ActionMailer::Base.default_url_options[:host]
  6 +
4 field :room_id, :type => String 7 field :room_id, :type => String
5 field :api_token, :type => String 8 field :api_token, :type => String
6 field :subdomain, :type => String 9 field :subdomain, :type => String
app/models/notification_services/hipchat_service.rb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +class NotificationServices::HipchatService < NotificationService
  2 + Label = 'hipchat'
  3 + Fields = [
  4 + [:api_token, {
  5 + :placeholder => "API Token"
  6 + }],
  7 + [:room_id, {
  8 + :placeholder => "Room ID",
  9 + :label => "Room ID"
  10 + }],
  11 + ]
  12 +
  13 + def check_params
  14 + if Fields.any? { |f, _| self[f].blank? }
  15 + errors.add :base, 'You must specify your Hipchat API token and Room ID'
  16 + end
  17 + end
  18 +
  19 + def create_notification(problem)
  20 + url = app_err_url problem.app, problem
  21 + message = <<-MSG.strip_heredoc
  22 + [#{ERB::Util.html_escape problem.app.name}]#{ERB::Util.html_escape notification_description(problem)}<br>
  23 + <a href="#{url}">#{url}</a>
  24 + MSG
  25 +
  26 + client = HipChat::Client.new(api_token)
  27 + client[room_id].send('Errbit', message, :color => 'red')
  28 + end
  29 +end
spec/fabricators/notification_service_fabricator.rb
@@ -5,6 +5,6 @@ Fabricator :notification_service do @@ -5,6 +5,6 @@ Fabricator :notification_service do
5 subdomain { sequence :word } 5 subdomain { sequence :word }
6 end 6 end
7 7
8 -%w(campfire).each do |t| 8 +%w(campfire hipchat).each do |t|
9 Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service" 9 Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service"
10 end 10 end
spec/models/notice_observer_spec.rb
@@ -44,7 +44,7 @@ describe NoticeObserver do @@ -44,7 +44,7 @@ describe NoticeObserver do
44 end 44 end
45 45
46 describe "should send a notification if a notification service is configured" do 46 describe "should send a notification if a notification service is configured" do
47 - let(:app) { app = Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:campfire_notification_service))} 47 + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:campfire_notification_service))}
48 let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) } 48 let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) }
49 49
50 before do 50 before do
@@ -56,9 +56,6 @@ describe NoticeObserver do @@ -56,9 +56,6 @@ describe NoticeObserver do
56 end 56 end
57 57
58 it "should create a campfire notification" do 58 it "should create a campfire notification" do
59 - err.problem.stub(:notices_count) { 1 }  
60 - app.notification_service.stub!(:create_notification).and_return(true)  
61 - app.stub!(:notification_recipients => %w('ryan@system88.com'))  
62 app.notification_service.should_receive(:create_notification) 59 app.notification_service.should_receive(:create_notification)
63 60
64 Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'}, 61 Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'},
@@ -67,7 +64,7 @@ describe NoticeObserver do @@ -67,7 +64,7 @@ describe NoticeObserver do
67 end 64 end
68 65
69 describe "should not send a notification if a notification service is not configured" do 66 describe "should not send a notification if a notification service is not configured" do
70 - let(:app) { app = Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:notification_service))} 67 + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:notification_service))}
71 let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) } 68 let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) }
72 69
73 before do 70 before do
@@ -79,8 +76,6 @@ describe NoticeObserver do @@ -79,8 +76,6 @@ describe NoticeObserver do
79 end 76 end
80 77
81 it "should not create a campfire notification" do 78 it "should not create a campfire notification" do
82 - err.problem.stub(:notices_count) { 1 }  
83 - app.stub!(:notification_recipients => %w('ryan@system88.com'))  
84 app.notification_service.should_not_receive(:create_notification) 79 app.notification_service.should_not_receive(:create_notification)
85 80
86 Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'}, 81 Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'},
@@ -88,4 +83,22 @@ describe NoticeObserver do @@ -88,4 +83,22 @@ describe NoticeObserver do
88 end 83 end
89 end 84 end
90 85
  86 + describe 'hipcat notifications' do
  87 + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:hipchat_notification_service))}
  88 + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) }
  89 +
  90 + before do
  91 + Errbit::Config.per_app_email_at_notices = true
  92 + end
  93 +
  94 + after do
  95 + Errbit::Config.per_app_email_at_notices = false
  96 + end
  97 +
  98 + it 'creates a hipchat notification' do
  99 + app.notification_service.should_receive(:create_notification)
  100 +
  101 + Fabricate(:notice, :err => err)
  102 + end
  103 + end
91 end 104 end
spec/models/notification_service/hipchat_service_spec.rb 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +require 'spec_helper'
  2 +
  3 +describe NotificationServices::HipchatService do
  4 + let(:service) { Fabricate.build(:hipchat_notification_service) }
  5 + let(:problem) { Fabricate(:problem) }
  6 + let(:room) { double }
  7 +
  8 + before do
  9 + HipChat::Client.any_instance.stub(:[] => room)
  10 + end
  11 +
  12 + it 'sends message' do
  13 + room.should_receive(:send)
  14 + service.create_notification(problem)
  15 + end
  16 +
  17 + it 'escapes html in message' do
  18 + service.stub(:notification_description => '<3')
  19 + room.should_receive(:send) do |_, message|
  20 + message.should_not include('<3')
  21 + message.should include('&lt;3')
  22 + end
  23 + service.create_notification(problem)
  24 + end
  25 +end