Commit 005eaf224602e154cd1d233c084597802d100d3c
Exists in
master
and in
1 other branch
Merge branch 'master' of https://github.com/boblail/errbit into boblail_master
Conflicts: Gemfile Gemfile.lock app/models/notice.rb app/views/notices/_environment.html.haml app/views/notices/_summary.html.haml spec/models/notice_spec.rb
Showing
12 changed files
with
107 additions
and
10 deletions
Show diff stats
Gemfile
... | ... | @@ -9,6 +9,7 @@ gem 'devise', '~> 1.1.8' |
9 | 9 | gem 'lighthouse-api' |
10 | 10 | gem 'redmine_client', :git => "git://github.com/oruen/redmine_client.git" |
11 | 11 | gem 'mongoid_rails_migrations' |
12 | +gem 'useragent', '~> 0.3.1' | |
12 | 13 | |
13 | 14 | platform :ruby do |
14 | 15 | gem 'bson_ext', '~> 1.2' | ... | ... |
Gemfile.lock
... | ... | @@ -114,6 +114,7 @@ GEM |
114 | 114 | treetop (1.4.9) |
115 | 115 | polyglot (>= 0.3.1) |
116 | 116 | tzinfo (0.3.26) |
117 | + useragent (0.3.1) | |
117 | 118 | warden (1.0.3) |
118 | 119 | rack (>= 1.0.0) |
119 | 120 | webmock (1.6.2) |
... | ... | @@ -138,5 +139,6 @@ DEPENDENCIES |
138 | 139 | redmine_client! |
139 | 140 | rspec (~> 2.5) |
140 | 141 | rspec-rails (~> 2.5) |
142 | + useragent (~> 0.3.1) | |
141 | 143 | webmock |
142 | 144 | will_paginate | ... | ... |
app/controllers/notices_controller.rb
... | ... | @@ -4,7 +4,8 @@ class NoticesController < ApplicationController |
4 | 4 | skip_before_filter :authenticate_user!, :only => :create |
5 | 5 | |
6 | 6 | def create |
7 | - @notice = Notice.from_xml(request.raw_post) | |
7 | + # params[:data] if the notice came from a GET request, raw_post if it came via POST | |
8 | + @notice = Notice.from_xml(params[:data] || request.raw_post) | |
8 | 9 | respond_with @notice |
9 | 10 | end |
10 | 11 | ... | ... |
app/helpers/application_helper.rb
1 | 1 | module ApplicationHelper |
2 | + | |
3 | + | |
2 | 4 | def lighthouse_tracker? object |
3 | 5 | object.issue_tracker_type == "lighthouseapp" |
4 | 6 | end |
7 | + | |
8 | + | |
9 | + def user_agent_graph(error) | |
10 | + tallies = tally(error.notices) {|notice| pretty_user_agent(notice.user_agent)} | |
11 | + create_percentage_table(tallies, :total => error.notices.count) | |
12 | + end | |
13 | + | |
14 | + def pretty_user_agent(user_agent) | |
15 | + (user_agent.nil? || user_agent.none?) ? "N/A" : "#{user_agent.browser} #{user_agent.version}" | |
16 | + end | |
17 | + | |
18 | + | |
19 | + def tally(collection, &block) | |
20 | + collection.inject({}) do |tallies, item| | |
21 | + value = yield item | |
22 | + tallies[value] = (tallies[value] || 0) + 1 | |
23 | + tallies | |
24 | + end | |
25 | + end | |
26 | + | |
27 | + | |
28 | + def create_percentage_table(tallies, options={}) | |
29 | + total = (options[:total] || total_from_tallies(tallies)) | |
30 | + percent = 100.0 / total.to_f | |
31 | + rows = tallies.map {|value, count| [(count.to_f * percent), value]} \ | |
32 | + .sort {|a, b| a[0] <=> b[0]} | |
33 | + render :partial => "errs/tally_table", :locals => {:rows => rows} | |
34 | + end | |
35 | + | |
36 | + | |
37 | +private | |
38 | + | |
39 | + | |
40 | + def total_from_tallies(tallies) | |
41 | + tallies.values.inject(0) {|sum, n| sum + n} | |
42 | + end | |
43 | + | |
44 | + | |
5 | 45 | end | ... | ... |
app/models/notice.rb
app/views/errs/_table.html.haml
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | - errs.each do |err| |
12 | 12 | %tr{:class => err.resolved? ? 'resolved' : 'unresolved'} |
13 | 13 | %td.app |
14 | - = err.app.name | |
14 | + = link_to err.app.name, app_path(err.app) | |
15 | 15 | %span.environment= err.environment |
16 | 16 | %td.message |
17 | 17 | = link_to err.message, app_err_path(err.app, err) | ... | ... |
app/views/notices/_environment.html.haml
app/views/notices/_summary.html.haml
public/stylesheets/application.css
... | ... | @@ -562,7 +562,7 @@ table.errs td.app .environment { |
562 | 562 | table.errs td.message a { |
563 | 563 | width: 420px; |
564 | 564 | display: block; |
565 | - word-wrap: break-word; | |
565 | + word-wrap: break-word; | |
566 | 566 | } |
567 | 567 | table.errs td.message em { |
568 | 568 | color: #727272; |
... | ... | @@ -574,6 +574,27 @@ table.errs tr.resolved td > * { |
574 | 574 | -webkit-opacity: 0.5; |
575 | 575 | } |
576 | 576 | |
577 | +/* Tally tables */ | |
578 | +table.tally { | |
579 | + border:none; | |
580 | +} | |
581 | +table.tally td, | |
582 | +table.tally th { | |
583 | + border:none !important; | |
584 | + background:none !important; | |
585 | + padding:8px 0 0; | |
586 | +} | |
587 | +table.tally tbody tr:first-child td, | |
588 | +table.tally tbody tr:first-child th { | |
589 | + padding-top:0; | |
590 | +} | |
591 | +table.tally td.percent { | |
592 | + width:4.5em; | |
593 | +} | |
594 | +table.tally th.value { | |
595 | + text-transform:none; | |
596 | +} | |
597 | + | |
577 | 598 | /* Resolve Errs */ |
578 | 599 | #action-bar a.resolve { |
579 | 600 | background: transparent url(images/icons/thumbs-up.png) 6px 5px no-repeat; | ... | ... |
spec/controllers/notices_controller_spec.rb
... | ... | @@ -2,7 +2,7 @@ require 'spec_helper' |
2 | 2 | |
3 | 3 | describe NoticesController do |
4 | 4 | |
5 | - context 'POST[XML] notices#create' do | |
5 | + context 'notices API' do | |
6 | 6 | before do |
7 | 7 | @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read |
8 | 8 | @app = Factory(:app_with_watcher) |
... | ... | @@ -11,15 +11,21 @@ describe NoticesController do |
11 | 11 | |
12 | 12 | request.env['Content-type'] = 'text/xml' |
13 | 13 | request.env['Accept'] = 'text/xml, application/xml' |
14 | - request.should_receive(:raw_post).and_return(@xml) | |
15 | 14 | end |
16 | 15 | |
17 | - it "generates a notice from the xml" do | |
16 | + it "generates a notice from xml [POST]" do | |
18 | 17 | Notice.should_receive(:from_xml).with(@xml).and_return(@notice) |
18 | + request.should_receive(:raw_post).and_return(@xml) | |
19 | 19 | post :create |
20 | 20 | end |
21 | 21 | |
22 | + it "generates a notice from xml [GET]" do | |
23 | + Notice.should_receive(:from_xml).with(@xml).and_return(@notice) | |
24 | + get :create, {:data => @xml} | |
25 | + end | |
26 | + | |
22 | 27 | it "sends a notification email" do |
28 | + request.should_receive(:raw_post).and_return(@xml) | |
23 | 29 | post :create |
24 | 30 | email = ActionMailer::Base.deliveries.last |
25 | 31 | email.to.should include(@app.watchers.first.email) | ... | ... |
spec/models/notice_spec.rb
... | ... | @@ -119,6 +119,19 @@ describe Notice do |
119 | 119 | end |
120 | 120 | end |
121 | 121 | |
122 | + describe "user agent" do | |
123 | + it "should be parsed and human-readable" do | |
124 | + notice = Factory.build(:notice, :request => {'cgi-data' => {'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16'}}) | |
125 | + notice.user_agent.browser.should == 'Chrome' | |
126 | + notice.user_agent.version.to_s.should =~ /^10\.0/ | |
127 | + end | |
128 | + | |
129 | + it "should be nil if HTTP_USER_AGENT is blank" do | |
130 | + notice = Factory.build(:notice) | |
131 | + notice.user_agent.should == nil | |
132 | + end | |
133 | + end | |
134 | + | |
122 | 135 | describe "email notifications" do |
123 | 136 | before do |
124 | 137 | @app = Factory(:app_with_watcher) | ... | ... |