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 CHANGED
@@ -17,8 +17,8 @@ dependencies are used:
17
17
  === Installation
18
18
 
19
19
  1. Install the gem from:
20
- [sudo] gem install tartarus --source=http://gemcutter.org
21
- 2. Add the exceptional gem dependency to your enviroment.rb:
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
+ 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
@@ -10,6 +10,7 @@ class Add<%= class_name %>Table < ActiveRecord::Migration
10
10
  t.text :request
11
11
  t.datetime :created_at
12
12
  end
13
+ add_index :<%= plural_name %>, :group_id
13
14
  end
14
15
 
15
16
  def self.down
@@ -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 = normalize_request_data(controller.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
@@ -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
@@ -23,3 +23,4 @@ end
23
23
 
24
24
  require 'tartarus/logger'
25
25
  require 'tartarus/rescue'
26
+ require 'tartarus/notifier'
@@ -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
- LoggedException.should_receive(:normalize_request_data).with(@controller.request)
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
- describe "#normalize_request_data" do
39
- before(:each) do
40
- @request_data = LoggedException.normalize_request_data(fake_controller_request)
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 have a enviroment hash that contains a hash of only the uppercase keys of the original controller request hash' do
44
- @request_data[:enviroment].should_not be_blank
45
- @request_data[:enviroment].should == { "http_host" => "test_host", "loooooooong_key_two" => "key_two_value", "key_one" => "key_one_value", :server => `hostname -s`.chomp, :process => $$ }
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
- it 'should have a session hash' do
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 have a http details hash' do
55
- @request_data[:http_details].should_not be_blank
56
- @request_data[:http_details].should == { :parameters => "params", :format => "html", :method => "POST", :url => "http://test_host/my/uri" }
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 "should return a hash of request data" do
60
- @request_data.should be_an_instance_of(Hash)
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 DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
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.1"
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{2009-11-24}
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
- version: 1.0.1
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: 2009-11-24 00:00:00 -08:00
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
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: rails
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
47
+ type: :development
48
+ version_requirements: *id002
35
49
  - !ruby/object:Gem::Dependency
36
50
  name: rspec
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
61
+ type: :development
62
+ version_requirements: *id003
45
63
  - !ruby/object:Gem::Dependency
46
64
  name: rspec-rails
47
- type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
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.5
164
+ rubygems_version: 1.3.7
135
165
  signing_key:
136
166
  specification_version: 3
137
167
  summary: Exception Logging for Rails