exceptional 2.0.14 → 2.0.15
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/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
|