sfalma 0.7
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/bin/sfalma +76 -0
- data/init.rb +27 -0
- data/install.rb +19 -0
- data/lib/sfalma/alert_data.rb +15 -0
- data/lib/sfalma/application_environment.rb +79 -0
- data/lib/sfalma/catcher.rb +26 -0
- data/lib/sfalma/config.rb +93 -0
- data/lib/sfalma/controller_exception_data.rb +69 -0
- data/lib/sfalma/exception_data.rb +146 -0
- data/lib/sfalma/integration/alerter.rb +11 -0
- data/lib/sfalma/integration/dj.rb +12 -0
- data/lib/sfalma/integration/rack.rb +28 -0
- data/lib/sfalma/integration/rack_rails.rb +26 -0
- data/lib/sfalma/integration/rails.rb +27 -0
- data/lib/sfalma/integration/sinatra.rb +6 -0
- data/lib/sfalma/integration/tester.rb +20 -0
- data/lib/sfalma/log_factory.rb +39 -0
- data/lib/sfalma/monkeypatches.rb +10 -0
- data/lib/sfalma/rack_exception_data.rb +29 -0
- data/lib/sfalma/railtie.rb +20 -0
- data/lib/sfalma/remote.rb +59 -0
- data/lib/sfalma/startup.rb +14 -0
- data/lib/sfalma/vcs.rb +45 -0
- data/lib/sfalma/version.rb +3 -0
- data/lib/sfalma.rb +71 -0
- data/lib/tasks/sfalma_tasks.rake +11 -0
- data/rails/init.rb +1 -0
- data/sfalma.gemspec +18 -0
- data/spec/bin/ginger +54 -0
- data/spec/dj_integration_spec.rb +29 -0
- data/spec/fixtures/favicon.png +0 -0
- data/spec/fixtures/sfalma.yml +10 -0
- data/spec/fixtures/sfalma_disabled.yml +4 -0
- data/spec/ginger_scenarios.rb +33 -0
- data/spec/rack_integration_spec.rb +21 -0
- data/spec/rails_integration_spec.rb +95 -0
- data/spec/rails_rack_integration_spec.rb +29 -0
- data/spec/sfalma/alert_exception_data_spec.rb +11 -0
- data/spec/sfalma/catcher_spec.rb +13 -0
- data/spec/sfalma/config_spec.rb +64 -0
- data/spec/sfalma/controller_exception_data_spec.rb +26 -0
- data/spec/sfalma/exception_data_spec.rb +198 -0
- data/spec/sfalma/monkeypatches_spec.rb +11 -0
- data/spec/sfalma/rack_exception_data_spec.rb +87 -0
- data/spec/sfalma/remote_spec.rb +31 -0
- data/spec/sfalma/startup_spec.rb +15 -0
- data/spec/sfalma_rescue_spec.rb +74 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/standalone_spec.rb +9 -0
- metadata +111 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Sfalma::Config, 'defaults' do
|
4
|
+
before :each do
|
5
|
+
Sfalma::Config.reset
|
6
|
+
end
|
7
|
+
it "have sensible defaults" do
|
8
|
+
Sfalma::Config.ssl?.should == false
|
9
|
+
Sfalma::Config.remote_host.should == 'api.sfalma.com'
|
10
|
+
Sfalma::Config.remote_port.should == 80
|
11
|
+
Sfalma::Config.application_root.should == Dir.pwd
|
12
|
+
Sfalma::Config.http_proxy_host.should be_nil
|
13
|
+
Sfalma::Config.http_proxy_port.should be_nil
|
14
|
+
Sfalma::Config.http_proxy_username.should be_nil
|
15
|
+
Sfalma::Config.http_proxy_password.should be_nil
|
16
|
+
Sfalma::Config.http_open_timeout.should == 2
|
17
|
+
Sfalma::Config.http_read_timeout.should == 4
|
18
|
+
end
|
19
|
+
it "have correct defaults when ssl" do
|
20
|
+
Sfalma::Config.ssl = true
|
21
|
+
Sfalma::Config.remote_host.should == 'api.sfalma.com'
|
22
|
+
Sfalma::Config.remote_port.should == 443
|
23
|
+
end
|
24
|
+
it "be disabled based on environment by default" do
|
25
|
+
%w(development test).each do |env|
|
26
|
+
Sfalma::Config.stub!(:application_environment).and_return(env)
|
27
|
+
Sfalma::Config.should_send_to_api?.should == false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
it "be enabled based on environment by default" do
|
31
|
+
%w(production staging).each do |env|
|
32
|
+
Sfalma::Config.stub!(:application_environment).and_return(env)
|
33
|
+
Sfalma::Config.should_send_to_api?.should == true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context 'production environment' do
|
37
|
+
before :each do
|
38
|
+
Sfalma::Config.stub!(:application_environment).and_return('production')
|
39
|
+
end
|
40
|
+
it "allow a new simpler format for " do
|
41
|
+
Sfalma::Config.load('spec/fixtures/sfalma.yml')
|
42
|
+
Sfalma::Config.api_key.should == 'abc123'
|
43
|
+
Sfalma::Config.ssl?.should == true
|
44
|
+
Sfalma::Config.remote_host.should == 'example.com'
|
45
|
+
Sfalma::Config.remote_port.should == 123
|
46
|
+
Sfalma::Config.should_send_to_api?.should == true
|
47
|
+
Sfalma::Config.http_proxy_host.should == 'annoying-proxy.example.com'
|
48
|
+
Sfalma::Config.http_proxy_port.should == 1066
|
49
|
+
Sfalma::Config.http_proxy_username.should == 'bob'
|
50
|
+
Sfalma::Config.http_proxy_password.should == 'jack'
|
51
|
+
Sfalma::Config.http_open_timeout.should == 5
|
52
|
+
Sfalma::Config.http_read_timeout.should == 10
|
53
|
+
end
|
54
|
+
it "allow disable production environment" do
|
55
|
+
Sfalma::Config.load('spec/fixtures/sfalma_disabled.yml')
|
56
|
+
Sfalma::Config.api_key.should == 'abc123'
|
57
|
+
Sfalma::Config.should_send_to_api?.should == false
|
58
|
+
end
|
59
|
+
it "load api_key from environment variable" do
|
60
|
+
ENV.should_receive(:[]).with('SFALMA_API_KEY').any_number_of_times.and_return('98765')
|
61
|
+
Sfalma::Config.api_key.should == '98765'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
|
5
|
+
class Sfalma::FunkyError < StandardError
|
6
|
+
def backtrace
|
7
|
+
'backtrace'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class BrokenJSON
|
12
|
+
def to_json
|
13
|
+
boom.time!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Sfalma::ControllerExceptionData do
|
18
|
+
it "raises useful error when to_json isn't available on to_hash" do
|
19
|
+
request = ActionController::TestRequest.new
|
20
|
+
brokenJson = BrokenJSON.new
|
21
|
+
session = {:boom => brokenJson}
|
22
|
+
request.stub!(:session).and_return(session)
|
23
|
+
data = Sfalma::ControllerExceptionData.new(Sfalma::FunkyError.new, nil, request)
|
24
|
+
JSON.parse(data.to_json)['request']['session']['data'].should == {"boom" => brokenJson.to_s}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
class Sfalma::FunkyError < StandardError
|
5
|
+
def backtrace
|
6
|
+
'backtrace'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Sfalma::ControllerExceptionData do
|
11
|
+
it "raises useful error when to_json isn't available on to_hash" do
|
12
|
+
begin
|
13
|
+
data = Sfalma::ExceptionData.new(Sfalma::FunkyError.new)
|
14
|
+
hash_without_json = {}
|
15
|
+
hash_without_json.stub!(:to_json).and_raise(NoMethodError)
|
16
|
+
data.stub!(:to_hash).and_return(hash_without_json)
|
17
|
+
data.to_json
|
18
|
+
fail 'expects to raise and error'
|
19
|
+
rescue StandardError => e
|
20
|
+
e.message.should =~ /to_json/
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Sfalma::ControllerExceptionData, 'when no request/controller/params' do
|
26
|
+
before :each do
|
27
|
+
ENV['LOGNAME'] = 'bob'
|
28
|
+
ENV['SOMEVAR'] = 'something'
|
29
|
+
ENV['SOMEOTHERVAR'] = 'something else'
|
30
|
+
Sfalma::ENVIRONMENT_FILTER << 'SOMEOTHERVAR'
|
31
|
+
ENV['HTTP_SOMETHING'] = 'should be stripped'
|
32
|
+
::RAILS_ENV = 'test' unless defined?(RAILS_ENV)
|
33
|
+
Time.stub!(:now).and_return(Time.mktime(1970, 1, 1))
|
34
|
+
error = Sfalma::FunkyError.new('some message')
|
35
|
+
@data = Sfalma::ControllerExceptionData.new(error)
|
36
|
+
@hash = @data.to_hash
|
37
|
+
end
|
38
|
+
|
39
|
+
it "capture exception details" do
|
40
|
+
error_hash = @hash['exception']
|
41
|
+
error_hash['exception_class'].should == 'Sfalma::FunkyError'
|
42
|
+
error_hash['message'].should == 'some message'
|
43
|
+
error_hash['backtrace'].should == 'backtrace'
|
44
|
+
DateTime.parse(error_hash['occurred_at']).should == DateTime.now
|
45
|
+
client_hash = @hash['client']
|
46
|
+
client_hash['name'].should == Sfalma::CLIENT_NAME
|
47
|
+
client_hash['version'].should == Sfalma::VERSION
|
48
|
+
client_hash['protocol_version'].should == Sfalma::PROTOCOL_VERSION
|
49
|
+
end
|
50
|
+
|
51
|
+
it "generates parseable json" do
|
52
|
+
require 'json'
|
53
|
+
JSON.parse(@data.to_json)['exception']['exception_class'].should == 'Sfalma::FunkyError'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "capture application_environment" do
|
57
|
+
application_env_hash = @hash['application_environment']
|
58
|
+
application_env_hash['environment'].should == 'test'
|
59
|
+
application_env_hash['env'].should_not be_nil
|
60
|
+
application_env_hash['env']['SOMEVAR'].should == 'something'
|
61
|
+
application_env_hash['env']['SOMEOTHERVAR'].should == nil
|
62
|
+
application_env_hash['host'].should == `hostname`.strip
|
63
|
+
application_env_hash['run_as_user'].should == 'bob'
|
64
|
+
application_env_hash['application_root_directory'].should == Dir.pwd
|
65
|
+
application_env_hash['language'].should == 'ruby'
|
66
|
+
application_env_hash['language_version'].should == "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE} #{RUBY_PLATFORM}"
|
67
|
+
application_env_hash['framework'].should == "rails"
|
68
|
+
application_env_hash['libraries_loaded']['rails'].should =~ /\d\.\d\.\d/
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Sfalma::ControllerExceptionData, 'with request/controller/params' do
|
73
|
+
class Sfalma::SomeController < ActionController::Base
|
74
|
+
filter_parameter_logging :filter_me
|
75
|
+
end
|
76
|
+
|
77
|
+
before :each do
|
78
|
+
@controller = Sfalma::SomeController.new
|
79
|
+
@request = ActionController::TestRequest.new({'action' => 'some_action' })
|
80
|
+
@request.request_uri = '/some_path?var1=abc'
|
81
|
+
@request.stub!(:parameters).and_return({'var1' => 'abc', 'action' => 'some_action', 'filter_me' => 'private'})
|
82
|
+
@request.stub!(:request_method).and_return(:get)
|
83
|
+
@request.stub!(:remote_ip).and_return('1.2.3.4')
|
84
|
+
@request.stub!(:env).and_return({'SOME_VAR' => 'abc', 'HTTP_CONTENT_TYPE' => 'text/html'})
|
85
|
+
@error = Sfalma::FunkyError.new('some message')
|
86
|
+
data = Sfalma::ControllerExceptionData.new(@error, @controller, @request)
|
87
|
+
@hash = data.to_hash
|
88
|
+
end
|
89
|
+
|
90
|
+
it "captures request" do
|
91
|
+
request_hash = @hash['request']
|
92
|
+
request_hash['url'].should == 'http://test.host/some_path?var1=abc'
|
93
|
+
request_hash['controller'].should == 'Sfalma::SomeController'
|
94
|
+
request_hash['action'].should == 'some_action'
|
95
|
+
request_hash['parameters'].should == {'var1' => 'abc', 'action' => 'some_action', 'filter_me' => '[FILTERED]'}
|
96
|
+
request_hash['request_method'].should == 'get'
|
97
|
+
request_hash['remote_ip'].should == '1.2.3.4'
|
98
|
+
request_hash['headers'].should == {'Content-Type' => 'text/html'}
|
99
|
+
end
|
100
|
+
|
101
|
+
it "filter out objects that aren't jsonable" do
|
102
|
+
class Crazy
|
103
|
+
def initialize
|
104
|
+
@bar = self
|
105
|
+
end
|
106
|
+
end
|
107
|
+
crazy = Crazy.new
|
108
|
+
input = {'crazy' => crazy, :simple => '123', :some_hash => {'1' => '2'}, :array => ['1', '2']}
|
109
|
+
Sfalma::ControllerExceptionData.sanitize_hash(input).should == {'crazy' => crazy.to_s, :simple => '123', :some_hash => {'1' => '2'}, :array => ['1', '2']}
|
110
|
+
end
|
111
|
+
|
112
|
+
it "allow if non jsonable objects are hidden in an array" do
|
113
|
+
class Bonkers
|
114
|
+
def to_json
|
115
|
+
no.can.do!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
crazy = Bonkers.new
|
119
|
+
input = {'crazy' => [crazy]}
|
120
|
+
Sfalma::ControllerExceptionData.sanitize_hash(input).should == {'crazy' => [crazy.to_s]}
|
121
|
+
end
|
122
|
+
|
123
|
+
it "filter params specified in env['action_dispatch.parameter_filter']" do
|
124
|
+
@request.stub!(:env).and_return({'SOME_VAR' => 'abc', 'HTTP_CONTENT_TYPE' => 'text/html', 'action_dispatch.parameter_filter' => [:var1]})
|
125
|
+
@request.stub!(:parameters).and_return({'var1' => 'abc'})
|
126
|
+
data = Sfalma::ControllerExceptionData.new(@error, @controller, @request)
|
127
|
+
data.to_hash['request']['parameters'].should == {'var1' => '[FILTERED]'}
|
128
|
+
end
|
129
|
+
|
130
|
+
it "formats the occurred_at as iso8601" do
|
131
|
+
@request.stub!(:env).and_return({'SOME_VAR' => 'abc', 'HTTP_CONTENT_TYPE' => 'text/html', 'action_dispatch.parameter_filter' => [:var1]})
|
132
|
+
@request.stub!(:parameters).and_return({'var1' => 'abc'})
|
133
|
+
data = Sfalma::ControllerExceptionData.new(@error, @controller, @request)
|
134
|
+
data.to_hash['exception']['occurred_at'].should match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.{1,6}$/)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "ArgumentError bug with file object" do
|
138
|
+
file = File.new(File.expand_path('../../fixtures/favicon.png',__FILE__))
|
139
|
+
@request.stub!(:parameters).and_return({'something' => file })
|
140
|
+
data = Sfalma::ControllerExceptionData.new(@error, @controller, @request)
|
141
|
+
data.to_hash['request']['parameters']['something'].should == file.to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
it "to_strings regex because JSON.parse(/aa/.to_json) doesn't work" do
|
145
|
+
input = {'crazy' => /abc.*/}
|
146
|
+
Sfalma::ExceptionData.sanitize_hash(input).should == {'crazy' => /abc.*/.to_s}
|
147
|
+
end
|
148
|
+
|
149
|
+
it "handles session objects with various interfaces" do
|
150
|
+
class SessionWithInstanceVariables
|
151
|
+
def initialize
|
152
|
+
@data = {'a' => '1', 'b' => /hello there Im a regex/i}
|
153
|
+
@session_id = '123'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
request = ActionController::TestRequest.new
|
158
|
+
session = SessionWithInstanceVariables.new
|
159
|
+
request.stub!(:session).and_return(session)
|
160
|
+
request.stub!(:session_options).and_return({})
|
161
|
+
Sfalma::ControllerExceptionData.sanitize_session(request).should == {'session_id' => '123', 'data' => {'a' => '1', 'b' => "(?i-mx:hello there Im a regex)"}}
|
162
|
+
session = mock('session', :session_id => '123', :instance_variable_get => {'a' => '1', 'b' => /another(.+) regex/mx})
|
163
|
+
request.stub!(:session).and_return(session)
|
164
|
+
Sfalma::ControllerExceptionData.sanitize_session(request).should == {'session_id' => '123', 'data' => {'a' => '1', 'b' => "(?mx-i:another(.+) regex)"}}
|
165
|
+
session = mock('session', :session_id => nil, :to_hash => {:session_id => '123', 'a' => '1'})
|
166
|
+
request.stub!(:session).and_return(session)
|
167
|
+
Sfalma::ControllerExceptionData.sanitize_session(request).should == {'session_id' => '123', 'data' => {'a' => '1'}}
|
168
|
+
request.stub!(:session_options).and_return({:id => 'xyz'})
|
169
|
+
Sfalma::ControllerExceptionData.sanitize_session(request).should == {'session_id' => 'xyz', 'data' => {'a' => '1'}}
|
170
|
+
end
|
171
|
+
|
172
|
+
it "filter session cookies from headers" do
|
173
|
+
@request.stub!(:env).and_return({'SOME_VAR' => 'abc', 'HTTP_COOKIE' => '_something_else=faafsafafasfa; _myapp-lick-nation_session=BAh7DDoMbnVtYmVyc1sJaQZpB2kIaQk6FnNvbWVfY3Jhenlfb2JqZWN0bzobU3Bpa2VDb250cm9sbGVyOjpDcmF6eQY6CUBiYXJABzoTc29tZXRoaW5nX2Vsc2UiCGNjYzoKYXBwbGUiDUJyYWVidXJuOgloYXNoewdpBmkHaQhpCToPc2Vzc2lvbl9pZCIlMmJjZTM4MjVjMThkNzYxOWEyZDA4NTJhNWY1NGQzMmU6C3RvbWF0byIJQmVlZg%3D%3D--66fb4606851f06bf409b8bc4ba7aea47a0259bf7'})
|
174
|
+
@hash = Sfalma::ControllerExceptionData.new(Sfalma::FunkyError.new('some message'), @controller, @request).to_hash
|
175
|
+
@hash['request']['headers'].should == {'Cookie' => '_something_else=faafsafafasfa; _myapp-lick-nation_session=[FILTERED]'}
|
176
|
+
end
|
177
|
+
|
178
|
+
it "creates a uniqueness_hash from backtrace" do
|
179
|
+
exception = Exception.new
|
180
|
+
exception.stub!(:backtrace).and_return(['123'])
|
181
|
+
data = Sfalma::ControllerExceptionData.new(exception)
|
182
|
+
data.uniqueness_hash.should == Digest::MD5.hexdigest('123')
|
183
|
+
end
|
184
|
+
|
185
|
+
it "creates a nil uniqueness_hash if nil backtrace" do
|
186
|
+
exception = Exception.new
|
187
|
+
exception.stub!(:backtrace).and_return(nil)
|
188
|
+
data = Sfalma::ControllerExceptionData.new(exception)
|
189
|
+
data.uniqueness_hash.should == nil
|
190
|
+
end
|
191
|
+
|
192
|
+
it "creates a uniqueness_hash from backtrace" do
|
193
|
+
exception = Exception.new
|
194
|
+
exception.stub!(:backtrace).and_return([])
|
195
|
+
data = Sfalma::ControllerExceptionData.new(exception)
|
196
|
+
data.uniqueness_hash.should == nil
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.join(File.dirname(__FILE__), '../..', 'lib', 'sfalma', 'monkeypatches')
|
3
|
+
|
4
|
+
describe Regexp do
|
5
|
+
it "should output a correctly formatted string" do
|
6
|
+
/hello/.to_json.should == "\"(?-mix:hello)\""
|
7
|
+
end
|
8
|
+
it "should output a correctly formatted string" do
|
9
|
+
2.to_json.should == "2"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
describe Sfalma::RackExceptionData do
|
5
|
+
|
6
|
+
class Sfalma::FunkyError < StandardError
|
7
|
+
def backtrace
|
8
|
+
'backtrace'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
app = lambda { |env| [200, {'Content-Type'=>'text/plain'}, 'Hello World']}
|
14
|
+
|
15
|
+
@env = {
|
16
|
+
"HTTP_HOST" =>"localhost:9292",
|
17
|
+
"HTTP_ACCEPT" =>"*/*",
|
18
|
+
"SERVER_NAME" =>"localhost",
|
19
|
+
"REQUEST_PATH" =>"/",
|
20
|
+
"rack.url_scheme" =>"http",
|
21
|
+
"HTTP_USER_AGENT" =>"curl/7.19.6 (i386-apple-darwin9.8.0) libcurl/7.19.6 zlib/1.2.3",
|
22
|
+
"REMOTE_HOST" =>"testing.com",
|
23
|
+
"rack.errors" => StringIO.new,
|
24
|
+
"SERVER_PROTOCOL" =>"HTTP/1.1",
|
25
|
+
"rack.version" =>[1, 1],
|
26
|
+
"rack.run_once" =>false,
|
27
|
+
"SERVER_SOFTWARE" =>"WEBrick/1.3.1 (Ruby/1.8.7/2009-06-12)",
|
28
|
+
"REMOTE_ADDR" =>"127.0.0.1",
|
29
|
+
"PATH_INFO" => "/",
|
30
|
+
"SCRIPT_NAME" =>"",
|
31
|
+
"HTTP_VERSION" =>"HTTP/1.1",
|
32
|
+
"rack.multithread" =>true,
|
33
|
+
"rack.multiprocess" =>false,
|
34
|
+
"REQUEST_URI" =>"http://localhost:9292/",
|
35
|
+
"SERVER_PORT" =>"9292",
|
36
|
+
"REQUEST_METHOD" =>"GET",
|
37
|
+
"rack.input" => StringIO.new,
|
38
|
+
"QUERY_STRING" =>"cockle=shell&bay=cool",
|
39
|
+
"GATEWAY_INTERFACE" =>"CGI/1.1"
|
40
|
+
}
|
41
|
+
|
42
|
+
error = Sfalma::FunkyError.new('some message')
|
43
|
+
request = Rack::Request.new(@env)
|
44
|
+
@data = Sfalma::RackExceptionData.new(error, @env, request)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "capture exception details" do
|
48
|
+
error_hash = @data.to_hash['exception']
|
49
|
+
error_hash['exception_class'].should == 'Sfalma::FunkyError'
|
50
|
+
error_hash['message'].should == 'some message'
|
51
|
+
error_hash['backtrace'].should == 'backtrace'
|
52
|
+
DateTime.parse(error_hash['occurred_at']).should == DateTime.parse(Time.now.to_json)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should capture request details" do
|
56
|
+
request_hash = @data.to_hash['request']
|
57
|
+
request_hash['url'].should == 'http://localhost:9292/?cockle=shell&bay=cool'
|
58
|
+
request_hash['parameters'].should == {"cockle"=>"shell", "bay"=>"cool"}
|
59
|
+
request_hash['request_method'].should == 'GET'
|
60
|
+
request_hash['remote_ip'].should == '127.0.0.1'
|
61
|
+
request_hash['headers'].should == {"Host"=>"localhost:9292", "Accept"=>"*/*", "User-Agent"=>"curl/7.19.6 (i386-apple-darwin9.8.0) libcurl/7.19.6 zlib/1.2.3", "Version"=>"HTTP/1.1"}
|
62
|
+
request_hash['session'].should == {'data' => {}, 'session_id' => ''}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should capture client detais" do
|
66
|
+
client_hash = @data.to_hash['client']
|
67
|
+
client_hash['name'].should == Sfalma::CLIENT_NAME
|
68
|
+
client_hash['version'].should == Sfalma::VERSION
|
69
|
+
client_hash['protocol_version'].should == Sfalma::PROTOCOL_VERSION
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should captire application environment" do
|
73
|
+
env_hash = @data.to_hash['application_environment']
|
74
|
+
env_hash['env'].should_not be_empty #execution dependent
|
75
|
+
env_hash['libraries_loaded'].should_not be_empty #execution dependent
|
76
|
+
env_hash['language'].should == 'ruby' #execution dependent
|
77
|
+
|
78
|
+
env_hash['language_version'].should_not be_empty #execution dependent
|
79
|
+
env_hash['environment'].should == 'test'
|
80
|
+
env_hash['application_root_directory'].should_not be_empty
|
81
|
+
env_hash['run_as_user'].should_not be_empty
|
82
|
+
env_hash['host'].should_not be_empty
|
83
|
+
|
84
|
+
env_hash['framework'].should == 'rack'
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'zlib'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
describe Sfalma::Remote do
|
6
|
+
before :each do
|
7
|
+
Sfalma::Config.reset
|
8
|
+
Sfalma::Config.api_key = 'abc123'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "calls remote with api_key, protocol_version and json" do
|
12
|
+
expected_url = "/api/errors?api_key=abc123&protocol_version=#{Sfalma::PROTOCOL_VERSION}"
|
13
|
+
expected_data = mock('data',:uniqueness_hash => nil, :to_json => '123')
|
14
|
+
Sfalma::Remote.should_receive(:call_remote).with(expected_url, Zlib::Deflate.deflate(expected_data.to_json,Zlib::BEST_SPEED))
|
15
|
+
Sfalma::Remote.error(expected_data)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "adds hash of backtrace as paramater if it is present" do
|
19
|
+
expected_url = "/api/errors?api_key=abc123&protocol_version=#{Sfalma::PROTOCOL_VERSION}&hash=blah"
|
20
|
+
expected_data = mock('data',:uniqueness_hash => 'blah', :to_json => '123')
|
21
|
+
Sfalma::Remote.should_receive(:call_remote).with(expected_url, Zlib::Deflate.deflate(expected_data.to_json,Zlib::BEST_SPEED))
|
22
|
+
Sfalma::Remote.error(expected_data)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "calls remote for startup" do
|
26
|
+
expected_url = "/api/announcements?api_key=abc123&protocol_version=#{Sfalma::PROTOCOL_VERSION}"
|
27
|
+
startup_data = mock('data',:to_json => '123')
|
28
|
+
Sfalma::Remote.should_receive(:call_remote).with(expected_url, Zlib::Deflate.deflate(startup_data.to_json,Zlib::BEST_SPEED))
|
29
|
+
Sfalma::Remote.startup_announce(startup_data)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Sfalma::Startup, 'announce_and_authenticate' do
|
4
|
+
it "raise StartupException if api_key is nil" do
|
5
|
+
Sfalma::Config.api_key = ''
|
6
|
+
lambda { Sfalma::Startup.announce }.should raise_error(Sfalma::StartupException, /API Key/)
|
7
|
+
end
|
8
|
+
it "calls Remote announce" do
|
9
|
+
Sfalma::Config.api_key = '123'
|
10
|
+
Sfalma::Remote.should_receive(:startup_announce).with(hash_including({'client' => { 'name' => Sfalma::CLIENT_NAME,
|
11
|
+
'version' => Sfalma::VERSION,
|
12
|
+
'protocol_version' => Sfalma::PROTOCOL_VERSION}}))
|
13
|
+
Sfalma::Startup.announce
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
context 'resuce errors from within a block' do
|
4
|
+
class FunkyException < StandardError;
|
5
|
+
end
|
6
|
+
it "Sfalma.rescue should send to sfalma and swallow error " do
|
7
|
+
to_raise = FunkyException.new
|
8
|
+
Sfalma::Catcher.should_receive(:handle).with(to_raise, 'my rescue name')
|
9
|
+
Sfalma.rescue('my rescue name') do
|
10
|
+
raise to_raise
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "reraises error with rescue_and_reraise" do
|
15
|
+
to_raise = FunkyException.new
|
16
|
+
Sfalma::Catcher.should_receive(:handle).with(to_raise, 'my rescue name')
|
17
|
+
begin
|
18
|
+
Sfalma.rescue_and_reraise('my rescue name') do
|
19
|
+
raise to_raise
|
20
|
+
end
|
21
|
+
fail 'expected a reraise'
|
22
|
+
rescue FunkyException => e
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "Sfalma.handle calls Sfalma::Catcher.handle" do
|
27
|
+
to_raise = FunkyException.new
|
28
|
+
Sfalma::Catcher.should_receive(:handle).with(to_raise, 'optional name for where it has occurred')
|
29
|
+
begin
|
30
|
+
raise to_raise
|
31
|
+
rescue => e
|
32
|
+
Sfalma.handle(e, 'optional name for where it has occurred')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "collects context information but leaves thread local empty after block" do
|
37
|
+
to_raise = FunkyException.new
|
38
|
+
Sfalma::Config.should_receive(:should_send_to_api?).and_return(true)
|
39
|
+
Sfalma::Remote.should_receive(:error) {|exception_data|
|
40
|
+
exception_data.to_hash['context']['foo'] == 'bar'
|
41
|
+
exception_data.to_hash['context']['baz'] == 42
|
42
|
+
exception_data.to_hash['context']['cats'] == {'lol' => 'bot'}
|
43
|
+
}
|
44
|
+
Sfalma.rescue('my rescue name') do
|
45
|
+
Sfalma.context('foo' => 'bar')
|
46
|
+
Sfalma.context('baz' => 42)
|
47
|
+
Sfalma.context('cats' => {'lol' => 'bot'})
|
48
|
+
raise to_raise
|
49
|
+
end
|
50
|
+
Thread.current[:exceptional_context].should == nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "clearr context with Sfalma.context.clear!" do
|
54
|
+
Sfalma.context('foo' => 'bar')
|
55
|
+
Thread.current[:exceptional_context].should_not == nil
|
56
|
+
Sfalma.context.clear!
|
57
|
+
Thread.current[:exceptional_context].should == nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "allows optional second paramater hash to get added to context" do
|
61
|
+
Sfalma.should_receive(:context).with(context_hash = {'foo' => 'bar', 'baz' => 42})
|
62
|
+
Sfalma.rescue('my rescue', context_hash) {}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should clear context after every invocation" do
|
66
|
+
Thread.current[:exceptional_context].should == nil
|
67
|
+
|
68
|
+
Sfalma.rescue('my rescue', context_hash = {'foo' => 'bar', 'baz' => 42}) {
|
69
|
+
Thread.current[:exceptional_context].should_not == nil
|
70
|
+
}
|
71
|
+
|
72
|
+
Thread.current[:exceptional_context].should == nil
|
73
|
+
end
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
begin
|
3
|
+
require 'ginger'
|
4
|
+
rescue LoadError
|
5
|
+
raise "cant load ginger"
|
6
|
+
end
|
7
|
+
|
8
|
+
gem 'rails'
|
9
|
+
require File.dirname(__FILE__) + '/../lib/sfalma' unless defined?(Sfalma)
|
10
|
+
|
11
|
+
ENV['RAILS_ENV'] = 'test'
|
12
|
+
|
13
|
+
require 'action_controller'
|
14
|
+
require 'action_controller/test_process'
|
15
|
+
|
16
|
+
def send_request(action = nil,params={})
|
17
|
+
@request = ActionController::TestRequest.new
|
18
|
+
@request.query_parameters = @request.query_parameters.merge(params)
|
19
|
+
@request.stub!(:request_method).and_return('GET')
|
20
|
+
@request.action = action ? action.to_s : ""
|
21
|
+
@response = ActionController::TestResponse.new
|
22
|
+
@controller.process(@request, @response)
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'sfalma', 'integration', 'rails')
|
3
|
+
|
4
|
+
describe Sfalma do
|
5
|
+
it "set the api key" do
|
6
|
+
Sfalma.configure('api-key')
|
7
|
+
Sfalma::Config.api_key.should == 'api-key'
|
8
|
+
end
|
9
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sfalma
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.7'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sfalma
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-05-05 00:00:00.000000000 +03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: &15079640 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *15079640
|
26
|
+
description: ! 'Sfalma is the Ruby gem for communicating with http://sfalma.com (hosted
|
27
|
+
error tracking service). Use it to find out about errors that happen in your web
|
28
|
+
or mobile app. '
|
29
|
+
email: info@sfalma.com
|
30
|
+
executables:
|
31
|
+
- sfalma
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- lib/tasks/sfalma_tasks.rake
|
36
|
+
- lib/sfalma/vcs.rb
|
37
|
+
- lib/sfalma/config.rb
|
38
|
+
- lib/sfalma/log_factory.rb
|
39
|
+
- lib/sfalma/rack_exception_data.rb
|
40
|
+
- lib/sfalma/railtie.rb
|
41
|
+
- lib/sfalma/application_environment.rb
|
42
|
+
- lib/sfalma/version.rb
|
43
|
+
- lib/sfalma/integration/dj.rb
|
44
|
+
- lib/sfalma/integration/rack_rails.rb
|
45
|
+
- lib/sfalma/integration/rack.rb
|
46
|
+
- lib/sfalma/integration/rails.rb
|
47
|
+
- lib/sfalma/integration/alerter.rb
|
48
|
+
- lib/sfalma/integration/tester.rb
|
49
|
+
- lib/sfalma/integration/sinatra.rb
|
50
|
+
- lib/sfalma/remote.rb
|
51
|
+
- lib/sfalma/monkeypatches.rb
|
52
|
+
- lib/sfalma/alert_data.rb
|
53
|
+
- lib/sfalma/startup.rb
|
54
|
+
- lib/sfalma/controller_exception_data.rb
|
55
|
+
- lib/sfalma/catcher.rb
|
56
|
+
- lib/sfalma/exception_data.rb
|
57
|
+
- lib/sfalma.rb
|
58
|
+
- spec/rails_integration_spec.rb
|
59
|
+
- spec/sfalma_rescue_spec.rb
|
60
|
+
- spec/ginger_scenarios.rb
|
61
|
+
- spec/fixtures/favicon.png
|
62
|
+
- spec/fixtures/sfalma.yml
|
63
|
+
- spec/fixtures/sfalma_disabled.yml
|
64
|
+
- spec/bin/ginger
|
65
|
+
- spec/rails_rack_integration_spec.rb
|
66
|
+
- spec/rack_integration_spec.rb
|
67
|
+
- spec/sfalma/alert_exception_data_spec.rb
|
68
|
+
- spec/sfalma/rack_exception_data_spec.rb
|
69
|
+
- spec/sfalma/startup_spec.rb
|
70
|
+
- spec/sfalma/config_spec.rb
|
71
|
+
- spec/sfalma/catcher_spec.rb
|
72
|
+
- spec/sfalma/remote_spec.rb
|
73
|
+
- spec/sfalma/exception_data_spec.rb
|
74
|
+
- spec/sfalma/monkeypatches_spec.rb
|
75
|
+
- spec/sfalma/controller_exception_data_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
- spec/dj_integration_spec.rb
|
78
|
+
- spec/standalone_spec.rb
|
79
|
+
- rails/init.rb
|
80
|
+
- init.rb
|
81
|
+
- install.rb
|
82
|
+
- sfalma.gemspec
|
83
|
+
- bin/sfalma
|
84
|
+
has_rdoc: true
|
85
|
+
homepage: http://sfalma.com/
|
86
|
+
licenses: []
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements:
|
104
|
+
- json_pure, json-jruby or json gem required
|
105
|
+
rubyforge_project: sfalma
|
106
|
+
rubygems_version: 1.5.3
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: sfalma.com is a cloud-based error tracker with a social twist with a focus
|
110
|
+
on mobile apps
|
111
|
+
test_files: []
|