tartarus 1.0.1 → 1.0.3
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/README.rdoc +11 -2
- data/VERSION +1 -1
- data/generators/tartarus/templates/app/views/exceptions/_exception.html.erb +1 -1
- data/generators/tartarus/templates/config/exceptions.yml +10 -1
- data/generators/tartarus/templates/db/migrate/add_logged_exceptions.rb +1 -0
- data/lib/tartarus/logger.rb +15 -23
- data/lib/tartarus/notifier.rb +11 -0
- data/lib/tartarus/rescue.rb +22 -0
- data/lib/tartarus.rb +1 -0
- data/spec/tartarus/logger_spec.rb +34 -21
- data/spec/tartarus/rescue_spec.rb +30 -0
- data/tartarus.gemspec +7 -6
- data/views/tartarus_notifier/notification.html.erb +9 -0
- metadata +51 -21
data/README.rdoc
CHANGED
@@ -17,8 +17,8 @@ dependencies are used:
|
|
17
17
|
=== Installation
|
18
18
|
|
19
19
|
1. Install the gem from:
|
20
|
-
|
21
|
-
2. Add the
|
20
|
+
gem install tartarus
|
21
|
+
2. Add the tartarus gem dependency to your enviroment.rb:
|
22
22
|
config.gem "tartarus"
|
23
23
|
3. Run the generator from the root of your Rails application:
|
24
24
|
script/generate tartarus
|
@@ -28,6 +28,15 @@ dependencies are used:
|
|
28
28
|
<script type="text/javascript" src="/javascripts/tartarus.jquery.js"></script>
|
29
29
|
<link href="/stylesheets/tartarus.css" media="all" rel="stylesheet" type="text/css" />
|
30
30
|
|
31
|
+
=== Configuration
|
32
|
+
|
33
|
+
Configuration is handled by config/exceptions.yml, which will be generated for you. You typically
|
34
|
+
will not need to change anything in here, however you can use this to set an email address to
|
35
|
+
have exception notifications delivered to, and a threshold. The threshold indicates how frequently
|
36
|
+
to send the notification, and is handled per-exception grouping (you will be notified every time the
|
37
|
+
threshold is reached, so with the default of 10 you will be notified at 10,20,30,etc.). In addition,
|
38
|
+
when an email is set, a notification will always be sent everytime a new type of exception is raised.
|
39
|
+
|
31
40
|
=== License
|
32
41
|
|
33
42
|
Copyright (c) 2009 Daniel Insley
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<td>
|
3
3
|
<strong><%= link_to "#{exception.exception_class}", :action => 'details', :id => exception.group_id %></strong>
|
4
4
|
<br />
|
5
|
-
<span><%= truncate(exception.message, :length => 115) %></span>
|
5
|
+
<span><%= truncate(h(exception.message), :length => 115) %></span>
|
6
6
|
</td>
|
7
7
|
|
8
8
|
<td>
|
@@ -1,9 +1,18 @@
|
|
1
1
|
development:
|
2
2
|
logging_enabled: true
|
3
3
|
logger_class: <%= class_name %>
|
4
|
+
notification_address:
|
5
|
+
notification_sender: noreply@example.com
|
6
|
+
notification_threshold: 10
|
4
7
|
test:
|
5
8
|
logging_enabled: false
|
6
9
|
logger_class: <%= class_name %>
|
10
|
+
notification_address:
|
11
|
+
notification_sender: noreply@example.com
|
12
|
+
notification_threshold: 10
|
7
13
|
production:
|
8
14
|
logging_enabled: true
|
9
|
-
logger_class: <%= class_name %>
|
15
|
+
logger_class: <%= class_name %>
|
16
|
+
notification_address:
|
17
|
+
notification_sender: noreply@example.com
|
18
|
+
notification_threshold: 10
|
data/lib/tartarus/logger.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Tartarus::Logger
|
2
|
+
def group_count
|
3
|
+
self.class.count( :conditions => ["group_id = ?", group_id] )
|
4
|
+
end
|
5
|
+
|
6
|
+
def handle_notifications
|
7
|
+
notification_address = Tartarus.configuration['notification_address']
|
8
|
+
return unless notification_address.present?
|
9
|
+
Tartarus::Notifier.deliver_notification( notification_address, self ) if group_count == 1 or (group_count%Tartarus.configuration['notification_threshold']).zero?
|
10
|
+
end
|
11
|
+
|
2
12
|
def self.included(base)
|
3
13
|
base.extend ClassMethods
|
4
14
|
base.serialize :request
|
@@ -6,38 +16,20 @@ module Tartarus::Logger
|
|
6
16
|
|
7
17
|
module ClassMethods
|
8
18
|
def log(controller, exception)
|
9
|
-
create do |logged_exception|
|
10
|
-
group_id = "#{exception.class.name}#{exception.message}#{controller.controller_path}#{controller.action_name}"
|
19
|
+
logged = create do |logged_exception|
|
20
|
+
group_id = "#{exception.class.name}#{exception.message.gsub(/(#<.+):(.+)(>)/,'\1\3')}#{controller.controller_path}#{controller.action_name}"
|
11
21
|
|
12
22
|
logged_exception.exception_class = exception.class.name
|
13
23
|
logged_exception.controller_path = controller.controller_path
|
14
24
|
logged_exception.action_name = controller.action_name
|
15
25
|
logged_exception.message = exception.message
|
16
26
|
logged_exception.backtrace = exception.backtrace * "\n"
|
17
|
-
logged_exception.request =
|
27
|
+
logged_exception.request = controller.normalize_request_data_for_tartarus
|
18
28
|
logged_exception.group_id = Digest::SHA1.hexdigest(group_id)
|
19
29
|
end
|
30
|
+
logged.handle_notifications
|
31
|
+
logged
|
20
32
|
end
|
21
33
|
|
22
|
-
def normalize_request_data(request)
|
23
|
-
enviroment = request.env.dup
|
24
|
-
|
25
|
-
request_details = {
|
26
|
-
:enviroment => { :process => $$, :server => `hostname -s`.chomp },
|
27
|
-
:session => { :variables => enviroment['rack.session'].to_hash, :cookie => enviroment['rack.request.cookie_hash'] },
|
28
|
-
:http_details => {
|
29
|
-
:method => request.method.to_s.upcase,
|
30
|
-
:url => "#{request.protocol}#{request.env["HTTP_HOST"]}#{request.request_uri}",
|
31
|
-
:format => request.format.to_s,
|
32
|
-
:parameters => request.parameters
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
enviroment.each_pair do |key, value|
|
37
|
-
request_details[:enviroment][key.downcase] = value if key.match(/^[A-Z_]*$/)
|
38
|
-
end
|
39
|
-
|
40
|
-
return request_details
|
41
|
-
end
|
42
34
|
end
|
43
35
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Tartarus::Notifier < ActionMailer::Base
|
2
|
+
self.mailer_name = 'tartarus_notifier'
|
3
|
+
self.view_paths << "#{File.dirname(__FILE__)}/../../views"
|
4
|
+
|
5
|
+
def notification( to, exception )
|
6
|
+
@recipients = to
|
7
|
+
@from = Tartarus.configuration['sender']
|
8
|
+
@subject = "Exception raised at #{exception.controller_path}##{exception.action_name} (#{exception.exception_class}) #{exception.message}"
|
9
|
+
@body[:exception] = exception
|
10
|
+
end
|
11
|
+
end
|
data/lib/tartarus/rescue.rb
CHANGED
@@ -14,4 +14,26 @@ module Tartarus::Rescue
|
|
14
14
|
|
15
15
|
rescue_action_without_tartarus(exception)
|
16
16
|
end
|
17
|
+
|
18
|
+
def normalize_request_data_for_tartarus
|
19
|
+
enviroment = request.env.dup
|
20
|
+
filtered_params = respond_to?(:filter_parameters) ? filter_parameters(request.parameters) : request.parameters.dup
|
21
|
+
|
22
|
+
request_details = {
|
23
|
+
:enviroment => { :process => $$, :server => `hostname -s`.chomp },
|
24
|
+
:session => { :variables => enviroment['rack.session'].to_hash, :cookie => enviroment['rack.request.cookie_hash'] },
|
25
|
+
:http_details => {
|
26
|
+
:method => request.method.to_s.upcase,
|
27
|
+
:url => "#{request.protocol}#{request.env["HTTP_HOST"]}#{request.request_uri}",
|
28
|
+
:format => request.format.to_s,
|
29
|
+
:parameters => filtered_params
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
enviroment.each_pair do |key, value|
|
34
|
+
request_details[:enviroment][key.downcase] = value if key.match(/^[A-Z_]*$/)
|
35
|
+
end
|
36
|
+
|
37
|
+
return request_details
|
38
|
+
end
|
17
39
|
end
|
data/lib/tartarus.rb
CHANGED
@@ -8,7 +8,7 @@ describe Tartarus::Logger do
|
|
8
8
|
describe "#log" do
|
9
9
|
before(:each) do
|
10
10
|
LoggedException.stub!(:normalize_request_data).and_return({})
|
11
|
-
@controller = mock('controller', :controller_path => 'home', :action_name => 'index', :request => fake_controller_request)
|
11
|
+
@controller = mock('controller', :controller_path => 'home', :normalize_request_data_for_tartarus => 'params', :action_name => 'index', :request => fake_controller_request)
|
12
12
|
@exception = StandardError.new('An error has occured!')
|
13
13
|
@exception.stub!(:backtrace).and_return(['one', 'two', 'three'])
|
14
14
|
end
|
@@ -25,7 +25,7 @@ describe Tartarus::Logger do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should normalize the controller request data" do
|
28
|
-
|
28
|
+
@controller.should_receive(:normalize_request_data_for_tartarus)
|
29
29
|
@logged_exception = LoggedException.log(@controller, @exception)
|
30
30
|
end
|
31
31
|
|
@@ -34,31 +34,44 @@ describe Tartarus::Logger do
|
|
34
34
|
@logged_exception.should be_an_instance_of(LoggedException)
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
|
38
|
+
it 'should return the group count' do
|
39
|
+
e = LoggedException.create( :group_id => "hash" )
|
40
|
+
LoggedException.should_receive( :count ).with( :conditions => ["group_id = ?", 'hash'] ).and_return( 42 )
|
41
|
+
e.group_count.should == 42
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#handle_notifications' do
|
45
|
+
before(:each) do
|
46
|
+
@e = LoggedException.create
|
47
|
+
Tartarus.configuration['notification_threshold'] = 10
|
48
|
+
Tartarus.configuration['notification_address'] = 'test@example.com'
|
41
49
|
end
|
42
50
|
|
43
|
-
it 'should
|
44
|
-
|
45
|
-
|
46
|
-
end
|
51
|
+
it 'should return and not deliver notification if there is no address present' do
|
52
|
+
Tartarus::Notifier.should_receive( :deliver_notification ).never
|
53
|
+
Tartarus.configuration['notification_address'] = nil
|
47
54
|
|
48
|
-
|
49
|
-
@request_data[:session].should_not be_blank
|
50
|
-
@request_data[:session].should be_an_instance_of(Hash)
|
51
|
-
@request_data[:session].should == { :cookie => {}, :variables => { :id=>"123123" } }
|
55
|
+
@e.handle_notifications
|
52
56
|
end
|
53
57
|
|
54
|
-
it 'should
|
55
|
-
|
56
|
-
@
|
58
|
+
it 'should send email if there is an address present and the count matches the threshold' do
|
59
|
+
Tartarus::Notifier.should_receive( :deliver_notification ).with( 'test@example.com', @e )
|
60
|
+
@e.stub( :group_count ).and_return( 20 )
|
61
|
+
@e.handle_notifications
|
57
62
|
end
|
58
|
-
|
59
|
-
it
|
60
|
-
@
|
63
|
+
|
64
|
+
it 'should send email if there is an address present and it is the first exception in a group' do
|
65
|
+
Tartarus::Notifier.should_receive( :deliver_notification ).with( 'test@example.com', @e )
|
66
|
+
@e.stub( :group_count ).and_return( 1 )
|
67
|
+
@e.handle_notifications
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should not send email if there is an address present and the count does not match the threshold' do
|
71
|
+
Tartarus::Notifier.should_receive( :deliver_notification ).never
|
72
|
+
@e.stub( :group_count ).and_return( 22 )
|
73
|
+
@e.handle_notifications
|
61
74
|
end
|
62
|
-
|
63
75
|
end
|
76
|
+
|
64
77
|
end
|
@@ -15,6 +15,36 @@ describe Tartarus::Rescue do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
describe 'when normalizing request data for tartarus' do
|
19
|
+
before( :each ) do
|
20
|
+
@controller.stub( :request ).and_return( fake_controller_request )
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have the session hash' do
|
24
|
+
params = @controller.normalize_request_data_for_tartarus
|
25
|
+
params[:session].should_not be_blank
|
26
|
+
params[:session].should be_an_instance_of(Hash)
|
27
|
+
params[:session].should == { :cookie => {}, :variables => { :id=>"123123" } }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should have a enviroment hash that contains a hash of only the uppercase keys of the original controller request hash' do
|
31
|
+
params = @controller.normalize_request_data_for_tartarus
|
32
|
+
params[:enviroment].should_not be_blank
|
33
|
+
params[:enviroment].should == { "http_host" => "test_host", "loooooooong_key_two" => "key_two_value", "key_one" => "key_one_value", :server => `hostname -s`.chomp, :process => $$ }
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should have a http details hash' do
|
37
|
+
params = @controller.normalize_request_data_for_tartarus
|
38
|
+
params[:http_details].should_not be_blank
|
39
|
+
params[:http_details].should == { :parameters => "params", :format => "html", :method => "POST", :url => "http://test_host/my/uri" }
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return a hash of request data" do
|
43
|
+
params = @controller.normalize_request_data_for_tartarus
|
44
|
+
params.should be_an_instance_of(Hash)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
18
48
|
describe "#rescue_action_with_tartarus" do
|
19
49
|
before(:each) do
|
20
50
|
@exception = StandardError.new
|
data/tartarus.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{tartarus}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Daniel Insley"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-10-27}
|
13
13
|
s.description = %q{Provides exception logging and a generator for creating a clean interface to manage exceptions.}
|
14
14
|
s.email = %q{dinsley@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
"generators/tartarus/templates/spec/models/logged_exception_spec.rb",
|
37
37
|
"lib/tartarus.rb",
|
38
38
|
"lib/tartarus/logger.rb",
|
39
|
+
"lib/tartarus/notifier.rb",
|
39
40
|
"lib/tartarus/rescue.rb",
|
40
41
|
"rails/init.rb",
|
41
42
|
"spec/rails/app/controllers/application_controller.rb",
|
@@ -61,7 +62,8 @@ Gem::Specification.new do |s|
|
|
61
62
|
"spec/tartarus/logger_spec.rb",
|
62
63
|
"spec/tartarus/rescue_spec.rb",
|
63
64
|
"spec/tartarus_spec.rb",
|
64
|
-
"tartarus.gemspec"
|
65
|
+
"tartarus.gemspec",
|
66
|
+
"views/tartarus_notifier/notification.html.erb"
|
65
67
|
]
|
66
68
|
s.homepage = %q{http://github.com/dinsley/tartarus}
|
67
69
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -110,4 +112,3 @@ Gem::Specification.new do |s|
|
|
110
112
|
s.add_dependency(%q<rspec-rails>, [">= 0"])
|
111
113
|
end
|
112
114
|
end
|
113
|
-
|
@@ -0,0 +1,9 @@
|
|
1
|
+
A new exception was raised (<%= @exception.created_at.strftime("%m/%d/%Y %I:%M%p") %>):
|
2
|
+
|
3
|
+
Class : <%= @exception.exception_class %>
|
4
|
+
Location : <%= @exception.controller_path %>#<%= @exception.action_name %>
|
5
|
+
Message : <%= @exception.message %>
|
6
|
+
Count : <%= @exception.group_count %>
|
7
|
+
|
8
|
+
Backtrace:
|
9
|
+
<%= @exception.backtrace %>
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tartarus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 17
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 3
|
10
|
+
version: 1.0.3
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Daniel Insley
|
@@ -9,49 +15,65 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
18
|
+
date: 2010-10-27 00:00:00 -07:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: will_paginate
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
23
32
|
version: "0"
|
24
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
25
35
|
- !ruby/object:Gem::Dependency
|
26
36
|
name: rails
|
27
|
-
|
28
|
-
|
29
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
30
40
|
requirements:
|
31
41
|
- - ">="
|
32
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
33
46
|
version: "0"
|
34
|
-
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
35
49
|
- !ruby/object:Gem::Dependency
|
36
50
|
name: rspec
|
37
|
-
|
38
|
-
|
39
|
-
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
40
54
|
requirements:
|
41
55
|
- - ">="
|
42
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
43
60
|
version: "0"
|
44
|
-
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
45
63
|
- !ruby/object:Gem::Dependency
|
46
64
|
name: rspec-rails
|
47
|
-
|
48
|
-
|
49
|
-
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
50
68
|
requirements:
|
51
69
|
- - ">="
|
52
70
|
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
53
74
|
version: "0"
|
54
|
-
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
55
77
|
description: Provides exception logging and a generator for creating a clean interface to manage exceptions.
|
56
78
|
email: dinsley@gmail.com
|
57
79
|
executables: []
|
@@ -81,6 +103,7 @@ files:
|
|
81
103
|
- generators/tartarus/templates/spec/models/logged_exception_spec.rb
|
82
104
|
- lib/tartarus.rb
|
83
105
|
- lib/tartarus/logger.rb
|
106
|
+
- lib/tartarus/notifier.rb
|
84
107
|
- lib/tartarus/rescue.rb
|
85
108
|
- rails/init.rb
|
86
109
|
- spec/rails/app/controllers/application_controller.rb
|
@@ -107,6 +130,7 @@ files:
|
|
107
130
|
- spec/tartarus/rescue_spec.rb
|
108
131
|
- spec/tartarus_spec.rb
|
109
132
|
- tartarus.gemspec
|
133
|
+
- views/tartarus_notifier/notification.html.erb
|
110
134
|
has_rdoc: true
|
111
135
|
homepage: http://github.com/dinsley/tartarus
|
112
136
|
licenses: []
|
@@ -117,21 +141,27 @@ rdoc_options:
|
|
117
141
|
require_paths:
|
118
142
|
- lib
|
119
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
120
145
|
requirements:
|
121
146
|
- - ">="
|
122
147
|
- !ruby/object:Gem::Version
|
148
|
+
hash: 3
|
149
|
+
segments:
|
150
|
+
- 0
|
123
151
|
version: "0"
|
124
|
-
version:
|
125
152
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
126
154
|
requirements:
|
127
155
|
- - ">="
|
128
156
|
- !ruby/object:Gem::Version
|
157
|
+
hash: 3
|
158
|
+
segments:
|
159
|
+
- 0
|
129
160
|
version: "0"
|
130
|
-
version:
|
131
161
|
requirements: []
|
132
162
|
|
133
163
|
rubyforge_project:
|
134
|
-
rubygems_version: 1.3.
|
164
|
+
rubygems_version: 1.3.7
|
135
165
|
signing_key:
|
136
166
|
specification_version: 3
|
137
167
|
summary: Exception Logging for Rails
|