Commit 5633d2ede1dccf411329c3674c1dd14b782de2fe

Authored by Shuky Dvir
2 parents d99b857e 35cdcd35
Exists in master and in 1 other branch production

Merge branch 'master' of https://github.com/errbit/errbit

Conflicts:
	Gemfile
	app/models/notice_observer.rb
	spec/fabricators/notification_service_fabricator.rb
@@ -34,6 +34,7 @@ gem 'fabrication', "~> 1.3.0" # Both for tests, and loading demo data @@ -34,6 +34,7 @@ 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 'xmpp4r' 36 gem 'xmpp4r'
  37 +gem 'hipchat'
37 38
38 # Please don't update this to airbrake - We override the send_notice method 39 # Please don't update this to airbrake - We override the send_notice method
39 # to handle internal errors. 40 # 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)
@@ -310,6 +316,7 @@ DEPENDENCIES @@ -310,6 +316,7 @@ DEPENDENCIES
310 execjs 316 execjs
311 fabrication (~> 1.3.0) 317 fabrication (~> 1.3.0)
312 haml 318 haml
  319 + hipchat
313 hoptoad_notifier (~> 2.4) 320 hoptoad_notifier (~> 2.4)
314 htmlentities (~> 4.3.0) 321 htmlentities (~> 4.3.0)
315 inherited_resources 322 inherited_resources
@@ -150,9 +150,6 @@ git clone http://github.com/errbit/errbit.git @@ -150,9 +150,6 @@ git clone http://github.com/errbit/errbit.git
150 gem install heroku 150 gem install heroku
151 heroku create example-errbit --stack cedar 151 heroku create example-errbit --stack cedar
152 heroku addons:add mongolab:starter 152 heroku addons:add mongolab:starter
153 -cp -f config/mongoid.mongolab.yml config/mongoid.yml  
154 -git add -f config/mongoid.yml  
155 -git commit -m "Added mongoid config for Mongolab"  
156 heroku addons:add sendgrid:starter 153 heroku addons:add sendgrid:starter
157 heroku config:add HEROKU=true 154 heroku config:add HEROKU=true
158 heroku config:add ERRBIT_HOST=some-hostname.example.com 155 heroku config:add ERRBIT_HOST=some-hostname.example.com
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,10 +2,8 @@ class NoticeObserver < Mongoid::Observer @@ -2,10 +2,8 @@ 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  
8 - unless notice.app.notification_service.nil? 5 + # if the app has a notification service, fire it off
  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
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
app/views/apps/_configuration_instructions.html.haml
1 %pre 1 %pre
2 - %code  
3 - :preserve  
4 - # Require the hoptoad_notifier gem in your App.  
5 - # ---------------------------------------------  
6 - #  
7 - # Rails 3 - In your Gemfile  
8 - # gem 'airbrake'  
9 - #  
10 - # Rails 2 - In environment.rb  
11 - # config.gem 'airbrake'  
12 - #  
13 - # Then add the following to config/initializers/errbit.rb  
14 - # ------------------------------------------------------- 2 + %code
  3 + :preserve
  4 + # Require the hoptoad_notifier gem in your App.
  5 + # ---------------------------------------------
  6 + #
  7 + # Rails 3 - In your Gemfile
  8 + # gem 'airbrake'
  9 + #
  10 + # Rails 2 - In environment.rb
  11 + # config.gem 'airbrake'
  12 + #
  13 + # Then add the following to config/initializers/errbit.rb
  14 + # -------------------------------------------------------
15 15
16 - Airbrake.configure do |config|  
17 - config.api_key = '#{app.api_key}'  
18 - config.host = '#{request.host}'  
19 - config.port = #{request.port}  
20 - config.secure = config.port == 443  
21 - end 16 + Airbrake.configure do |config|
  17 + config.api_key = '#{app.api_key}'
  18 + config.host = '#{request.host}'
  19 + config.port = #{request.port}
  20 + config.secure = config.port == 443
  21 + end
22 22
23 - # Set up Javascript notifications  
24 - # -------------------------------  
25 - #  
26 - # To receive notifications for javascript errors,  
27 - # you should add <%= airbrake_javascript_notifier %> to the top of your layouts.  
28 - #  
29 - # Testing  
30 - # -------  
31 - #  
32 - # Rails 2 - you'll need to vendor airbrake to get the rake tasks  
33 - # rake gems:unpack GEM=airbrake  
34 - #  
35 - # Run:  
36 - # rake airbrake:test  
37 - # refresh this page 23 + # Set up Javascript notifications
  24 + # -------------------------------
  25 + #
  26 + # To receive notifications for javascript errors,
  27 + # you should add <%= airbrake_javascript_notifier %> to the top of your layouts.
  28 + #
  29 + # Testing
  30 + # -------
  31 + #
  32 + # Rails 2 - you'll need to vendor airbrake to get the rake tasks
  33 + # rake gems:unpack GEM=airbrake
  34 + #
  35 + # Run:
  36 + # rake airbrake:test
  37 + # refresh this page
38 38
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 gtalk).each do |t| 8 +%w(campfire gtalk 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'},
@@ -66,4 +63,42 @@ describe NoticeObserver do @@ -66,4 +63,42 @@ describe NoticeObserver do
66 end 63 end
67 end 64 end
68 65
  66 + describe "should not send a notification if a notification service is not configured" do
  67 + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:notification_service))}
  68 + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) }
  69 +
  70 + before do
  71 + Errbit::Config.per_app_email_at_notices = true
  72 + end
  73 +
  74 + after do
  75 + Errbit::Config.per_app_email_at_notices = false
  76 + end
  77 +
  78 + it "should not create a campfire notification" do
  79 + app.notification_service.should_not_receive(:create_notification)
  80 +
  81 + Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'},
  82 + :backtrace => [{ :error => 'Le Broken' }], :notifier => { 'name' => 'Notifier', 'version' => '1', 'url' => 'http://toad.com' })
  83 + end
  84 + end
  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
69 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