tartarus 1.0.0
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/.document +5 -0
- data/.gitignore +5 -0
- data/README.rdoc +54 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/generators/tartarus/USAGE +14 -0
- data/generators/tartarus/tartarus_generator.rb +51 -0
- data/generators/tartarus/templates/app/controllers/exceptions_controller.rb +31 -0
- data/generators/tartarus/templates/app/models/logged_exception.rb +3 -0
- data/generators/tartarus/templates/app/views/exceptions/_exception.html.erb +14 -0
- data/generators/tartarus/templates/app/views/exceptions/details.html.erb +86 -0
- data/generators/tartarus/templates/app/views/exceptions/index.html.erb +28 -0
- data/generators/tartarus/templates/config/exceptions.yml +9 -0
- data/generators/tartarus/templates/db/migrate/add_logged_exceptions.rb +18 -0
- data/generators/tartarus/templates/public/javascripts/tartarus.jquery.js +6 -0
- data/generators/tartarus/templates/public/stylesheets/tartarus.css +26 -0
- data/generators/tartarus/templates/spec/controllers/exceptions_controller_spec.rb +83 -0
- data/generators/tartarus/templates/spec/models/logged_exception_spec.rb +7 -0
- data/lib/tartarus/logger.rb +46 -0
- data/lib/tartarus/rescue.rb +15 -0
- data/lib/tartarus.rb +22 -0
- data/rails/init.rb +3 -0
- data/spec/rails/app/controllers/application_controller.rb +10 -0
- data/spec/rails/app/models/logged_exception.rb +2 -0
- data/spec/rails/config/boot.rb +110 -0
- data/spec/rails/config/database.yml +5 -0
- data/spec/rails/config/environment.rb +41 -0
- data/spec/rails/config/environments/development.rb +17 -0
- data/spec/rails/config/environments/production.rb +28 -0
- data/spec/rails/config/environments/test.rb +28 -0
- data/spec/rails/config/exceptions.yml +9 -0
- data/spec/rails/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails/config/initializers/inflections.rb +10 -0
- data/spec/rails/config/initializers/mime_types.rb +5 -0
- data/spec/rails/config/initializers/new_rails_defaults.rb +21 -0
- data/spec/rails/config/initializers/session_store.rb +15 -0
- data/spec/rails/config/locales/en.yml +5 -0
- data/spec/rails/config/routes.rb +43 -0
- data/spec/rails/db/test.sqlite3 +0 -0
- data/spec/rcov.opts +3 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/tartarus/logger_spec.rb +63 -0
- data/spec/tartarus/rescue_spec.rb +43 -0
- data/spec/tartarus_spec.rb +53 -0
- metadata +154 -0
data/.document
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Tartarus
|
2
|
+
|
3
|
+
It is a deep, gloomy place, a pit, or an abyss used as a dungeon of torment and suffering..
|
4
|
+
|
5
|
+
Tartarus provides logging to your database for exceptions triggered by the users of
|
6
|
+
your Rails application. A generator is included that will give you a clean interface
|
7
|
+
to view and manage the exceptions.
|
8
|
+
|
9
|
+
=== Dependencies
|
10
|
+
|
11
|
+
If you wish to use the generator to build the exception viewing/manging interface, the following
|
12
|
+
dependencies are used:
|
13
|
+
|
14
|
+
* will_paginate
|
15
|
+
* jquery
|
16
|
+
|
17
|
+
=== Installation
|
18
|
+
|
19
|
+
1. Install the gem:
|
20
|
+
[sudo] gem install tartarus
|
21
|
+
2. Add the exceptional gem dependency to your enviroment.rb:
|
22
|
+
config.gem "tartarus"
|
23
|
+
3. Run the generator from the root of your Rails application:
|
24
|
+
script/generate tartarus
|
25
|
+
4. Run the migration that was generated:
|
26
|
+
rake db:migrate
|
27
|
+
5. Add the javascript and stylesheet includes in your layout:
|
28
|
+
<script type="text/javascript" src="/javascripts/tartarus.jquery.js"></script>
|
29
|
+
<link href="/stylesheets/tartarus.css" media="all" rel="stylesheet" type="text/css" />
|
30
|
+
6. View the generated 'config/exceptions.yml' file and make sure the default options are correct.
|
31
|
+
|
32
|
+
=== License
|
33
|
+
|
34
|
+
Copyright (c) 2009 Daniel Insley
|
35
|
+
|
36
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
37
|
+
a copy of this software and associated documentation files (the
|
38
|
+
"Software"), to deal in the Software without restriction, including
|
39
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
40
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
41
|
+
permit persons to whom the Software is furnished to do so, subject to
|
42
|
+
the following conditions:
|
43
|
+
|
44
|
+
The above copyright notice and this permission notice shall be
|
45
|
+
included in all copies or substantial portions of the Software.
|
46
|
+
|
47
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
48
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
49
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
50
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
51
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
52
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
53
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
54
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "tartarus"
|
8
|
+
gem.summary = %Q{Exception Logging for Rails}
|
9
|
+
gem.description = %Q{Provides exception logging and a generator for creating a clean interface to manage exceptions.}
|
10
|
+
gem.email = "dinsley@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/dinsley/tartarus"
|
12
|
+
gem.authors = ["Daniel Insley"]
|
13
|
+
gem.add_dependency "will_paginate"
|
14
|
+
gem.add_development_dependency "rails"
|
15
|
+
gem.add_development_dependency "rspec"
|
16
|
+
gem.add_development_dependency "rspec-rails"
|
17
|
+
# Gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.spec_opts = ['--options', "spec/spec.opts"]
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
29
|
+
spec.rcov = true
|
30
|
+
spec.rcov_opts = lambda do
|
31
|
+
IO.readlines("spec/rcov.opts").map { |l| l.chomp.split " " }.flatten
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
task :spec => :check_dependencies
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
if File.exist?('VERSION')
|
41
|
+
version = File.read('VERSION')
|
42
|
+
else
|
43
|
+
version = ""
|
44
|
+
end
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "tartarus #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
Generates a model, controller and views for viewing and managing exceptions.
|
3
|
+
|
4
|
+
Usage:
|
5
|
+
If you do not pass any arguments, the model class will default to "LoggedException".
|
6
|
+
|
7
|
+
Examples:
|
8
|
+
script/generate tartarus
|
9
|
+
|
10
|
+
Creates default logged exception model, controller, and views.
|
11
|
+
|
12
|
+
script/generate tartarus MyException
|
13
|
+
|
14
|
+
Creates a custom model, controller, and views.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class TartarusGenerator < Rails::Generator::NamedBase
|
2
|
+
default_options :skip_migration => false
|
3
|
+
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
5
|
+
runtime_args << 'LoggedException' if runtime_args.empty?
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
record do |m|
|
11
|
+
puts "\nGenerated files:\n"
|
12
|
+
# Directories
|
13
|
+
m.directory "app/views/exceptions"
|
14
|
+
m.directory "spec/models"
|
15
|
+
m.directory "spec/controllers"
|
16
|
+
|
17
|
+
# Configuration
|
18
|
+
m.template 'config/exceptions.yml', 'config/exceptions.yml'
|
19
|
+
|
20
|
+
#Migration
|
21
|
+
m.migration_template "db/migrate/add_logged_exceptions.rb", "db/migrate", :migration_file_name => "add_#{singular_name}_table"
|
22
|
+
|
23
|
+
# Controllers
|
24
|
+
m.template 'app/controllers/exceptions_controller.rb', "app/controllers/exceptions_controller.rb"
|
25
|
+
|
26
|
+
# Views
|
27
|
+
Dir.glob( File.dirname(__FILE__) + '/templates/app/views/exceptions/*.html.erb').each do |path|
|
28
|
+
view = File.basename( path )
|
29
|
+
m.file "app/views/exceptions/#{view}", "app/views/exceptions/#{view}"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Models
|
33
|
+
m.template 'app/models/logged_exception.rb', "app/models/#{file_name}.rb"
|
34
|
+
|
35
|
+
# Specs
|
36
|
+
m.template 'spec/models/logged_exception_spec.rb', "spec/models/#{file_name}_spec.rb"
|
37
|
+
m.template 'spec/controllers/exceptions_controller_spec.rb', 'spec/controllers/exceptions_controller_spec.rb'
|
38
|
+
|
39
|
+
# Public
|
40
|
+
m.file 'public/javascripts/tartarus.jquery.js', 'public/javascripts/tartarus.jquery.js'
|
41
|
+
m.file 'public/stylesheets/tartarus.css', 'public/stylesheets/tartarus.css'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def after_generate
|
46
|
+
puts "\nIn order for exceptional to function properly, you'll need to complete the following steps to complete the installation process: \n\n"
|
47
|
+
puts " 1) Run 'rake db:migrate' to generate the logging table for your model.\n"
|
48
|
+
puts " 2) Add '/javascripts/tartarus.jquery.js', and 'stylesheets/tartarus.css' to your applications layout.\n"
|
49
|
+
puts " 3) View 'config/exceptions.yml' and make sure the default options are correct.\n\n"
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ExceptionsController < ApplicationController
|
2
|
+
def index
|
3
|
+
@exceptions = <%= class_name %>.all(:select => '*, COUNT(*) as count', :group => 'group_id', :order => 'created_at DESC')
|
4
|
+
end
|
5
|
+
|
6
|
+
def details
|
7
|
+
@exceptions = <%= class_name %>.paginate(:all, :conditions => { :group_id => params[:id] }, :order => 'created_at DESC', :page => params[:page], :per_page => 1)
|
8
|
+
@exception = @exceptions.first
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_all
|
12
|
+
<%= class_name %>.delete_all
|
13
|
+
redirect_to :action => :index
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove_group
|
17
|
+
<%= class_name %>.delete_all(:group_id => params[:id])
|
18
|
+
redirect_to :action => :index
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove_individual
|
22
|
+
exception = <%= class_name %>.find_by_id(params[:id])
|
23
|
+
exception.destroy
|
24
|
+
|
25
|
+
if <%= class_name %>.count(:conditions => { :group_id => exception.group_id }).zero?
|
26
|
+
redirect_to :action => :index
|
27
|
+
else
|
28
|
+
redirect_to :action => :details, :id => exception.group_id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<tr id="exception_<%= exception.group_id %>">
|
2
|
+
<td>
|
3
|
+
<strong><%= link_to "#{exception.exception_class}", :action => 'details', :id => exception.group_id %></strong>
|
4
|
+
<br />
|
5
|
+
<span><%= truncate(exception.message, :length => 115) %></span>
|
6
|
+
</td>
|
7
|
+
|
8
|
+
<td>
|
9
|
+
<%= "#{exception.controller_path}##{exception.action_name}" %>
|
10
|
+
</td>
|
11
|
+
|
12
|
+
<td><%= exception.created_at.strftime("%m/%d/%Y %I:%M%p") %></td>
|
13
|
+
<td style="text-align: center;"><%= exception.count %></td>
|
14
|
+
</tr>
|
@@ -0,0 +1,86 @@
|
|
1
|
+
<div id="tartarus">
|
2
|
+
<div id="exception_group_details">
|
3
|
+
<div id="tartarus_cap">
|
4
|
+
<div id="tartarus_nav">
|
5
|
+
<%= link_to 'Return to overview', :controller => 'exceptions', :action => 'index' %>
|
6
|
+
<%= will_paginate @exceptions, :page_links => false, :class => 'tartarus_pagination' %>
|
7
|
+
</div>
|
8
|
+
<h2><%= @exception.exception_class %> in "<%= "#{@exception.controller_path}##{@exception.action_name}" %>"</h2>
|
9
|
+
<div>Viewing Exception <%= params[:page] || 1 %> of <%= @exceptions.total_pages %></div>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<h3><%= @exception.created_at.strftime("%B %e %Y at %I:%M:%S%p") %></h3>
|
14
|
+
<pre><%= @exception.message %></pre>
|
15
|
+
|
16
|
+
<div id="exception_actions">
|
17
|
+
<%= link_to 'Remove all', :action => 'remove_group', :id => @exception.group_id %>
|
18
|
+
·
|
19
|
+
<%= link_to 'Remove', :action => 'remove_individual', :id => @exception.id %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div id="exception">
|
23
|
+
<div id="request_information" class="togglable">
|
24
|
+
<h3><a class="toggle_link" href="javascript:void(0);">Request</a></h3>
|
25
|
+
<ul class="toggle_data">
|
26
|
+
<% @exception.request[:http_details].each_pair do |key, value| %>
|
27
|
+
<% unless value.blank? %>
|
28
|
+
<li><strong><%= key %></strong> :
|
29
|
+
<% if value.is_a?(Hash) %>
|
30
|
+
<ul>
|
31
|
+
<% value.each_pair do |key, value| %>
|
32
|
+
<% unless value.blank? %>
|
33
|
+
<li><strong><%= key %></strong> : <%= value %></li>
|
34
|
+
<% end %>
|
35
|
+
<% end%>
|
36
|
+
</ul>
|
37
|
+
<% else %>
|
38
|
+
<%= value %>
|
39
|
+
<% end %>
|
40
|
+
</li>
|
41
|
+
<% end %>
|
42
|
+
<% end %>
|
43
|
+
</ul>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="backtrace_information" class="togglable">
|
47
|
+
<h3><a class="toggle_link" href="javascript:void(0);">Backtrace</a></h3>
|
48
|
+
<pre class="toggle_data"><%= h(@exception.backtrace) %></pre>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div id="session_information" class="togglable">
|
52
|
+
<h3><a class="toggle_link" href="javascript:void(0);">Session & Cookies</a></h3>
|
53
|
+
<ul class="toggle_data">
|
54
|
+
<% @exception.request[:session].each_pair do |key, value| %>
|
55
|
+
<% unless value.blank? %>
|
56
|
+
<li><strong><%= key %></strong> :
|
57
|
+
<% if value.is_a?(Hash) %>
|
58
|
+
<ul>
|
59
|
+
<% value.each_pair do |key, value| %>
|
60
|
+
<% unless value.blank? %>
|
61
|
+
<li><strong><%= key %></strong> : <%= value %></li>
|
62
|
+
<% end %>
|
63
|
+
<% end %>
|
64
|
+
</ul>
|
65
|
+
<% else %>
|
66
|
+
<%= value %>
|
67
|
+
<% end %>
|
68
|
+
</li>
|
69
|
+
<% end %>
|
70
|
+
<% end %>
|
71
|
+
</ul>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<div id="enviroment_information" class="togglable">
|
75
|
+
<h3><a class="toggle_link" href="javascript:void(0);">Enviroment</a></h3>
|
76
|
+
<ul class="toggle_data">
|
77
|
+
<% @exception.request[:enviroment].each_pair do |key, value| %>
|
78
|
+
<% unless value.blank? %>
|
79
|
+
<li><strong><%= key%></strong> : <%= value %></li>
|
80
|
+
<% end %>
|
81
|
+
<% end %>
|
82
|
+
</ul>
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
</div>
|
86
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<div id="tartarus">
|
2
|
+
<div id="tartarus_cap">
|
3
|
+
<div id="tartarus_nav">
|
4
|
+
<%= link_to 'Remove all', :action => :remove_all %>
|
5
|
+
</div>
|
6
|
+
<h2>Exception Overview</h2>
|
7
|
+
<div><%= @exceptions.length %> Exceptions</div>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<table id="tartarus_overview">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th id="exception_summary">Summary</th>
|
14
|
+
<th id="exception_location">Location</th>
|
15
|
+
<th id="exception_date">Latest</th>
|
16
|
+
<th id="exception_count">Count</th>
|
17
|
+
</tr>
|
18
|
+
</thead>
|
19
|
+
|
20
|
+
<tbody>
|
21
|
+
<% @exceptions.each do |exception| %>
|
22
|
+
<%= render :partial => 'exception', :object => exception %>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
|
26
|
+
</table>
|
27
|
+
</div>
|
28
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Add<%= class_name %>Table < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :<%= plural_name %>, :force => true do |t|
|
4
|
+
t.string :group_id
|
5
|
+
t.string :exception_class
|
6
|
+
t.string :controller_path
|
7
|
+
t.string :action_name
|
8
|
+
t.text :message
|
9
|
+
t.text :backtrace
|
10
|
+
t.text :request
|
11
|
+
t.datetime :created_at
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :<%= plural_name %>
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#tartarus { margin: 0px 20px }
|
2
|
+
|
3
|
+
#tartarus_cap { padding-bottom: 10px; border-bottom: 1px solid #777; margin: 20px 0px; }
|
4
|
+
#tartarus h2 { margin: 10px 0px; }
|
5
|
+
|
6
|
+
#tartarus_nav { float: right }
|
7
|
+
.tartarus_pagination { margin-top: 20px; }
|
8
|
+
|
9
|
+
#tartarus table { border-collapse: collapse; width: 100%; }
|
10
|
+
#tartarus table tr { border-bottom: 1px solid #E0DFE0; }
|
11
|
+
#tartarus table th, #tartarus table td { padding: 5px; }
|
12
|
+
#tartarus table th { text-align: left; }
|
13
|
+
|
14
|
+
#tartarus th#exception_location { width: 150px; }
|
15
|
+
#tartarus th#exception_date { width: 150px; }
|
16
|
+
#tartarus th#exception_count { text-align: center; }
|
17
|
+
|
18
|
+
#tartarus pre { -webkit-border-radius: 5px; -moz-border-radius: 5px; font-size: 10px; color: #fff; background-color: #222; padding: 10px; font-family: Consolas, Monaco, 'Courier New', Courier,monospace; }
|
19
|
+
#tartarus a, #tartarus a:visited { text-decoration: underline; #bdf; }
|
20
|
+
#tartarus a:hover { #09f }
|
21
|
+
|
22
|
+
#tartarus #exception { clear: both; }
|
23
|
+
#tartarus #exception_actions { float: right; }
|
24
|
+
|
25
|
+
.toggle_data { display: none }
|
26
|
+
#backtrace_information .toggle_data { display: block; }
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe ExceptionsController do
|
4
|
+
before(:each) do
|
5
|
+
@exception = <%= class_name %>.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#index" do
|
9
|
+
it 'should set an assigns of exceptions with the collection of all exception groups' do
|
10
|
+
<%= class_name %>.should_receive(:all).with(:select => '*, COUNT(*) as count', :group => 'group_id', :order => 'created_at DESC').and_return([@exception])
|
11
|
+
|
12
|
+
get :index
|
13
|
+
assigns[:exceptions].should == [@exception]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#details" do
|
18
|
+
before(:each) do
|
19
|
+
@exception2 = <%= class_name %>.new
|
20
|
+
<%= class_name %>.stub!(:paginate).and_return([@exception, @exception2])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should set an assigns of exceptions with a paginated collection' do
|
24
|
+
<%= class_name %>.should_receive(:paginate).with(:all, :conditions => { :group_id => '89hasd98ashdasas98dhsda' },
|
25
|
+
:order => 'created_at DESC', :page => '1', :per_page => 1).and_return([@exception, @exception2])
|
26
|
+
|
27
|
+
get :details, :id => '89hasd98ashdasas98dhsda', :page => 1
|
28
|
+
assigns[:exceptions].should == [@exception, @exception2]
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set an assigns of exception with the first exception from the paginated collection' do
|
32
|
+
get :details, :id => '89hasd98ashdasas98dhsda'
|
33
|
+
assigns[:exception].should == @exception
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#remove_all" do
|
38
|
+
it 'should delete all exceptions' do
|
39
|
+
<%= class_name %>.should_receive(:delete_all)
|
40
|
+
get :remove_all
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should redirect to exceptions#index' do
|
44
|
+
get :remove_all
|
45
|
+
response.should redirect_to(:action => :index)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#remove_group" do
|
50
|
+
it 'should delete all exceptions in a specific group' do
|
51
|
+
<%= class_name %>.should_receive(:delete_all).with(:group_id => '892h39fds')
|
52
|
+
get :remove_group, :id => '892h39fds'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should redirect to exceptions#index' do
|
56
|
+
get :remove_group, :id => '892h39fds'
|
57
|
+
response.should redirect_to(:action => :index)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#remove_individual" do
|
62
|
+
before(:each) do
|
63
|
+
<%= class_name %>.stub!(:find_by_id).and_return(@exception)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should remove a single exception' do
|
67
|
+
@exception.should_receive(:destroy)
|
68
|
+
get :remove_individual, :id => 1
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should redirect to exceptions#index if the exception group contains no more exceptions' do
|
72
|
+
<%= class_name %>.stub!(:count).and_return(0)
|
73
|
+
get :remove_individual, :id => 1
|
74
|
+
response.should redirect_to(:action => :index)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should redirect to exceptions#details if the exception group contains more exceptions' do
|
78
|
+
<%= class_name %>.stub!(:count).and_return(1)
|
79
|
+
get :remove_individual, :id => 1
|
80
|
+
response.should redirect_to(:action => :details)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Tartarus::Logger
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.serialize :request
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def log(controller, exception)
|
9
|
+
create do |logged_exception|
|
10
|
+
group_id = "#{exception.class.name}#{exception.message}#{controller.controller_path}#{controller.action_name}"
|
11
|
+
|
12
|
+
logged_exception.exception_class = exception.class.name
|
13
|
+
logged_exception.controller_path = controller.controller_path
|
14
|
+
logged_exception.action_name = controller.action_name
|
15
|
+
logged_exception.message = exception.message
|
16
|
+
logged_exception.backtrace = exception.backtrace * "\n"
|
17
|
+
logged_exception.request = normalize_request_data(controller.request)
|
18
|
+
logged_exception.group_id = Digest::SHA1.hexdigest(group_id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def normalize_request_data(request)
|
23
|
+
request_details = {
|
24
|
+
:enviroment => {},
|
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 => request.parameters
|
30
|
+
},
|
31
|
+
|
32
|
+
:session => {
|
33
|
+
:variables => request.env['rack.session'],
|
34
|
+
:options => request.env['rack.session.options'],
|
35
|
+
:cookie => request.env['rack.request.cookie_hash']
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
request.env.each_pair do |key, value|
|
40
|
+
request_details[:enviroment][key.downcase] = value if key.match(/^[A-Z_]*$/)
|
41
|
+
end
|
42
|
+
|
43
|
+
return request_details
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Tartarus::Rescue
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
alias_method_chain :rescue_action, :tartarus
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def rescue_action_with_tartarus(exception)
|
9
|
+
if response_code_for_rescue(exception) == :internal_server_error
|
10
|
+
Tartarus.log(self, exception)
|
11
|
+
end
|
12
|
+
|
13
|
+
rescue_action_without_tartarus(exception)
|
14
|
+
end
|
15
|
+
end
|
data/lib/tartarus.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'will_paginate'
|
3
|
+
|
4
|
+
class Tartarus
|
5
|
+
class << self
|
6
|
+
def configuration
|
7
|
+
@cached_config ||= YAML.load_file("#{Rails.root}/config/exceptions.yml")[Rails.env]
|
8
|
+
end
|
9
|
+
|
10
|
+
def logger_class
|
11
|
+
configuration['logger_class'].constantize
|
12
|
+
end
|
13
|
+
|
14
|
+
def log(controller, exception)
|
15
|
+
logger_class.log(controller, exception)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'tartarus/logger'
|
22
|
+
require 'tartarus/rescue'
|
data/rails/init.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Filters added to this controller apply to all controllers in the application.
|
2
|
+
# Likewise, all the methods added will be available for all controllers.
|
3
|
+
|
4
|
+
class ApplicationController < ActionController::Base
|
5
|
+
helper :all # include all helpers, all the time
|
6
|
+
protect_from_forgery # See ActionController::RequestForgeryProtection for details
|
7
|
+
|
8
|
+
# Scrub sensitive parameters from your log
|
9
|
+
# filter_parameter_logging :password
|
10
|
+
end
|