flyingmachine-merb_whoops_notifier 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/LICENSE +21 -0
- data/README +59 -0
- data/Rakefile +74 -0
- data/TODO +2 -0
- data/lib/merb_whoops_notifier/merbtasks.rb +2 -0
- data/lib/merb_whoops_notifier/whoops_mixin.rb +17 -0
- data/lib/merb_whoops_notifier/whoops_notifier.rb +144 -0
- data/lib/merb_whoops_notifier.rb +10 -0
- data/spec/fixtures/whoops.yml +9 -0
- data/spec/merb_whoops_notifier_spec.rb +113 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_helper.rb +33 -0
- metadata +77 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Copyright (c) 2008 Corey Donohoe<atmos@atmos.org>, Joakim Kolsjö<trejje@gmail.com>,
|
|
2
|
+
Daniel Higginbotham<daniel@flyingmachinestudios.com>
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
a copy of this software and associated documentation files (the
|
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
merb_whoops_notifier
|
|
2
|
+
---------------------------------------------
|
|
3
|
+
This is merb plugin for exception notification with whoops. It should work with
|
|
4
|
+
any merb app that's based on merb 1.0 and higher
|
|
5
|
+
|
|
6
|
+
This plugin: http://github.com/atmos/merb_whoops_notifier/tree/master
|
|
7
|
+
The original: http://github.com/thoughtbot/whoops_notifier/tree/master
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
1) Get your api key for your app from whoopsapp.com
|
|
12
|
+
|
|
13
|
+
2) Add the api key to config/whoops.yml with a similar syntax as the following
|
|
14
|
+
---
|
|
15
|
+
:development: &defaults
|
|
16
|
+
:api_key: ZOMGLOLROFLMAO
|
|
17
|
+
|
|
18
|
+
:rake:
|
|
19
|
+
<<: *defaults
|
|
20
|
+
|
|
21
|
+
:test:
|
|
22
|
+
<<: *defaults
|
|
23
|
+
|
|
24
|
+
:production:
|
|
25
|
+
:api_key: UBERSECRETSHIT
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
3) Require whoops in init.rb
|
|
29
|
+
require 'merb_whoops_notifier'
|
|
30
|
+
|
|
31
|
+
4) Add the following method to your Exceptions controller. Depending on your merb version you'll need to use the exceptions,standard_error, or internal_server error as the action name. Kinda weak, but the API changed a lot in 0.9.x
|
|
32
|
+
|
|
33
|
+
class Exceptions < Merb::Controller
|
|
34
|
+
if %w( staging production ).include?(Merb.env)
|
|
35
|
+
def standard_error
|
|
36
|
+
WhoopsNotifier.notify_whoops(request, session)
|
|
37
|
+
render
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
5) Restart the server, trigger an error(in staging or prod) and check that it arrived at whoops :)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
Filtersing your post environment
|
|
46
|
+
--------------------------------
|
|
47
|
+
If you have environmental variables set in your ruby process that should not be sent to whoops,
|
|
48
|
+
there's a mechanism for filtering those attributes now. Throw something like this in
|
|
49
|
+
config/init.rb
|
|
50
|
+
|
|
51
|
+
Merb::BootLoader.after_app_loads do
|
|
52
|
+
WhoopsNotifier.environment_filters = %w(^AWS ^EC2 SECRET PRIVATE KEY)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Each of these words will be compiled into a regex so you should be able to use anchors if needed.
|
|
56
|
+
|
|
57
|
+
Thanks to the following GitHubbers
|
|
58
|
+
----------------------------------
|
|
59
|
+
joakimk, fairchild and cv.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake/gempackagetask'
|
|
3
|
+
require 'rubygems/specification'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'merb-core/version'
|
|
6
|
+
require 'merb-core/tasks/merb_rake_helper'
|
|
7
|
+
require 'spec/rake/spectask'
|
|
8
|
+
|
|
9
|
+
install_home = ENV['GEM_HOME'] ? "-i #{ENV['GEM_HOME']}" : ""
|
|
10
|
+
|
|
11
|
+
def sudo
|
|
12
|
+
windows = (PLATFORM =~ /win32|cygwin/) rescue nil
|
|
13
|
+
ENV['MERB_SUDO'] ||= "sudo"
|
|
14
|
+
sudo = windows ? "" : ENV['MERB_SUDO']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
NAME = "merb_whoops_notifier"
|
|
18
|
+
GEM_VERSION = "1.0"
|
|
19
|
+
AUTHOR = "Daniel Higginbotham"
|
|
20
|
+
EMAIL = 'daniel@flyingmachinestudios.com'
|
|
21
|
+
HOMEPAGE = "http://github.com/flyingmachine/merb_whoops_notifier"
|
|
22
|
+
SUMMARY = "Merb plugin that provides whoops exception notification"
|
|
23
|
+
|
|
24
|
+
spec = Gem::Specification.new do |s|
|
|
25
|
+
s.rubyforge_project = 'merb'
|
|
26
|
+
s.name = NAME
|
|
27
|
+
s.version = GEM_VERSION
|
|
28
|
+
s.platform = Gem::Platform::RUBY
|
|
29
|
+
s.has_rdoc = true
|
|
30
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
|
31
|
+
s.summary = SUMMARY
|
|
32
|
+
s.description = s.summary
|
|
33
|
+
s.author = AUTHOR
|
|
34
|
+
s.email = EMAIL
|
|
35
|
+
s.homepage = HOMEPAGE
|
|
36
|
+
s.add_dependency('merb-core', '>= 1.0.9')
|
|
37
|
+
s.require_path = 'lib'
|
|
38
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
42
|
+
pkg.gem_spec = spec
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
desc "install the plugin locally"
|
|
46
|
+
task :install => [:package] do
|
|
47
|
+
sh %{#{sudo} gem install #{install_home} pkg/#{NAME}-#{GEM_VERSION} --no-update-sources}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
desc "create a gemspec file"
|
|
51
|
+
task :make_spec do
|
|
52
|
+
File.open("#{NAME}.gemspec", "w") do |file|
|
|
53
|
+
file.puts spec.to_ruby
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
namespace :jruby do
|
|
58
|
+
desc "Run :package and install the resulting .gem with jruby"
|
|
59
|
+
task :install => :package do
|
|
60
|
+
sh %{#{sudo} jruby -S gem install #{install_home} pkg/#{NAME}-#{GEM_VERSION}.gem --no-rdoc --no-ri}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
Spec::Rake::SpecTask.new(:default) do |t|
|
|
65
|
+
t.spec_opts << %w(-fs --color) << %w(-O spec/spec.opts)
|
|
66
|
+
t.spec_opts << '--loadby' << 'random'
|
|
67
|
+
t.spec_files = Dir["spec/*_spec.rb"]
|
|
68
|
+
t.rcov = ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true
|
|
69
|
+
t.rcov_opts << '--exclude' << '.gem/'
|
|
70
|
+
|
|
71
|
+
t.rcov_opts << '--text-summary'
|
|
72
|
+
t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
|
|
73
|
+
t.rcov_opts << '--only-uncovered'
|
|
74
|
+
end
|
data/TODO
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+'/whoops_notifier')
|
|
2
|
+
|
|
3
|
+
module WhoopsMixin
|
|
4
|
+
def notify_whoops(request=nil, session=nil)
|
|
5
|
+
request ||= self.request
|
|
6
|
+
session ||= self.session
|
|
7
|
+
|
|
8
|
+
WhoopsNotifier.notify_whoops(request, session)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def warn_whoops(message, request=nil, session=nil, options={})
|
|
12
|
+
request ||= self.request
|
|
13
|
+
session ||= self.session
|
|
14
|
+
|
|
15
|
+
WhoopsNotifier.warn_whoops(message, request, session, options)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
|
|
3
|
+
module WhoopsNotifier
|
|
4
|
+
class << self
|
|
5
|
+
attr_accessor :host, :logger
|
|
6
|
+
|
|
7
|
+
def configure
|
|
8
|
+
key = YAML.load_file(Merb.root / 'config' / 'whoops.yml')
|
|
9
|
+
if key
|
|
10
|
+
env = key[Merb.env.to_sym]
|
|
11
|
+
env ? @host = env[:host] : raise(ArgumentError, "No whoops host for Merb environment #{Merb.env}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def logger
|
|
16
|
+
@logger || Merb.logger
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def environment_filters
|
|
20
|
+
@environment_filters ||= %w(AWS_ACCESS_KEY AWS_SECRET_ACCESS_KEY AWS_ACCOUNT SSH_AUTH_SOCK)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def warn_whoops(message, request, session, options={})
|
|
24
|
+
return if request.nil?
|
|
25
|
+
params = request.params
|
|
26
|
+
|
|
27
|
+
data = {
|
|
28
|
+
:error_class => options[:error_class] || message,
|
|
29
|
+
:error_message => message,
|
|
30
|
+
:backtrace => caller,
|
|
31
|
+
:environment => ENV.to_hash
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
data[:request] = {
|
|
35
|
+
:params => params
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
data[:environment] = clean_whoops_environment(ENV.to_hash.merge(request.env))
|
|
39
|
+
data[:environment][:RAILS_ENV] = Merb.env
|
|
40
|
+
|
|
41
|
+
data[:session] = {
|
|
42
|
+
:key => session.instance_variable_get("@session_id"),
|
|
43
|
+
:data => session.to_hash
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
send_to_whoops :notice => default_notice_options.merge(data)
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def notify_whoops(request, session)
|
|
51
|
+
return if request.nil?
|
|
52
|
+
params = request.params
|
|
53
|
+
|
|
54
|
+
request.exceptions.each do |exception|
|
|
55
|
+
data = {
|
|
56
|
+
:error_class => Extlib::Inflection.camelize(exception.class.name),
|
|
57
|
+
:error_message => "#{Extlib::Inflection.camelize(exception.class.name)}: #{exception.message}",
|
|
58
|
+
:backtrace => exception.backtrace,
|
|
59
|
+
:environment => ENV.to_hash
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
data[:request] = {
|
|
63
|
+
:params => params
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
data[:environment] = clean_whoops_environment(ENV.to_hash.merge(request.env))
|
|
67
|
+
data[:environment][:RAILS_ENV] = Merb.env
|
|
68
|
+
|
|
69
|
+
data[:session] = {
|
|
70
|
+
:key => session.instance_variable_get("@session_id"),
|
|
71
|
+
:data => session.to_hash
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
send_to_whoops :notice => default_notice_options.merge(data)
|
|
75
|
+
end
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def send_to_whoops(data) #:nodoc:
|
|
80
|
+
url = URI.parse(WhoopsNotifier.host)
|
|
81
|
+
|
|
82
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
|
83
|
+
headers = {
|
|
84
|
+
'Content-type' => 'application/x-yaml',
|
|
85
|
+
'Accept' => 'text/xml, application/xml'
|
|
86
|
+
}
|
|
87
|
+
http.read_timeout = 5 # seconds
|
|
88
|
+
http.open_timeout = 2 # seconds
|
|
89
|
+
# http.use_ssl = WhoopsNotifier.secure
|
|
90
|
+
response = begin
|
|
91
|
+
http.post("/error_reports", clean_non_serializable_data(data).to_yaml, headers)
|
|
92
|
+
rescue TimeoutError => e
|
|
93
|
+
logger.error "Timeout while contacting the Whoops server."
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
case response
|
|
97
|
+
when Net::HTTPSuccess then
|
|
98
|
+
logger.info "Whoops Success: #{response.class}"
|
|
99
|
+
else
|
|
100
|
+
logger.error "Whoops Failure: #{response.class}\n#{response.body if response.respond_to? :body}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def default_notice_options #:nodoc:
|
|
106
|
+
{
|
|
107
|
+
:error_message => 'Notification',
|
|
108
|
+
:backtrace => nil,
|
|
109
|
+
:request => {},
|
|
110
|
+
:session => {},
|
|
111
|
+
:environment => {}
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def clean_non_serializable_data(notice) #:nodoc:
|
|
116
|
+
notice.select{|k,v| serializable?(v) }.inject({}) do |h, pair|
|
|
117
|
+
h[pair.first] = pair.last.is_a?(Hash) ? clean_non_serializable_data(pair.last) : pair.last
|
|
118
|
+
h
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def serializable?(value) #:nodoc:
|
|
123
|
+
value.is_a?(Fixnum) ||
|
|
124
|
+
value.is_a?(Array) ||
|
|
125
|
+
value.is_a?(String) ||
|
|
126
|
+
value.is_a?(Hash) ||
|
|
127
|
+
value.is_a?(Bignum)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def stringify_keys(hash) #:nodoc:
|
|
131
|
+
hash.inject({}) do |h, pair|
|
|
132
|
+
h[pair.first.to_s] = pair.last.is_a?(Hash) ? stringify_keys(pair.last) : pair.last
|
|
133
|
+
h
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
def clean_whoops_environment(env) #:nodoc:
|
|
137
|
+
env.each do |k, v|
|
|
138
|
+
env[k] = "[FILTERED]" if WhoopsNotifier.environment_filters.any? do |filter|
|
|
139
|
+
k.to_s.match(/#{filter}/)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+'/merb_whoops_notifier/whoops_notifier')
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__)+'/merb_whoops_notifier/whoops_mixin')
|
|
3
|
+
|
|
4
|
+
# make sure we're running inside Merb
|
|
5
|
+
if defined?(Merb::Plugins)
|
|
6
|
+
Merb::BootLoader.after_app_loads do
|
|
7
|
+
WhoopsNotifier.configure
|
|
8
|
+
end
|
|
9
|
+
Merb::Plugins.add_rakefiles "merb_whoops_notifier/merbtasks"
|
|
10
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "WhoopsNotifier" do
|
|
4
|
+
include Merb::Spec::Helpers
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
stub(Merb).env { :production }
|
|
8
|
+
stub(Merb).root { Dir.tmpdir }
|
|
9
|
+
|
|
10
|
+
@http = Net::HTTP.new('localhost')
|
|
11
|
+
@headers = { "Content-type" => "application/x-yaml", "Accept" => "text/xml, application/xml" }
|
|
12
|
+
host = "http://localhost:3000/"
|
|
13
|
+
@config = {:development => {:host=>host}, :production => {:host=>host}, :test => {:host=>host}}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should define a constant" do
|
|
17
|
+
WhoopsNotifier.should_not be_nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe ".configure" do
|
|
21
|
+
before(:each) do
|
|
22
|
+
mock(YAML).load_file(File.join(Merb.root / 'config' / 'whoops.yml')) { @config }
|
|
23
|
+
WhoopsNotifier.configure
|
|
24
|
+
end
|
|
25
|
+
it "should know the host key after configuring" do
|
|
26
|
+
WhoopsNotifier.host.should == 'http://localhost:3000/'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe ".stringify_key" do
|
|
31
|
+
it "should turn string keys into symbols" do
|
|
32
|
+
WhoopsNotifier.stringify_keys({'foo' => 'bar', :baz => 'foo', :bar => 'foo'}).should == { 'foo' => 'bar', 'baz' => 'foo', 'bar' => 'foo'}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
describe "notification" do
|
|
38
|
+
before(:each) do
|
|
39
|
+
stub(Net::HTTP).new('localhost', 3000, nil, nil, nil, nil) { @http }
|
|
40
|
+
mock(YAML).load_file(File.join(Merb.root / 'config' / 'whoops.yml')) { @config }
|
|
41
|
+
WhoopsNotifier.configure
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".default_notice_options" do
|
|
45
|
+
it "should return sane defaults" do
|
|
46
|
+
WhoopsNotifier.default_notice_options.should == {
|
|
47
|
+
:error_message => 'Notification',
|
|
48
|
+
:backtrace => nil,
|
|
49
|
+
:request => {},
|
|
50
|
+
:session => {},
|
|
51
|
+
:environment => {}
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe ".notify_whoops" do
|
|
57
|
+
describe "bad input" do
|
|
58
|
+
it "should handle nil input" do
|
|
59
|
+
WhoopsNotifier.notify_whoops(nil, nil).should be_nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "good input" do
|
|
64
|
+
before(:each) do
|
|
65
|
+
mock(WhoopsNotifier).send_to_whoops(anything).times(2) { true }
|
|
66
|
+
@request = setup_merb_request
|
|
67
|
+
mock(@request).exceptions { [RuntimeError.new('ZOMG'), RuntimeError.new('ORLY')]}
|
|
68
|
+
mock(@request).params { {"q"=>"0017000000SmnJ0"} }
|
|
69
|
+
end
|
|
70
|
+
it "should return true" do
|
|
71
|
+
WhoopsNotifier.notify_whoops(@request, {}).should be_true
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe ".send_to_whoops" do
|
|
77
|
+
describe "any 2XX response" do
|
|
78
|
+
before(:each) do
|
|
79
|
+
response = Net::HTTPOK.new('1.1', 200, 'Wazzup?')
|
|
80
|
+
mock(@http).post("/error_reports", "--- {}\n\n", @headers) { response }
|
|
81
|
+
end
|
|
82
|
+
it "should log success" do
|
|
83
|
+
mock(WhoopsNotifier.logger).info "Whoops Success: Net::HTTPOK"
|
|
84
|
+
WhoopsNotifier.send_to_whoops({})
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
describe "any non 2XX response" do
|
|
88
|
+
before(:each) do
|
|
89
|
+
response = Net::HTTPInternalServerError.new('1.1', 500, 'Upstream unavailable')
|
|
90
|
+
mock(response).body { 'Upstream unavailable' }
|
|
91
|
+
|
|
92
|
+
stub(@http.instance_variable_get('@socket')).closed? { true }
|
|
93
|
+
mock(@http).post("/error_reports", "--- {}\n\n", @headers) { response }
|
|
94
|
+
end
|
|
95
|
+
it "should log failure" do
|
|
96
|
+
mock(WhoopsNotifier.logger).error "Whoops Failure: Net::HTTPInternalServerError\nUpstream unavailable"
|
|
97
|
+
WhoopsNotifier.send_to_whoops({})
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
describe "a timeout exception is thrown" do
|
|
101
|
+
before(:each) do
|
|
102
|
+
response = TimeoutError.new("It took too fucking long")
|
|
103
|
+
mock(@http).post("/error_reports", "--- {}\n\n", @headers) { raise response }
|
|
104
|
+
end
|
|
105
|
+
it "should log failure" do
|
|
106
|
+
mock(WhoopsNotifier.logger).error("Whoops Failure: NilClass\n")
|
|
107
|
+
mock(WhoopsNotifier.logger).error("Timeout while contacting the Whoops server.")
|
|
108
|
+
WhoopsNotifier.send_to_whoops({})
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
data/spec/spec.opts
ADDED
|
File without changes
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
$TESTING=true
|
|
2
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
|
3
|
+
require 'rr'
|
|
4
|
+
require 'merb-core'
|
|
5
|
+
require 'merb_whoops_notifier'
|
|
6
|
+
require 'tmpdir'
|
|
7
|
+
require 'pp'
|
|
8
|
+
|
|
9
|
+
Spec::Runner.configure do |config|
|
|
10
|
+
config.mock_with :rr
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module Merb
|
|
14
|
+
module Spec
|
|
15
|
+
module Helpers
|
|
16
|
+
def setup_merb_request
|
|
17
|
+
rack_env = {"SERVER_NAME"=>"localhost",
|
|
18
|
+
"rack.run_once"=>false, "rack.url_scheme"=>"http", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/526.1+ (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1",
|
|
19
|
+
"HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "PATH_INFO"=>"/search/", "HTTP_CACHE_CONTROL"=>"max-age=0",
|
|
20
|
+
"HTTP_ACCEPT_LANGUAGE"=>"en-us", "HTTP_HOST"=>"localhost:4000", "SERVER_PROTOCOL"=>"HTTP/1.1", "SCRIPT_NAME"=>"",
|
|
21
|
+
"REQUEST_PATH"=>"/search/", "SERVER_SOFTWARE"=>"Mongrel 1.1.5", "REMOTE_ADDR"=>"127.0.0.1", "rack.streaming"=>true,
|
|
22
|
+
"rack.version"=>[0, 1], "rack.multithread"=>true, "HTTP_VERSION"=>"HTTP/1.1", "rack.multiprocess"=>false,
|
|
23
|
+
"REQUEST_URI"=>"/search/?q=0017000000SmnJ0", "SERVER_PORT"=>"4000", "QUERY_STRING"=>"q=0017000000SmnJ0",
|
|
24
|
+
"GATEWAY_INTERFACE"=>"CGI/1.2", "HTTP_ACCEPT"=>"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
|
|
25
|
+
"REQUEST_METHOD"=>"GET", "HTTP_CONNECTION"=>"keep-alive"}
|
|
26
|
+
|
|
27
|
+
request = Merb::Request.new(rack_env)
|
|
28
|
+
stub(request).env { rack_env }
|
|
29
|
+
request
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: flyingmachine-merb_whoops_notifier
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: "1.0"
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Daniel Higginbotham
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-04-03 00:00:00 -07:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: merb-core
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 1.0.9
|
|
24
|
+
version:
|
|
25
|
+
description: Merb plugin that provides whoops exception notification
|
|
26
|
+
email: daniel@flyingmachinestudios.com
|
|
27
|
+
executables: []
|
|
28
|
+
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files:
|
|
32
|
+
- README
|
|
33
|
+
- LICENSE
|
|
34
|
+
- TODO
|
|
35
|
+
files:
|
|
36
|
+
- LICENSE
|
|
37
|
+
- README
|
|
38
|
+
- Rakefile
|
|
39
|
+
- TODO
|
|
40
|
+
- lib/merb_whoops_notifier
|
|
41
|
+
- lib/merb_whoops_notifier/merbtasks.rb
|
|
42
|
+
- lib/merb_whoops_notifier/whoops_mixin.rb
|
|
43
|
+
- lib/merb_whoops_notifier/whoops_notifier.rb
|
|
44
|
+
- lib/merb_whoops_notifier.rb
|
|
45
|
+
- spec/fixtures
|
|
46
|
+
- spec/fixtures/whoops.yml
|
|
47
|
+
- spec/merb_whoops_notifier_spec.rb
|
|
48
|
+
- spec/spec.opts
|
|
49
|
+
- spec/spec_helper.rb
|
|
50
|
+
has_rdoc: true
|
|
51
|
+
homepage: http://github.com/flyingmachine/merb_whoops_notifier
|
|
52
|
+
post_install_message:
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
|
|
55
|
+
require_paths:
|
|
56
|
+
- lib
|
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: "0"
|
|
62
|
+
version:
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: "0"
|
|
68
|
+
version:
|
|
69
|
+
requirements: []
|
|
70
|
+
|
|
71
|
+
rubyforge_project: merb
|
|
72
|
+
rubygems_version: 1.2.0
|
|
73
|
+
signing_key:
|
|
74
|
+
specification_version: 2
|
|
75
|
+
summary: Merb plugin that provides whoops exception notification
|
|
76
|
+
test_files: []
|
|
77
|
+
|