rails_exception_logger 0.2.1

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.
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