rails_exception_logger 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +135 -0
  4. data/Rakefile +40 -0
  5. data/app/assets/javascripts/rails_exception_logger/application.js +15 -0
  6. data/app/assets/javascripts/rails_exception_logger/logged_exceptions.js +2 -0
  7. data/app/assets/javascripts/rails_exception_logger/rails_exception_logger.js +69 -0
  8. data/app/assets/stylesheets/rails_exception_logger/application.css +13 -0
  9. data/app/assets/stylesheets/rails_exception_logger/rails_exception_logger.css +320 -0
  10. data/app/assets/stylesheets/rails_exception_logger/rails_logged_exceptions.css +4 -0
  11. data/app/controllers/rails_exception_logger/application_controller.rb +4 -0
  12. data/app/controllers/rails_exception_logger/logged_exceptions_controller.rb +105 -0
  13. data/app/helpers/exception_logger/application_helper.rb +4 -0
  14. data/app/helpers/exception_logger/logged_exceptions_helper.rb +42 -0
  15. data/app/models/rails_exception_logger/logged_exception.rb +83 -0
  16. data/app/views/layouts/rails_exception_logger/application.html.erb +20 -0
  17. data/app/views/rails_exception_logger/logged_exceptions/_exceptions.html.erb +32 -0
  18. data/app/views/rails_exception_logger/logged_exceptions/_feed.html.erb +3 -0
  19. data/app/views/rails_exception_logger/logged_exceptions/_show.html.erb +23 -0
  20. data/app/views/rails_exception_logger/logged_exceptions/destroy.js.erb +2 -0
  21. data/app/views/rails_exception_logger/logged_exceptions/destroy_all.js.erb +2 -0
  22. data/app/views/rails_exception_logger/logged_exceptions/feed.rss.builder +20 -0
  23. data/app/views/rails_exception_logger/logged_exceptions/index.html.erb +46 -0
  24. data/app/views/rails_exception_logger/logged_exceptions/index.js.erb +2 -0
  25. data/app/views/rails_exception_logger/logged_exceptions/query.js.erb +2 -0
  26. data/app/views/rails_exception_logger/logged_exceptions/show.html.erb +8 -0
  27. data/app/views/rails_exception_logger/logged_exceptions/show.js.erb +2 -0
  28. data/config/initializers/date_formats.rb +5 -0
  29. data/config/locales/en.yml +17 -0
  30. data/config/routes.rb +13 -0
  31. data/db/migrate/20120507081835_create_rails_exception_logger_logged_exceptions.rb +14 -0
  32. data/lib/rails_exception_logger/engine.rb +5 -0
  33. data/lib/rails_exception_logger/version.rb +3 -0
  34. data/lib/rails_exception_logger.rb +68 -0
  35. data/lib/tasks/rails_exception_logger_tasks.rake +4 -0
  36. data/test/dummy/README.rdoc +261 -0
  37. data/test/dummy/Rakefile +7 -0
  38. data/test/dummy/app/assets/javascripts/application.js +15 -0
  39. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  40. data/test/dummy/app/controllers/application_controller.rb +3 -0
  41. data/test/dummy/app/controllers/simulate_controller.rb +10 -0
  42. data/test/dummy/app/helpers/application_helper.rb +2 -0
  43. data/test/dummy/app/helpers/simulate_helper.rb +2 -0
  44. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  45. data/test/dummy/app/views/simulate/failure.html.erb +2 -0
  46. data/test/dummy/config/application.rb +50 -0
  47. data/test/dummy/config/boot.rb +10 -0
  48. data/test/dummy/config/database.yml +25 -0
  49. data/test/dummy/config/environment.rb +5 -0
  50. data/test/dummy/config/environments/development.rb +29 -0
  51. data/test/dummy/config/environments/production.rb +63 -0
  52. data/test/dummy/config/environments/test.rb +33 -0
  53. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  54. data/test/dummy/config/initializers/inflections.rb +15 -0
  55. data/test/dummy/config/initializers/mime_types.rb +5 -0
  56. data/test/dummy/config/initializers/secret_token.rb +7 -0
  57. data/test/dummy/config/initializers/session_store.rb +8 -0
  58. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  59. data/test/dummy/config/locales/en.yml +5 -0
  60. data/test/dummy/config/routes.rb +6 -0
  61. data/test/dummy/config.ru +4 -0
  62. data/test/dummy/db/migrate/20120507083836_create_exception_logger_logged_exceptions.exception_logger.rb +15 -0
  63. data/test/dummy/db/schema.rb +27 -0
  64. data/test/dummy/public/404.html +26 -0
  65. data/test/dummy/public/422.html +26 -0
  66. data/test/dummy/public/500.html +25 -0
  67. data/test/dummy/public/favicon.ico +0 -0
  68. data/test/dummy/script/rails +6 -0
  69. data/test/dummy/test/functional/simulate_controller_test.rb +9 -0
  70. data/test/dummy/test/unit/helpers/simulate_helper_test.rb +4 -0
  71. data/test/exception_logger_test.rb +7 -0
  72. data/test/fixtures/exception_logger/logged_exceptions.yml +11 -0
  73. data/test/functional/exception_logger/logged_exceptions_controller_test.rb +9 -0
  74. data/test/integration/navigation_test.rb +10 -0
  75. data/test/test_helper.rb +10 -0
  76. data/test/unit/exception_logger/logged_exception_test.rb +9 -0
  77. data/test/unit/helpers/exception_logger/logged_exceptions_helper_test.rb +6 -0
  78. metadata +204 -0
