bullhorn 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -65
- data/VERSION +1 -1
- data/bullhorn.gemspec +5 -4
- data/lib/bullhorn.rb +5 -0
- data/lib/bullhorn/backtrace.rb +47 -0
- data/lib/bullhorn/sender.rb +18 -6
- metadata +11 -4
data/README.rdoc
CHANGED
@@ -2,72 +2,10 @@
|
|
2
2
|
|
3
3
|
The Rack middleware drop-in for the bullhorn exception notification application.
|
4
4
|
|
5
|
-
See http://bullhorn.it and signup for a free account!
|
5
|
+
See http://www.bullhorn.it and signup for a free account!
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
require 'rubygems'
|
10
|
-
require 'sinatra'
|
11
|
-
|
12
|
-
# this must be enabled for errors to propagate
|
13
|
-
set :raise_errors, true
|
14
|
-
|
15
|
-
# of course the best way to do that is:
|
16
|
-
set :raise_errors, production?
|
17
|
-
|
18
|
-
# Let's say we have an error we don't want to be notified about
|
19
|
-
MyOwnError = Class.new(StandardError)
|
20
|
-
|
21
|
-
use Bullhorn, :api_key => "__your key here__",
|
22
|
-
:filters => %w(password password_confirmation),
|
23
|
-
:ignore_exceptions => [MyOwnError]
|
24
|
-
|
25
|
-
get "/hello" do
|
26
|
-
"Hello world"
|
27
|
-
end
|
28
|
-
|
29
|
-
get "/fail" do
|
30
|
-
raise "Failure from the app"
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
== Rails 3 Example
|
35
|
-
|
36
|
-
Whatever::Application.config.middleware.use Bullhorn,
|
37
|
-
:api_key => "_your api key here_",
|
38
|
-
:filters => %w(password password_confirmation credit_card)
|
39
|
-
|
40
|
-
# by default, ActiveRecord::RecordNotFound,
|
41
|
-
# AbstractController::ActionNotFound and ActionController::RoutingError
|
42
|
-
# are ignored in a Rails 3 context.
|
43
|
-
|
44
|
-
== Rails 2.3.5 backward compatibility
|
45
|
-
|
46
|
-
# in config/environment.rb
|
47
|
-
|
48
|
-
config.gem 'bullhorn'
|
49
|
-
|
50
|
-
# in config/initializers/bullhorn.rb
|
51
|
-
Bullhorn::Plugin.options = {
|
52
|
-
:api_key => "_api key here_",
|
53
|
-
:filters => %w(password password_confirmation credit_card)
|
54
|
-
}
|
55
|
-
|
56
|
-
# in your application controller
|
57
|
-
class ApplicationController < ActionController::Base
|
58
|
-
include Bullhorn::Plugin
|
59
|
-
end
|
60
|
-
|
61
|
-
== Note on Patches/Pull Requests
|
62
|
-
|
63
|
-
* Fork the project.
|
64
|
-
* Make your feature addition or bug fix.
|
65
|
-
* Add tests for it. This is important so I don't break it in a
|
66
|
-
future version unintentionally.
|
67
|
-
* Commit, do not mess with rakefile, version, or history.
|
68
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
69
|
-
* Send me a pull request. Bonus points for topic branches.
|
7
|
+
Installing instructions: http://www.bullhorn.it/page/installation
|
70
8
|
|
71
9
|
== Copyright
|
72
10
|
|
73
|
-
Copyright (c) 2010 Cyril David.
|
11
|
+
Copyright (c) 2010 Cyril David, Rico Sta. Cruz and Sinefunc, Inc. Released under the MIT license.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bullhorn.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bullhorn}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Cyril David"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-10-18}
|
13
13
|
s.description = %q{drop in rack middleware for bullhorn.it}
|
14
14
|
s.email = %q{cyx.ucron@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -78,6 +78,7 @@ Gem::Specification.new do |s|
|
|
78
78
|
"examples/foobar/test/unit/helpers/raiser_helper_test.rb",
|
79
79
|
"examples/sinatra.rb",
|
80
80
|
"lib/bullhorn.rb",
|
81
|
+
"lib/bullhorn/backtrace.rb",
|
81
82
|
"lib/bullhorn/plugin.rb",
|
82
83
|
"lib/bullhorn/sender.rb",
|
83
84
|
"test/helper.rb",
|
@@ -88,7 +89,7 @@ Gem::Specification.new do |s|
|
|
88
89
|
s.homepage = %q{http://github.com/sinefunc/bullhorn}
|
89
90
|
s.rdoc_options = ["--charset=UTF-8"]
|
90
91
|
s.require_paths = ["lib"]
|
91
|
-
s.rubygems_version = %q{1.3.
|
92
|
+
s.rubygems_version = %q{1.3.7}
|
92
93
|
s.summary = %q{rack middleware client for bullhorn.it}
|
93
94
|
s.test_files = [
|
94
95
|
"test/helper.rb",
|
@@ -123,7 +124,7 @@ Gem::Specification.new do |s|
|
|
123
124
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
124
125
|
s.specification_version = 3
|
125
126
|
|
126
|
-
if Gem::Version.new(Gem::
|
127
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
127
128
|
s.add_development_dependency(%q<contest>, [">= 0"])
|
128
129
|
s.add_development_dependency(%q<mocha>, [">= 0"])
|
129
130
|
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
data/lib/bullhorn.rb
CHANGED
@@ -8,7 +8,10 @@ require 'digest/sha1'
|
|
8
8
|
class Bullhorn
|
9
9
|
autoload :Plugin, "bullhorn/plugin"
|
10
10
|
autoload :Sender, "bullhorn/sender"
|
11
|
+
autoload :Backtrace, "bullhorn/backtrace"
|
11
12
|
|
13
|
+
LANGUAGE = "ruby"
|
14
|
+
CLIENT_NAME = "bullhorn-ruby"
|
12
15
|
VERSION = "0.0.5"
|
13
16
|
|
14
17
|
URL = "http://www.bullhorn.it/api/v1/exception"
|
@@ -19,6 +22,7 @@ class Bullhorn
|
|
19
22
|
attr :api_key
|
20
23
|
attr :url
|
21
24
|
attr :ignore_exceptions
|
25
|
+
attr :show_code_context
|
22
26
|
|
23
27
|
include Sender
|
24
28
|
|
@@ -28,6 +32,7 @@ class Bullhorn
|
|
28
32
|
@filters = Array(options[:filters])
|
29
33
|
@url = options[:url] || URL
|
30
34
|
@ignore_exceptions = Array(options[:ignore_exceptions] || default_ignore_exceptions)
|
35
|
+
@show_code_context = (options[:show_code_context].nil? ? true : options[:show_code_context])
|
31
36
|
end
|
32
37
|
|
33
38
|
def call(env)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Bullhorn
|
2
|
+
class Backtrace
|
3
|
+
def initialize(exception, options = {})
|
4
|
+
@exception = exception
|
5
|
+
@raw = exception.backtrace # Array
|
6
|
+
@options = { :context => true }
|
7
|
+
|
8
|
+
@options.merge!(options)
|
9
|
+
|
10
|
+
# Sample:
|
11
|
+
# [ "(irb):3:in `irb_binding'",
|
12
|
+
# "/Users/rsc/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/irb/workspace.rb:80:in `eval'",
|
13
|
+
# "/Users/rsc/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/irb.rb:159:in `block (2 levels) in eval_input'",
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns nil or an array.
|
17
|
+
def get_context(fname, line, size = 2)
|
18
|
+
begin
|
19
|
+
line = line.to_i
|
20
|
+
from = [0, (line-size-1)].max
|
21
|
+
lines = File.open(fname, 'r') { |file| file.lines.to_a[from...(line+size)] }
|
22
|
+
|
23
|
+
i = [line - size, 0].max
|
24
|
+
lines.map { |hash| i += 1; { (i-1) => hash } }
|
25
|
+
rescue
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_a
|
31
|
+
@raw.inject([]) do |arr, line|
|
32
|
+
m = line.match(/^(?<file>[^:]+):(?<line>[0-9]+):in `(?<function>.*)'$/)
|
33
|
+
|
34
|
+
arr << { :function => m[:function],
|
35
|
+
:file => m[:file],
|
36
|
+
:line => m[:line],
|
37
|
+
:context => (@options[:context] ? get_context(m[:file], m[:line]) : nil)
|
38
|
+
}
|
39
|
+
arr
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_json
|
44
|
+
to_a.send(:to_json)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/bullhorn/sender.rb
CHANGED
@@ -7,17 +7,33 @@ class Bullhorn
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def notify(exception, env)
|
10
|
+
bt = Backtrace.new(exception, :context => @show_code_context)
|
11
|
+
|
10
12
|
Net::HTTP.post_form(URI(url), {
|
11
13
|
:api_key => api_key,
|
12
14
|
:message => exception.message,
|
13
|
-
:backtrace => serialize(
|
15
|
+
:backtrace => serialize(bt.to_a),
|
14
16
|
:env => serialize(whitelist(env)),
|
15
17
|
:request_body => serialize(whitelist(request_body(env))),
|
16
|
-
:sha1 => sha1(exception)
|
18
|
+
:sha1 => sha1(exception),
|
19
|
+
# APIv2
|
20
|
+
:language => Bullhorn::LANGUAGE,
|
21
|
+
:client_name => Bullhorn::CLIENT_NAME,
|
22
|
+
:client_version => Bullhorn::VERSION,
|
23
|
+
:url => [ "http://", env['HTTP_HOST'], env['REQUEST_URI'] ].join(''),
|
24
|
+
:class => exception.class.to_s
|
17
25
|
})
|
18
26
|
end
|
19
27
|
|
20
28
|
protected
|
29
|
+
def sha1(exception)
|
30
|
+
# Treat 2 exceptions as the same if they match the same exception class
|
31
|
+
# and same origin.
|
32
|
+
salt = '#bh#' + Bullhorn::CLIENT_NAME
|
33
|
+
str = [ salt, exception.class.to_s, exception.backtrace.first ].join('|')
|
34
|
+
Digest::SHA1.hexdigest(str)
|
35
|
+
end
|
36
|
+
|
21
37
|
def request_body(env)
|
22
38
|
if io = env['rack.input']
|
23
39
|
io.rewind if io.respond_to?(:rewind)
|
@@ -55,9 +71,5 @@ class Bullhorn
|
|
55
71
|
end
|
56
72
|
end
|
57
73
|
end
|
58
|
-
|
59
|
-
def sha1(exception)
|
60
|
-
Digest::SHA1.hexdigest(exception.message + exception.backtrace.inspect)
|
61
|
-
end
|
62
74
|
end
|
63
75
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.6
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Cyril David
|
@@ -14,13 +14,14 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-10-18 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: contest
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
24
25
|
requirements:
|
25
26
|
- - ">="
|
26
27
|
- !ruby/object:Gem::Version
|
@@ -33,6 +34,7 @@ dependencies:
|
|
33
34
|
name: mocha
|
34
35
|
prerelease: false
|
35
36
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
36
38
|
requirements:
|
37
39
|
- - ">="
|
38
40
|
- !ruby/object:Gem::Version
|
@@ -45,6 +47,7 @@ dependencies:
|
|
45
47
|
name: rack-test
|
46
48
|
prerelease: false
|
47
49
|
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
48
51
|
requirements:
|
49
52
|
- - ">="
|
50
53
|
- !ruby/object:Gem::Version
|
@@ -57,6 +60,7 @@ dependencies:
|
|
57
60
|
name: fakeweb
|
58
61
|
prerelease: false
|
59
62
|
requirement: &id004 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
60
64
|
requirements:
|
61
65
|
- - ">="
|
62
66
|
- !ruby/object:Gem::Version
|
@@ -136,6 +140,7 @@ files:
|
|
136
140
|
- examples/foobar/test/unit/helpers/raiser_helper_test.rb
|
137
141
|
- examples/sinatra.rb
|
138
142
|
- lib/bullhorn.rb
|
143
|
+
- lib/bullhorn/backtrace.rb
|
139
144
|
- lib/bullhorn/plugin.rb
|
140
145
|
- lib/bullhorn/sender.rb
|
141
146
|
- test/helper.rb
|
@@ -152,6 +157,7 @@ rdoc_options:
|
|
152
157
|
require_paths:
|
153
158
|
- lib
|
154
159
|
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
155
161
|
requirements:
|
156
162
|
- - ">="
|
157
163
|
- !ruby/object:Gem::Version
|
@@ -159,6 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
159
165
|
- 0
|
160
166
|
version: "0"
|
161
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
162
169
|
requirements:
|
163
170
|
- - ">="
|
164
171
|
- !ruby/object:Gem::Version
|
@@ -168,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
175
|
requirements: []
|
169
176
|
|
170
177
|
rubyforge_project:
|
171
|
-
rubygems_version: 1.3.
|
178
|
+
rubygems_version: 1.3.7
|
172
179
|
signing_key:
|
173
180
|
specification_version: 3
|
174
181
|
summary: rack middleware client for bullhorn.it
|