exceptional 2.0.14 → 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/init.rb +13 -4
- data/install.rb +3 -3
- data/lib/exceptional.rb +2 -1
- data/lib/exceptional/controller_exception_data.rb +6 -31
- data/lib/exceptional/exception_data.rb +32 -2
- data/lib/exceptional/integration/rack_rails.rb +21 -0
- data/lib/exceptional/rack_exception_data.rb +4 -4
- data/lib/exceptional/version.rb +1 -1
- data/spec/exceptional/exception_data_spec.rb +1 -1
- data/spec/exceptional/rack_exception_data_spec.rb +2 -2
- data/spec/rails_rack_integration_spec.rb +29 -0
- metadata +20 -5
data/init.rb
CHANGED
@@ -15,10 +15,19 @@ if (defined?(Exceptional::VERSION::STRING) rescue nil) && %w(development test).i
|
|
15
15
|
else
|
16
16
|
begin
|
17
17
|
Exceptional::Config.load(File.join(RAILS_ROOT, "/config/exceptional.yml"))
|
18
|
-
|
19
|
-
|
18
|
+
|
19
|
+
Exceptional.logger.info("Loading Exceptional for #{Rails::VERSION::STRING}")
|
20
|
+
|
21
|
+
if Rails::VERSION::STRING.to_i > 2
|
22
|
+
puts "Exceptional Rails 3 Support via Rack"
|
23
|
+
::Rails.configuration.middleware.insert_after 'ActionDispatch::ShowExceptions', Rack::RailsExceptional
|
24
|
+
else
|
25
|
+
require File.join('exceptional', 'integration', 'rails')
|
26
|
+
require File.join('exceptional', 'integration', 'dj')
|
27
|
+
end
|
20
28
|
rescue => e
|
21
29
|
STDERR.puts "Problem starting Exceptional Plugin. Your app will run as normal."
|
22
|
-
|
30
|
+
Exceptional.logger.error(e.message)
|
31
|
+
Exceptional.logger.error(e.backtrace)
|
23
32
|
end
|
24
|
-
end
|
33
|
+
end
|
data/install.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This is the post install hook for when Exceptional is installed as a plugin.
|
2
|
-
require '
|
3
|
-
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
4
|
# puts IO.read(File.join(File.dirname(__FILE__), 'README'))
|
5
5
|
|
6
6
|
config_file = File.expand_path("#{File.dirname(__FILE__)}/../../../config/exceptional.yml")
|
@@ -15,5 +15,5 @@ else
|
|
15
15
|
puts "For exceptional to work you need to configure your API key."
|
16
16
|
puts " See #{example_config_file}"
|
17
17
|
puts "If you don't have an API key, get one at http://getexceptional.com/."
|
18
|
-
|
18
|
+
FileUtils.copy example_config_file, config_file
|
19
19
|
end
|
data/lib/exceptional.rb
CHANGED
@@ -9,7 +9,8 @@ require 'exceptional/exception_data'
|
|
9
9
|
require 'exceptional/controller_exception_data'
|
10
10
|
require 'exceptional/rack_exception_data'
|
11
11
|
require 'exceptional/remote'
|
12
|
-
require 'exceptional/integration/rack'
|
12
|
+
require 'exceptional/integration/rack'
|
13
|
+
require 'exceptional/integration/rack_rails'
|
13
14
|
require 'exceptional/version'
|
14
15
|
|
15
16
|
module Exceptional
|
@@ -12,53 +12,28 @@ module Exceptional
|
|
12
12
|
"rails"
|
13
13
|
end
|
14
14
|
|
15
|
-
def extra_stuff
|
15
|
+
def extra_stuff
|
16
16
|
return {} if @request.nil?
|
17
17
|
{
|
18
18
|
'request' => {
|
19
|
-
'url' => "#{@request.protocol}#{@request.host}#{@request.request_uri}",
|
19
|
+
'url' => (@request.respond_to?(:url) ? @request.url : "#{@request.protocol}#{@request.host}#{@request.request_uri}"),
|
20
20
|
'controller' => @controller.class.to_s,
|
21
|
-
'action' => @request.parameters['action'],
|
22
|
-
'parameters' => filter_paramaters(@request.parameters),
|
21
|
+
'action' => (@request.respond_to?(:parameters) ? @request.parameters['action'] : @request.params['action']),
|
22
|
+
'parameters' => filter_paramaters(@request.respond_to?(:parameters) ? @request.parameters : @request.params),
|
23
23
|
'request_method' => @request.request_method.to_s,
|
24
|
-
'remote_ip' => @request.remote_ip,
|
24
|
+
'remote_ip' => (@request.respond_to?(:remote_ip) ? @request.remote_ip : @request.ip),
|
25
25
|
'headers' => extract_http_headers(@request.env),
|
26
26
|
'session' => self.class.sanitize_session(@request)
|
27
27
|
}
|
28
28
|
}
|
29
29
|
end
|
30
30
|
|
31
|
-
def filter_paramaters(hash)
|
31
|
+
def filter_paramaters(hash)
|
32
32
|
if @controller.respond_to?(:filter_parameters)
|
33
33
|
@controller.send(:filter_parameters, hash)
|
34
34
|
else
|
35
35
|
hash
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
def extract_http_headers(env)
|
40
|
-
headers = {}
|
41
|
-
env.select{|k, v| k =~ /^HTTP_/}.each do |name, value|
|
42
|
-
proper_name = name.sub(/^HTTP_/, '').split('_').map{|upper_case| upper_case.capitalize}.join('-')
|
43
|
-
headers[proper_name] = value
|
44
|
-
end
|
45
|
-
unless headers['Cookie'].nil?
|
46
|
-
headers['Cookie'] = headers['Cookie'].sub(/_session=\S+/, '_session=[FILTERED]')
|
47
|
-
end
|
48
|
-
headers
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.sanitize_session(request)
|
52
|
-
session = request.session
|
53
|
-
session_hash = {}
|
54
|
-
session_hash['session_id'] = request.session_options ? request.session_options[:id] : nil
|
55
|
-
session_hash['session_id'] ||= session.respond_to?(:session_id) ? session.session_id : session.instance_variable_get("@session_id")
|
56
|
-
session_hash['data'] = session.respond_to?(:to_hash) ? session.to_hash : session.instance_variable_get("@data") || {}
|
57
|
-
session_hash['session_id'] ||= session_hash['data'][:session_id]
|
58
|
-
session_hash['data'].delete(:session_id)
|
59
|
-
sanitize_hash(session_hash)
|
60
|
-
rescue
|
61
|
-
{}
|
62
|
-
end
|
63
38
|
end
|
64
39
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
|
3
3
|
module Exceptional
|
4
|
-
class ExceptionData
|
4
|
+
class ExceptionData
|
5
|
+
|
5
6
|
def initialize(exception, name=nil)
|
6
7
|
@exception = exception
|
7
8
|
@name = name
|
@@ -38,7 +39,9 @@ module Exceptional
|
|
38
39
|
begin
|
39
40
|
require 'json'
|
40
41
|
return to_hash.to_json
|
41
|
-
rescue StandardError
|
42
|
+
rescue StandardError => e
|
43
|
+
Exceptional.logger.error(e.message)
|
44
|
+
Exceptional.logger.error(e.backtrace)
|
42
45
|
raise StandardError.new("You need a json gem/library installed to send errors to Exceptional (Object.to_json not defined). \nInstall json_pure, yajl-ruby, json-jruby, or the c-based json gem")
|
43
46
|
end
|
44
47
|
end
|
@@ -67,5 +70,32 @@ module Exceptional
|
|
67
70
|
rescue
|
68
71
|
{}
|
69
72
|
end
|
73
|
+
|
74
|
+
def extract_http_headers(env)
|
75
|
+
headers = {}
|
76
|
+
env.select{|k, v| k =~ /^HTTP_/}.each do |name, value|
|
77
|
+
proper_name = name.sub(/^HTTP_/, '').split('_').map{|upper_case| upper_case.capitalize}.join('-')
|
78
|
+
headers[proper_name] = value
|
79
|
+
end
|
80
|
+
unless headers['Cookie'].nil?
|
81
|
+
headers['Cookie'] = headers['Cookie'].sub(/_session=\S+/, '_session=[FILTERED]')
|
82
|
+
end
|
83
|
+
headers
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.sanitize_session(request)
|
87
|
+
session_hash = {'session_id' => "", 'data' => {}}
|
88
|
+
|
89
|
+
if request.respond_to?(:session)
|
90
|
+
session = request.session
|
91
|
+
session_hash['session_id'] = request.session_options ? request.session_options[:id] : nil
|
92
|
+
session_hash['session_id'] ||= session.respond_to?(:session_id) ? session.session_id : session.instance_variable_get("@session_id")
|
93
|
+
session_hash['data'] = session.respond_to?(:to_hash) ? session.to_hash : session.instance_variable_get("@data") || {}
|
94
|
+
session_hash['session_id'] ||= session_hash['data'][:session_id]
|
95
|
+
session_hash['data'].delete(:session_id)
|
96
|
+
end
|
97
|
+
|
98
|
+
self.sanitize_hash(session_hash)
|
99
|
+
end
|
70
100
|
end
|
71
101
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class RailsExceptional
|
6
|
+
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
begin
|
13
|
+
status, headers, body = @app.call(env)
|
14
|
+
rescue Exception => e
|
15
|
+
puts ">>>#{env['action_controller.instance']}"
|
16
|
+
::Exceptional::Catcher.handle_with_controller(e,env['action_controller.instance'], Rack::Request.new(env))
|
17
|
+
raise
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,7 +3,7 @@ require 'digest/md5'
|
|
3
3
|
module Exceptional
|
4
4
|
class RackExceptionData < ExceptionData
|
5
5
|
def initialize(exception, environment, request)
|
6
|
-
super(exception)
|
6
|
+
super(exception)
|
7
7
|
@environment = environment
|
8
8
|
@request = request
|
9
9
|
end
|
@@ -16,12 +16,12 @@ module Exceptional
|
|
16
16
|
return {} if @request.nil?
|
17
17
|
{
|
18
18
|
'request' => {
|
19
|
-
'url' => "#{@request.url}",
|
19
|
+
'url' => "#{@request.url}",
|
20
20
|
'parameters' => @request.params,
|
21
21
|
'request_method' => @request.request_method.to_s,
|
22
22
|
'remote_ip' => @request.ip,
|
23
|
-
'headers' => @environment
|
24
|
-
'session' => @request
|
23
|
+
'headers' => extract_http_headers(@environment),
|
24
|
+
'session' => self.class.sanitize_session(@request)
|
25
25
|
}
|
26
26
|
}
|
27
27
|
end
|
data/lib/exceptional/version.rb
CHANGED
@@ -39,7 +39,7 @@ describe Exceptional::ControllerExceptionData, 'when no request/controller/param
|
|
39
39
|
error_hash['exception_class'].should == 'Exceptional::FunkyError'
|
40
40
|
error_hash['message'].should == 'some message'
|
41
41
|
error_hash['backtrace'].should == 'backtrace'
|
42
|
-
DateTime.parse(error_hash['occurred_at']).should ==
|
42
|
+
DateTime.parse(error_hash['occurred_at']).should == DateTime.now
|
43
43
|
client_hash = @hash['client']
|
44
44
|
client_hash['name'].should == Exceptional::CLIENT_NAME
|
45
45
|
client_hash['version'].should == Exceptional::VERSION
|
@@ -58,8 +58,8 @@ describe Exceptional::RackExceptionData do
|
|
58
58
|
request_hash['parameters'].should == {"cockle"=>"shell", "bay"=>"cool"}
|
59
59
|
request_hash['request_method'].should == 'GET'
|
60
60
|
request_hash['remote_ip'].should == '127.0.0.1'
|
61
|
-
request_hash['headers'].should == {"
|
62
|
-
request_hash['session'].should == {}
|
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
63
|
end
|
64
64
|
|
65
65
|
it "should capture client detais" do
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'rack/mock'
|
3
|
+
|
4
|
+
class ExceptionalTestError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Rack::RailsExceptional do
|
8
|
+
|
9
|
+
class TestingController < ActionController::Base
|
10
|
+
filter_parameter_logging :password, /credit_card/
|
11
|
+
|
12
|
+
def raises_something
|
13
|
+
raise StandardError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
@error = ExceptionalTestError.new
|
19
|
+
@app = lambda { |env| raise @error, 'Whoops!' }
|
20
|
+
@env = Rack::MockRequest.env_for("/foo")
|
21
|
+
@env['action_controller.instance'] = TestingController.new
|
22
|
+
end
|
23
|
+
|
24
|
+
it 're-raises errors caught in the middleware' do
|
25
|
+
rr = Rack::RailsExceptional.new(@app)
|
26
|
+
Exceptional::Catcher.should_receive(:handle_with_controller)
|
27
|
+
lambda { rr.call(@env)}.should raise_error(ExceptionalTestError)
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exceptional
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 17
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
- 15
|
10
|
+
version: 2.0.15
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Contrast
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-05-31 00:00:00 +01:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -29,6 +35,7 @@ files:
|
|
29
35
|
- lib/exceptional/exception_data.rb
|
30
36
|
- lib/exceptional/integration/dj.rb
|
31
37
|
- lib/exceptional/integration/rack.rb
|
38
|
+
- lib/exceptional/integration/rack_rails.rb
|
32
39
|
- lib/exceptional/integration/rails.rb
|
33
40
|
- lib/exceptional/integration/sinatra.rb
|
34
41
|
- lib/exceptional/integration/tester.rb
|
@@ -54,6 +61,7 @@ files:
|
|
54
61
|
- spec/ginger_scenarios.rb
|
55
62
|
- spec/rack_integration_spec.rb
|
56
63
|
- spec/rails_integration_spec.rb
|
64
|
+
- spec/rails_rack_integration_spec.rb
|
57
65
|
- spec/spec_helper.rb
|
58
66
|
- spec/standalone_spec.rb
|
59
67
|
- rails/init.rb
|
@@ -61,6 +69,7 @@ files:
|
|
61
69
|
- init.rb
|
62
70
|
- install.rb
|
63
71
|
- exceptional.gemspec
|
72
|
+
- bin/exceptional
|
64
73
|
has_rdoc: true
|
65
74
|
homepage: http://getexceptional.com/
|
66
75
|
licenses: []
|
@@ -71,21 +80,27 @@ rdoc_options: []
|
|
71
80
|
require_paths:
|
72
81
|
- lib
|
73
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
74
84
|
requirements:
|
75
85
|
- - ">="
|
76
86
|
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
77
90
|
version: "0"
|
78
|
-
version:
|
79
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
80
93
|
requirements:
|
81
94
|
- - ">="
|
82
95
|
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
83
99
|
version: "0"
|
84
|
-
version:
|
85
100
|
requirements:
|
86
101
|
- json_pure, json-jruby or json gem required
|
87
102
|
rubyforge_project: exceptional
|
88
|
-
rubygems_version: 1.3.
|
103
|
+
rubygems_version: 1.3.7
|
89
104
|
signing_key:
|
90
105
|
specification_version: 3
|
91
106
|
summary: getexceptional.com is a hosted service for tracking errors in your Ruby/Rails/Rack apps
|