@@ -0,0 +1,105 @@
1
+ module RailsExceptionLogger
2
+ class LoggedExceptionsController < ApplicationController
3
+ layout 'rails_exception_logger/application'
4
+
5
+ cattr_accessor :application_name
6
+
7
+ helper_method :params_filters
8
+
9
+ #ApplicationController.class_eval do
10
+ # rescue_from Exception, :with => :log_exception_handler
11
+ #end
12
+
13
+ def index
14
+ @exception_names = LoggedException.class_names
15
+ @controller_actions = LoggedException.controller_actions
16
+ query
17
+ end
18
+
19
+ def query
20
+ exceptions = LoggedException.sorted
21
+ unless params[:id].blank?
22
+ exceptions = exceptions.where(:id => params[:id])
23
+ end
24
+ unless params[:query].blank?
25
+ exceptions = exceptions.message_like(params[:query])
26
+ end
27
+ unless params[:date_ranges_filter].blank?
28
+ exceptions = exceptions.days_old(params[:date_ranges_filter])
29
+ end
30
+ unless params[:exception_names_filter].blank?
31
+ exceptions = exceptions.by_exception_class(params[:exception_names_filter])
32
+ end
33
+ unless params[:controller_actions_filter].blank?
34
+ c_a_params = params[:controller_actions_filter].split('/')
35
+ controller_filter = c_a_params.first.underscore
36
+ action_filter = c_a_params.last.downcase
37
+ exceptions = exceptions.by_controller(controller_filter)
38
+ exceptions = exceptions.by_action(action_filter)
39
+ end
40
+ @exceptions = exceptions.paginate(:page => params[:page], :per_page => 30)
41
+
42
+ respond_to do |format|
43
+ format.html { redirect_to :action => 'index' unless action_name == 'index' }
44
+ format.js
45
+ end
46
+ end
47
+
48
+ def feed
49
+ @exceptions = LoggedException.all
50
+
51
+ respond_to do |format|
52
+ format.rss { render :layout => false }
53
+ end
54
+ end
55
+
56
+ def show
57
+ @exception = LoggedException.where(:id => params[:id]).first
58
+
59
+ respond_to do |format|
60
+ format.js
61
+ format.html
62
+ end
63
+ end
64
+
65
+ def destroy
66
+ @exception = LoggedException.where(:id => params[:id]).first
67
+ @exception.destroy
68
+ end
69
+
70
+ def destroy_all
71
+ LoggedException.delete_all(:id => params[:ids]) unless params[:ids].blank?
72
+ query
73
+ end
74
+
75
+ def clear
76
+ LoggedException.delete_all
77
+ redirect_to :back
78
+ end
79
+
80
+ private
81
+
82
+ def params_filters
83
+ {
84
+ :query => params[:query],
85
+ :date_ranges_filter => params[:date_ranges_filter],
86
+ :exception_names_filter => params[:exception_names_filter],
87
+ :controller_actions_filter => params[:controller_actions_filter],
88
+ }
89
+ end
90
+
91
+ def access_denied_with_basic_auth
92
+ headers["Status"] = "Unauthorized"
93
+ headers["WWW-Authenticate"] = %(Basic realm="Web Password")
94
+ render :text => "Could't authenticate you", :status => '401 Unauthorized'
95
+ end
96
+
97
+ @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
98
+ # gets BASIC auth info
99
+ def get_auth_data
100
+ auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
101
+ auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
102
+ return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,4 @@
1
+ module RailsExceptionLogger
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,42 @@
1
+ module RailsExceptionLogger
2
+ module LoggedExceptionsHelper
3
+ def pretty_exception_date(exception)
4
+ if Date.today == exception.created_at.to_date
5
+ if false # exception.created_at > Time.now - 4.hours
6
+ "#{time_ago_in_words(exception.created_at).gsub(/about /,"~ ")} agox"
7
+ else
8
+ "Today, #{exception.created_at.strftime(Time::DATE_FORMATS[:exc_time])}"
9
+ end
10
+ else
11
+ exception.created_at.strftime(Time::DATE_FORMATS[:exc_date])
12
+ end
13
+ end
14
+
15
+ def filtered?
16
+ [:query, :date_ranges_filter, :exception_names_filter, :controller_actions_filter].any? { |p| params[p] }
17
+ end
18
+
19
+ def listify(text)
20
+ list_items = text.scan(/^\s*\* (.+)/).map {|match| content_tag(:li, match.first) }
21
+ content_tag(:ul, list_items)
22
+ end
23
+
24
+ def page_title(text)
25
+ title = ""
26
+ unless controller.application_name.blank?
27
+ title << "#{controller.application_name} :: "
28
+ end
29
+ title << text.to_s
30
+ content_for(:title, title.to_s)
31
+ end
32
+
33
+ # Rescue textilize call if RedCloth is not available.
34
+ def pretty_format(text)
35
+ begin
36
+ textilize(text).html_safe
37
+ rescue
38
+ simple_format(text).html_safe
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,83 @@
1
+ module RailsExceptionLogger
2
+ class LoggedException < ActiveRecord::Base
3
+ self.table_name = "logged_exceptions"
4
+ HOSTNAME = `hostname -s`.chomp
5
+ class << self
6
+ def create_from_exception(controller, exception, data)
7
+ message = exception.message.inspect
8
+ message << "\n* Extra Data\n\n#{data}" unless data.blank?
9
+ e = create! \
10
+ :exception_class => exception.class.name,
11
+ :controller_name => controller.controller_path,
12
+ :action_name => controller.action_name,
13
+ :message => message,
14
+ :backtrace => exception.backtrace,
15
+ :request => controller.request
16
+ end
17
+
18
+ def host_name
19
+ HOSTNAME
20
+ end
21
+ end
22
+
23
+ scope :by_exception_class, lambda {|exception_class| where(:exception_class => exception_class)}
24
+ scope :by_controller_and_action, lambda {|controller_name, action_name| where(:controller_name => controller_name, :action_name => action_name)}
25
+ scope :by_controller, lambda {|controller_name| where(:controller_name => controller_name)}
26
+ scope :by_action, lambda {|action_name| where(:action_name => action_name)}
27
+ scope :message_like, lambda {|query| where('message like ?', "%#{query}%")}
28
+ scope :days_old, lambda {|day_number| where('created_at >= ?', day_number.to_f.days.ago.utc)}
29
+ scope :sorted, lambda { order('created_at DESC') }
30
+
31
+ def name
32
+ "#{self.exception_class} in #{self.controller_action}"
33
+ end
34
+
35
+ def backtrace=(trace)
36
+ trace = sanitize_backtrace(trace) * "\n" unless trace.is_a?(String)
37
+ write_attribute :backtrace, trace
38
+ end
39
+
40
+ def request=(request)
41
+ if request.is_a?(String)
42
+ write_attribute :request, request
43
+ else
44
+ max = request.env.keys.max { |a,b| a.length <=> b.length }
45
+ env = request.env.keys.sort.inject [] do |env, key|
46
+ env << '* ' + ("%-*s: %s" % [max.length, key, request.env[key].to_s.strip])
47
+ end
48
+ write_attribute(:environment, (env << "* Process: #{$$}" << "* Server : #{self.class.host_name}") * "\n")
49
+
50
+ write_attribute(:request, [
51
+ "* URL:#{" #{request.method.to_s.upcase}" unless request.get?} #{request.protocol}#{request.env["HTTP_HOST"]}#{request.fullpath}",
52
+ "* Format: #{request.format.to_s}",
53
+ "* Parameters: #{request.parameters.inspect}",
54
+ "* Rails Root: #{rails_root}"
55
+ ] * "\n")
56
+ end
57
+ end
58
+
59
+ def controller_action
60
+ @controller_action ||= "#{controller_name.camelcase}/#{action_name}"
61
+ end
62
+
63
+ def self.class_names
64
+ select("DISTINCT exception_class").order(:exception_class).collect(&:exception_class)
65
+ end
66
+
67
+ def self.controller_actions
68
+ select("DISTINCT controller_name, action_name").order(:controller_name,:action_name).collect(&:controller_action)
69
+ end
70
+
71
+ private
72
+ @@rails_root = Pathname.new(Rails.root).cleanpath.to_s
73
+ @@backtrace_regex = /^#{Regexp.escape(@@rails_root)}/
74
+
75
+ def sanitize_backtrace(trace)
76
+ trace.collect { |line| Pathname.new(line.gsub(@@backtrace_regex, "[RAILS_ROOT]")).cleanpath.to_s }
77
+ end
78
+
79
+ def rails_root
80
+ @@rails_root
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <%= csrf_meta_tag %>
6
+ <title><%= yield(:title) || "Exception Logger" %></title>
7
+
8
+ <%= stylesheet_link_tag "rails_exception_logger/application" %>
9
+
10
+ <%= auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "RSS Feed"}) %>
11
+ </head>
12
+ <body>
13
+ <div id="container">
14
+ <%= yield %>
15
+ </div>
16
+ <br style="clear:both" />
17
+
18
+ <%= javascript_include_tag "rails_exception_logger/application" %>
19
+ </body>
20
+ </html>
@@ -0,0 +1,32 @@
1
+ <div id="exceptions">
2
+ <div class="pages">
3
+ <%= link_to('Clear History', {:action => :clear}, :confirm => "are you sure?", :method => :post) %>
4
+ <%= link_to 'Delete Visible', { :action => 'destroy_all' }.merge(params_filters), :class => 'delete_visible_link' %>
5
+ <strong><%= will_paginate @exceptions, :params => { :controller => "logged_exceptions", :action => "index" }.merge(params_filters), :style => 'display:inline' %></strong>
6
+ </div>
7
+ <h1>Exceptions <%= raw "<span>(filtered)</span>" if filtered? %> </h1>
8
+ <table>
9
+ <thead>
10
+ <tr>
11
+ <th>Exception</th>
12
+ <th>Date</th>
13
+ <th></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <% @exceptions.each do |exception| %>
18
+ <tr id="<%= dom_id(exception) %>" class="<%= cycle("eor", "") %> exception">
19
+ <td>
20
+ <div class="expclass"><%= link_to exception.name, {:action => "show", :id => exception}, :class => 'show_link' %></div>
21
+ <span class="message"><%= h exception.message %></span>
22
+ </td>
23
+ <td class="time"><%= pretty_exception_date(exception) %></td>
24
+ <td><%= link_to 'Delete', { :action => 'destroy', :id => exception }, :class => "util delete_link" %></td>
25
+ </tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
29
+ <div class="pages pages-bottom">
30
+ <strong><%= will_paginate @exceptions, :params => { :controller => "logged_exceptions", :action => "index" }.merge(params_filters), :style => 'display:inline' %></strong>
31
+ </div>
32
+ </div> <!-- #exceptions -->
@@ -0,0 +1,3 @@
1
+ <ul id="feed" class="filters">
2
+ <li><%= link_to "RSS Feed", feed_logged_exceptions_url(:format => :rss) %></li>
3
+ </ul>
@@ -0,0 +1,23 @@
1
+ <div class="tools">
2
+ <%= link_to 'Delete', { :action => 'destroy', :id => @exception }, :class => "util delete_link" %>
3
+ <span class="pipe">|</span>
4
+ <%= link_to "Close", "#", :class => "util close_link" %>
5
+ </div>
6
+
7
+ <div class="date">
8
+ <%= @exception.created_at.strftime(Time::DATE_FORMATS[:exc_full]) %>
9
+ </div>
10
+ <h1><%= @exception.name %></h1>
11
+
12
+ <h2>Request</h2>
13
+ <%= pretty_format(@exception.request) %>
14
+
15
+ <h2>Backtrace</h2>
16
+ <%= simple_format @exception.message %>
17
+
18
+ <div id="backtrace">
19
+ <%= raw @exception.backtrace.gsub(/\n/,"<br />") %>
20
+ </div>
21
+
22
+ <h2>Environment</h2>
23
+ <%= pretty_format(@exception.environment) %>
@@ -0,0 +1,2 @@
1
+ $('#<%= dom_id(@exception) %>').addClass('deleted');
2
+ $('#showpage').hide();
@@ -0,0 +1,2 @@
1
+ $('#exceptions').html('<%= escape_javascript render :partial => "exceptions" %>');
2
+ $('#showpage').hide();
@@ -0,0 +1,20 @@
1
+ xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
2
+
3
+ xml.rss "version" => "2.0" do
4
+ xml.channel do
5
+ xml.title "#{RailsExceptionLogger::LoggedExceptionsController.application_name}"
6
+ xml.link url_for(:only_path => false, :skip_relative_url_root => false)
7
+ xml.language "en-us"
8
+ xml.ttl "60"
9
+
10
+ @exceptions.each do |exc|
11
+ xml.item do
12
+ xml.title "#{exc.name} @ #{exc.created_at.rfc822}"
13
+ xml.description exc.message
14
+ xml.pubDate exc.created_at.rfc822
15
+ xml.guid [request.host_with_port, 'exceptions', exc.id.to_s].join(":"), "isPermaLink" => "false"
16
+ xml.link url_for(:action => 'index', :anchor => "e#{exc.id}", :only_path => false, :skip_relative_url_root => false)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,46 @@
1
+ <% page_title t(".title") %>
2
+ <div id="right">
3
+ <h3><%=t(".filters")%></h3>
4
+ <ul id="all_exceptions" class="filters">
5
+ <li><%= link_to t(".latest_exceptions"), :action => 'index', :id => nil %></li>
6
+ </ul>
7
+ <h4><%=t(".exception")%></h4>
8
+ <ul id="exception_names" class="filters">
9
+ <% @exception_names.each do |name| %>
10
+ <li><%= link_to name, {:action => 'query', :exception_names_filter => "#{name}"}, :class => 'filter_link' %></li>
11
+ <% end %>
12
+ </ul>
13
+ <h4><%=t(".controller_action")%></h4>
14
+ <ul id="controller_actions" class="filters">
15
+ <% @controller_actions.each do |action| %>
16
+ <li><%= link_to action, {:action => 'query', :controller_actions_filter => "#{action}"}, :class => 'filter_link' %></li>
17
+ <% end %>
18
+ </ul>
19
+ <h4><%=t(".dates")%></h4>
20
+ <ul id="date_ranges" class="filters">
21
+ <li><%= link_to t(".today"), {:action => 'query', :date_ranges_filter => "1"}, :title => "1", :class => 'filter_link' %></li>
22
+ <li><%= link_to t(".last_few_days"), {:action => 'query', :date_ranges_filter => "3"}, :title => "3", :class => 'filter_link' %></li>
23
+ <li><%= link_to t(".last_7_days"), {:action => 'query', :date_ranges_filter => "7"}, :title => "7", :class => 'filter_link' %></li>
24
+ <li><%= link_to t(".last_30_days"), {:action => 'query', :date_ranges_filter => "30"}, :title => "30", :class => 'filter_link' %></li>
25
+ </ul>
26
+ <div id="search">
27
+ <%= form_tag "logged_exceptions/query", :id => 'query-form' %>
28
+ <div>
29
+ <%= text_field_tag :query, "", :size => 17 %>
30
+ <%= submit_tag :Find %>
31
+ <%= hidden_field_tag :exception_names_filter %>
32
+ <%= hidden_field_tag :date_ranges_filter %>
33
+ <%= hidden_field_tag :controller_actions_filter %>
34
+ <%= hidden_field_tag :page, (params[:page] || 1) %>
35
+ </div>
36
+ </form>
37
+ </div>
38
+ <%= render :partial => 'feed' %>
39
+ </div> <!-- right -->
40
+ <div id="left">
41
+ <div class="page" id="showpage" style="display:none;"></div>
42
+ <div class="page">
43
+ <%= render :partial => "exceptions" %>
44
+ </div>
45
+ </div>
46
+ <div id="activity" style="display:none;">Busy...</div>
@@ -0,0 +1,2 @@
1
+ $('#exceptions').html('<%= escape_javascript render :partial => "exceptions" %>');
2
+ $('#showpage').hide();
@@ -0,0 +1,2 @@
1
+ $('#exceptions').html('<%= escape_javascript render :partial => "exceptions" %>');
2
+ $('#showpage').hide();
@@ -0,0 +1,8 @@
1
+ <% page_title t(".title") %>
2
+ <div id="right">
3
+ </div> <!-- right -->
4
+ <div id="left">
5
+ <div class="page" id="showpage">
6
+ <%= render :partial => "show" %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,2 @@
1
+ $('#showpage').html('<%= escape_javascript render :partial => "show" %>');
2
+ $('#showpage').show();
@@ -0,0 +1,5 @@
1
+ Time::DATE_FORMATS.merge!(
2
+ :exc_full => "%A, %b %d, %Y at %l:%M %p",
3
+ :exc_date => "%b %d, %Y",
4
+ :exc_time => "%l:%M %p"
5
+ )
@@ -0,0 +1,17 @@
1
+ en:
2
+ rails_exception_logger:
3
+ logged_exceptions:
4
+ index:
5
+ title: Logged Exceptions
6
+ filters: Filters
7
+ latest_exceptions: Latest Exceptions
8
+ exception: Exception
9
+ controller_action: Controller / Action
10
+ dates: Dates
11
+ today: Today
12
+ last_few_days: Last few days
13
+ last_7_days: Last 7 days
14
+ last_30_days: Last 30 days
15
+ show:
16
+ title: Logged Exception
17
+
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ RailsExceptionLogger::Engine.routes.draw do
2
+ # Exception Logger
3
+ resources :rails_logged_exceptions do
4
+ collection do
5
+ post :clear
6
+ post :query
7
+ post :destroy_all
8
+ get :feed
9
+ end
10
+ end
11
+
12
+ root :to => 'logged_exceptions#index'
13
+ end
@@ -0,0 +1,14 @@
1
+ class CreateRailsExceptionLoggerLoggedExceptions < ActiveRecord::Migration
2
+ def change
3
+ create_table :rails_logged_exceptions, :force => true do |t|
4
+ t.string :exception_class
5
+ t.string :controller_name
6
+ t.string :action_name
7
+ t.text :message
8
+ t.text :backtrace
9
+ t.text :environment
10
+ t.text :request
11
+ t.datetime :created_at
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module RailsExceptionLogger
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsExceptionLogger
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module RailsExceptionLogger
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,68 @@
1
+ require "rails_exception_logger/engine"
2
+ require "will_paginate"
3
+ require 'ipaddr'
4
+
5
+ module RailsExceptionLogger
6
+ # Copyright (c) 2005 Jamis Buck
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to
13
+ # permit persons to whom the Software is furnished to do so, subject to
14
+ # the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be
17
+ # included in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ module ExceptionLoggable
27
+ def self.included(target)
28
+ target.extend(ClassMethods)
29
+ target.class_attribute :local_addresses, :exception_data
30
+
31
+ target.local_addresses = [IPAddr.new("127.0.0.1")]
32
+ end
33
+
34
+ module ClassMethods
35
+ def consider_local(*args)
36
+ local_addresses.concat(args.flatten.map { |a| IPAddr.new(a) })
37
+ end
38
+ end
39
+
40
+ def local_request?
41
+ remote = IPAddr.new(request.remote_ip)
42
+ !self.class.local_addresses.detect { |addr| addr.include?(remote) }.nil?
43
+ end
44
+
45
+ # we log the exception and raise it again, for the normal handling.
46
+ def log_exception_handler(exception)
47
+ log_exception(exception)
48
+ raise exception
49
+ end
50
+
51
+ def rescue_action(exception)
52
+ status = response_code_for_rescue(exception)
53
+ log_exception(exception) if status != :not_found
54
+ super
55
+ end
56
+
57
+ def log_exception(exception)
58
+ deliverer = self.class.exception_data
59
+ data = case deliverer
60
+ when nil then {}
61
+ when Symbol then send(deliverer)
62
+ when Proc then deliverer.call(self)
63
+ end
64
+
65
+ LoggedException.create_from_exception(self, exception, data)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rails_exception_logger do
3
+ # # Task goes here
4
+ # end