exceptional 2.0.5 → 2.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/exceptional +23 -13
- data/exceptional.gemspec +3 -3
- data/lib/exceptional.rb +5 -2
- data/lib/exceptional/application_environment.rb +2 -7
- data/lib/exceptional/catcher.rb +8 -1
- data/lib/exceptional/controller_exception_data.rb +4 -0
- data/lib/exceptional/exception_data.rb +5 -1
- data/lib/exceptional/integration/rack.rb +21 -0
- data/lib/exceptional/rack_exception_data.rb +29 -0
- data/lib/exceptional/remote.rb +2 -2
- data/lib/exceptional/startup.rb +1 -1
- data/spec/exceptional/exception_data_spec.rb +3 -0
- data/spec/exceptional/rack_exception_data_spec.rb +87 -0
- data/spec/rack_integration_spec.rb +21 -0
- data/spec/rails_integration_spec.rb +1 -1
- metadata +8 -4
data/bin/exceptional
CHANGED
@@ -12,25 +12,35 @@ test # Send a test exception to Exceptional.
|
|
12
12
|
install <api_key> # Create config/exceptional.yml with your api_key. Overrites existing one.
|
13
13
|
USAGE
|
14
14
|
when 'test'
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
if defined?(RAILS_ROOT)
|
16
|
+
puts "Loading Rails environment."
|
17
|
+
require(File.join('config', 'boot'))
|
18
|
+
require(File.join(RAILS_ROOT, 'config', 'environment')) if defined?(RAILS_ROOT)
|
19
|
+
require "exceptional/integration/tester"
|
20
|
+
else
|
21
|
+
require 'json'
|
22
|
+
require 'exceptional'
|
23
|
+
require "exceptional/integration/tester"
|
24
|
+
Exceptional::Config.load('config/exceptional.yml')
|
25
|
+
end
|
26
|
+
unless Exceptional::Config.api_key.empty?
|
20
27
|
Exceptional::Integration.test
|
21
|
-
|
28
|
+
else
|
29
|
+
puts 'API key not configured'
|
30
|
+
end
|
22
31
|
when 'install'
|
23
32
|
api_key = args[0]
|
24
33
|
if (api_key.nil?)
|
25
34
|
puts 'Missing required paramater <api-key>. Check your app configuration at http://getexceptional.com.'
|
26
35
|
else
|
27
|
-
|
28
|
-
puts "Run this command from the root of your rails application."
|
36
|
+
if (defined?(RAILS_ROOT) && !File.file?('config/environment.rb'))
|
37
|
+
puts "Run this command from the root of your rails application." and return
|
29
38
|
else
|
30
|
-
|
31
|
-
config_file.puts("api-key: #{api_key}\n")
|
32
|
-
config_file.close
|
33
|
-
puts "Config file written as config/exceptional.yml."
|
39
|
+
Dir.mkdir('config') unless File.exists?('config')
|
34
40
|
end
|
35
|
-
end
|
41
|
+
end
|
42
|
+
config_file = File.open('config/exceptional.yml', 'w')
|
43
|
+
config_file.puts("api-key: #{api_key}\n")
|
44
|
+
config_file.close
|
45
|
+
puts "Config file written as config/exceptional.yml."
|
36
46
|
end
|
data/exceptional.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = %q{exceptional}
|
4
|
-
s.version = "2.0.
|
4
|
+
s.version = "2.0.6"
|
5
5
|
s.authors = ["Contrast"]
|
6
|
-
s.summary = %q{
|
7
|
-
s.description = %q{Exceptional is the
|
6
|
+
s.summary = %q{ getexceptional.com is a hosted service for tracking errors in your Ruby/Rails/Rack apps }
|
7
|
+
s.description = %q{Exceptional is the Ruby gem for communicating with http://getexceptional.com (hosted error tracking service). Use it to find out about errors that happen in your live app. It captures lots of helpful information to help you fix the errors.}
|
8
8
|
s.email = %q{hello@contrast.ie}
|
9
9
|
s.files = Dir['lib/**/*'] + Dir['spec/**/*'] + Dir['spec/**/*'] + Dir['rails/**/*'] + Dir['tasks/**/*'] + Dir['*.rb'] + ["exceptional.gemspec"]
|
10
10
|
s.homepage = %q{http://getexceptional.com/}
|
data/lib/exceptional.rb
CHANGED
@@ -7,12 +7,15 @@ require 'exceptional/config'
|
|
7
7
|
require 'exceptional/application_environment'
|
8
8
|
require 'exceptional/exception_data'
|
9
9
|
require 'exceptional/controller_exception_data'
|
10
|
+
require 'exceptional/rack_exception_data'
|
10
11
|
require 'exceptional/remote'
|
12
|
+
require 'exceptional/integration/rack'
|
11
13
|
|
12
14
|
module Exceptional
|
15
|
+
|
13
16
|
PROTOCOL_VERSION = 5
|
14
|
-
VERSION = '2.0.
|
15
|
-
CLIENT_NAME = 'getexceptional-
|
17
|
+
VERSION = '2.0.6'
|
18
|
+
CLIENT_NAME = 'getexceptional-gem'
|
16
19
|
|
17
20
|
def self.logger
|
18
21
|
::Exceptional::LogFactory.logger
|
@@ -2,8 +2,8 @@ require 'digest/md5'
|
|
2
2
|
|
3
3
|
module Exceptional
|
4
4
|
class ApplicationEnvironment
|
5
|
-
def self.to_hash
|
6
|
-
|
5
|
+
def self.to_hash(framework)
|
6
|
+
{
|
7
7
|
'client' => {
|
8
8
|
'name' => Exceptional::CLIENT_NAME,
|
9
9
|
'version' => Exceptional::VERSION,
|
@@ -21,11 +21,6 @@ module Exceptional
|
|
21
21
|
'libraries_loaded' => libraries_loaded
|
22
22
|
}
|
23
23
|
}
|
24
|
-
hash
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.framework
|
28
|
-
defined?(RAILS_ENV) ? "rails" : nil
|
29
24
|
end
|
30
25
|
|
31
26
|
def self.environment
|
data/lib/exceptional/catcher.rb
CHANGED
@@ -7,6 +7,13 @@ module Exceptional
|
|
7
7
|
Remote.error(data)
|
8
8
|
end
|
9
9
|
end
|
10
|
+
|
11
|
+
def handle_with_rack(exception, environment, request)
|
12
|
+
if Config.should_send_to_api?
|
13
|
+
data = RackExceptionData.new(exception, environment, request)
|
14
|
+
Remote.error(data)
|
15
|
+
end
|
16
|
+
end
|
10
17
|
|
11
18
|
def handle(exception, name=nil)
|
12
19
|
if Config.should_send_to_api?
|
@@ -16,4 +23,4 @@ module Exceptional
|
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
19
|
-
end
|
26
|
+
end
|
@@ -8,7 +8,7 @@ module Exceptional
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def to_hash
|
11
|
-
hash = ::Exceptional::ApplicationEnvironment.to_hash
|
11
|
+
hash = ::Exceptional::ApplicationEnvironment.to_hash(framework)
|
12
12
|
hash.merge!({
|
13
13
|
'exception' => {
|
14
14
|
'exception_class' => @exception.class.to_s,
|
@@ -43,6 +43,10 @@ module Exceptional
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
def framework
|
48
|
+
nil
|
49
|
+
end
|
46
50
|
|
47
51
|
def uniqueness_hash
|
48
52
|
return nil if (@exception.backtrace.nil? || @exception.backtrace.empty?)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class Exceptional
|
6
|
+
|
7
|
+
def initialize(app, exceptional_config = "config/exceptional.yml")
|
8
|
+
@app = app
|
9
|
+
::Exceptional::Config.load(exceptional_config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
begin
|
14
|
+
status, headers, body = @app.call(env)
|
15
|
+
rescue Exception => e
|
16
|
+
::Exceptional::Catcher.handle_with_rack(e,env, Rack::Request.new(env))
|
17
|
+
raise(e)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Exceptional
|
4
|
+
class RackExceptionData < ExceptionData
|
5
|
+
def initialize(exception, environment, request)
|
6
|
+
super(exception)
|
7
|
+
@environment = environment
|
8
|
+
@request = request
|
9
|
+
end
|
10
|
+
|
11
|
+
def framework
|
12
|
+
"rack"
|
13
|
+
end
|
14
|
+
|
15
|
+
def extra_stuff
|
16
|
+
return {} if @request.nil?
|
17
|
+
{
|
18
|
+
'request' => {
|
19
|
+
'url' => "#{@request.url}",
|
20
|
+
'parameters' => @request.params,
|
21
|
+
'request_method' => @request.request_method.to_s,
|
22
|
+
'remote_ip' => @request.ip,
|
23
|
+
'headers' => @environment.reject{|k,v| !k.match(/^HTTP_/)},
|
24
|
+
'session' => @request.session
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/exceptional/remote.rb
CHANGED
@@ -37,10 +37,10 @@ module Exceptional
|
|
37
37
|
response = client.post(url, data)
|
38
38
|
case response
|
39
39
|
when Net::HTTPSuccess
|
40
|
-
Exceptional.logger.info(
|
40
|
+
Exceptional.logger.info( "#{url} Successful")
|
41
41
|
return true
|
42
42
|
else
|
43
|
-
Exceptional.logger.error(
|
43
|
+
Exceptional.logger.error("#{url} - #{response.code} - Failed")
|
44
44
|
end
|
45
45
|
rescue Exception => e
|
46
46
|
Exceptional.logger.error('Problem notifying Exceptional about the error')
|
data/lib/exceptional/startup.rb
CHANGED
@@ -7,7 +7,7 @@ module Exceptional
|
|
7
7
|
if Config.api_key.blank?
|
8
8
|
raise StartupException, 'API Key must be configured (/config/exceptional.yml)'
|
9
9
|
end
|
10
|
-
Remote.startup_announce(::Exceptional::ApplicationEnvironment.to_hash)
|
10
|
+
Remote.startup_announce(::Exceptional::ApplicationEnvironment.to_hash('rails'))
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -118,6 +118,7 @@ describe Exceptional::ControllerExceptionData, 'with request/controller/params'
|
|
118
118
|
@session_id = '123'
|
119
119
|
end
|
120
120
|
end
|
121
|
+
|
121
122
|
request = ActionController::TestRequest.new
|
122
123
|
session = SessionWithInstanceVariables.new
|
123
124
|
request.stub!(:session).and_return(session)
|
@@ -159,4 +160,6 @@ describe Exceptional::ControllerExceptionData, 'with request/controller/params'
|
|
159
160
|
data = Exceptional::ControllerExceptionData.new(myException)
|
160
161
|
data.uniqueness_hash.should == nil
|
161
162
|
end
|
163
|
+
|
164
|
+
|
162
165
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'digest/md5'
|
3
|
+
|
4
|
+
describe Exceptional::RackExceptionData do
|
5
|
+
|
6
|
+
class Exceptional::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 = Exceptional::FunkyError.new('some message')
|
43
|
+
request = Rack::Request.new(@env)
|
44
|
+
@data = Exceptional::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 == 'Exceptional::FunkyError'
|
50
|
+
error_hash['message'].should == 'some message'
|
51
|
+
error_hash['backtrace'].should == 'backtrace'
|
52
|
+
error_hash['occurred_at'].should == Time.now.strftime("%Y%m%d %H:%M:%S %Z")
|
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 == {"HTTP_HOST"=>"localhost:9292", "HTTP_ACCEPT"=>"*/*", "HTTP_USER_AGENT"=>"curl/7.19.6 (i386-apple-darwin9.8.0) libcurl/7.19.6 zlib/1.2.3", "HTTP_VERSION"=>"HTTP/1.1"}
|
62
|
+
request_hash['session'].should == {}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should capture client detais" do
|
66
|
+
client_hash = @data.to_hash['client']
|
67
|
+
client_hash['name'].should == Exceptional::CLIENT_NAME
|
68
|
+
client_hash['version'].should == Exceptional::VERSION
|
69
|
+
client_hash['protocol_version'].should == Exceptional::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,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'rack/mock'
|
3
|
+
|
4
|
+
class ExceptionalTestError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Rack::Exceptional do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
Exceptional::Config.should_receive(:load)
|
11
|
+
@error = ExceptionalTestError.new
|
12
|
+
@app = lambda { |env| raise @error, 'Whoops!' }
|
13
|
+
@env = env = Rack::MockRequest.env_for("/foo")
|
14
|
+
end
|
15
|
+
|
16
|
+
it 're-raises errors caught in the middleware' do
|
17
|
+
rr = Rack::Exceptional.new(@app)
|
18
|
+
Exceptional::Catcher.should_receive(:handle_with_rack)
|
19
|
+
lambda { rr.call(@env)}.should raise_error(ExceptionalTestError)
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exceptional
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Contrast
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-26 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: Exceptional is the
|
16
|
+
description: Exceptional is the Ruby gem for communicating with http://getexceptional.com (hosted error tracking service). Use it to find out about errors that happen in your live app. It captures lots of helpful information to help you fix the errors.
|
17
17
|
email: hello@contrast.ie
|
18
18
|
executables:
|
19
19
|
- exceptional
|
@@ -27,9 +27,11 @@ files:
|
|
27
27
|
- lib/exceptional/config.rb
|
28
28
|
- lib/exceptional/controller_exception_data.rb
|
29
29
|
- lib/exceptional/exception_data.rb
|
30
|
+
- lib/exceptional/integration/rack.rb
|
30
31
|
- lib/exceptional/integration/rails.rb
|
31
32
|
- lib/exceptional/integration/tester.rb
|
32
33
|
- lib/exceptional/log_factory.rb
|
34
|
+
- lib/exceptional/rack_exception_data.rb
|
33
35
|
- lib/exceptional/remote.rb
|
34
36
|
- lib/exceptional/startup.rb
|
35
37
|
- lib/exceptional.rb
|
@@ -37,12 +39,14 @@ files:
|
|
37
39
|
- spec/exceptional/catcher_spec.rb
|
38
40
|
- spec/exceptional/config_spec.rb
|
39
41
|
- spec/exceptional/exception_data_spec.rb
|
42
|
+
- spec/exceptional/rack_exception_data_spec.rb
|
40
43
|
- spec/exceptional/remote_spec.rb
|
41
44
|
- spec/exceptional/startup_spec.rb
|
42
45
|
- spec/exceptional_rescue_spec.rb
|
43
46
|
- spec/fixtures/exceptional.yml
|
44
47
|
- spec/fixtures/exceptional_old.yml
|
45
48
|
- spec/ginger_scenarios.rb
|
49
|
+
- spec/rack_integration_spec.rb
|
46
50
|
- spec/rails_integration_spec.rb
|
47
51
|
- spec/spec_helper.rb
|
48
52
|
- spec/standalone_spec.rb
|
@@ -78,6 +82,6 @@ rubyforge_project: exceptional
|
|
78
82
|
rubygems_version: 1.3.5
|
79
83
|
signing_key:
|
80
84
|
specification_version: 3
|
81
|
-
summary:
|
85
|
+
summary: getexceptional.com is a hosted service for tracking errors in your Ruby/Rails/Rack apps
|
82
86
|
test_files: []
|
83
87
|
|