error_log 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog.txt ADDED
@@ -0,0 +1,15 @@
1
+ 0.0.5
2
+ * haml dependency added (sorry folks, I could not stand rhtml
3
+ * viewing archive
4
+ * selecting sort order
5
+ * proper group by
6
+
7
+ 0.0.4
8
+ * marking single errros as read
9
+
10
+ 0.0.3
11
+ * very unmatura error params introduced
12
+
13
+ 0.0.2
14
+ Basic skeleton
15
+ * errors can be browsed already, grouped by error string and category
data/README.txt CHANGED
@@ -8,7 +8,7 @@ Easy way to track exceptions and warnings in your rails app
8
8
  It's still just a skeleton.
9
9
  More description and documentation will come.. one day.. I guess.
10
10
 
11
- THIS IS DEVELOPMENT VERSION, DO NOT EVEN TOUCH PRODUCTION SERVER WITH IT.
11
+ THIS IS AN EARLY DEVELOPMENT VERSION, DO NOT EVEN TOUCH PRODUCTION SERVER WITH IT.
12
12
  Actually, it is so unmature that even playing with it can make you sad.
13
13
  And no one likes to be sad.
14
14
 
@@ -53,14 +53,15 @@ To be continued.
53
53
 
54
54
  == TODOS
55
55
 
56
+ * git (and other VCS) awareness
57
+ * better params viewing (currently only example params)
56
58
  * setting error level threshold while browsing
57
- * nicer browsing (themes would be good, but I really do not like css so help needed)
59
+ * better look (themes would be good, but I really do not like css, so help needed)
58
60
  * adding errors to ignore list
59
- * alternative errors storage (for database failures, maybe just some sqlite?)
61
+ * pagination could by nice ;) (it ain't actually so bad without it thanks to grouping)
62
+ * alternative errors storage (for database failures, probably sqlite will do)
60
63
  * clickable backtraces? we could show some code
61
64
  * rails 2.x compatibility
62
- * marking single errors as read, browsing archive
63
- * bugfixes, lots of
64
65
 
65
66
  == STUFF
66
67
 
@@ -1,57 +1,125 @@
1
1
 
2
+
3
+ require 'haml'
4
+
2
5
  module ErrorLog
3
- module Controller# < ActionController::Base
4
-
5
- def index
6
-
7
- # Rails 2.x compatible finder
8
- scope = ErrorLog::Model
9
-
10
- unless params[:errors_category].to_s.empty?
11
- @errors_category = params[:errors_category]
12
- scope = scope.where(:category => @errors_category)
13
- end
14
-
15
- @error_logs = scope.all(
16
- :order => 'created_at DESC',
17
- :conditions => {
18
- :viewed => false
19
- }
20
- ).group_by(&:error_hash)
21
-
22
- @category_counts = ErrorLog::Model.count(
23
- :conditions => {:viewed => false},
24
- :group => :category
25
- )
26
-
27
- render :template => '/index'
6
+ module Controller
7
+
8
+ def index
9
+
10
+ prepare_opts
11
+
12
+ scope = ErrorLog::Model
13
+
14
+ scope = scope.where(:category => @errors_category) unless @errors_category.to_s.empty?
15
+
16
+ @error_logs = scope.all(
17
+ :select => 'count(*) as count_all,
18
+ min(created_at) as created_at_first,
19
+ max(created_at) as created_at_last,
20
+ min(backtrace) as backtrace,
21
+ min(error) as error,
22
+ min(category) as category,
23
+ min(params) as params,
24
+ max(level_id) as level_id,
25
+ error_hash',
26
+ :order => @opts[:sort_by],
27
+ :group => 'error_hash',
28
+ :conditions => {
29
+ :viewed => viewing_archive?
30
+ })
31
+
32
+
33
+ @category_counts = ErrorLog::Model.count(
34
+ :conditions => {:viewed => viewing_archive?},
35
+ :group => :category
36
+ )
37
+
38
+ render :template => '/index'
39
+ end
40
+
41
+ def set_all_viewed
42
+ ErrorLog::Model.update_all(:viewed => true)
43
+ redirect_to :back
44
+ end
45
+
46
+ def delete_all_archived
47
+ ErrorLog::Model.where(:viewed => true).destroy_all
48
+ redirect_to :back
49
+ end
50
+
51
+ # set all logs with given error hash viewed
52
+ def set_viewed
53
+ logs = ErrorLog::Model.where(:viewed => false, :error_hash => params[:error_hash])
54
+ logs.update_all(:viewed => true)
55
+ render :update do |page|
56
+ page[params[:row_div_id]].hide
28
57
  end
58
+ end
29
59
 
30
- def set_all_viewed
31
- ErrorLog::Model.update_all(:viewed => true)
32
- redirect_to :back
60
+ # destroy all archived logs with given error hash
61
+ def delete
62
+ logs = ErrorLog::Model.where(:viewed => true, :error_hash => params[:error_hash])
63
+ logs.destroy_all
64
+ render :update do |page|
65
+ page[params[:row_div_id]].hide
33
66
  end
67
+ end
68
+
69
+ protected
70
+
71
+ def viewing_archive?
72
+ @opts[:archive] == '1'
73
+ end
74
+
75
+ def self.included(klass)
76
+ klass.send(:helper_method,:viewing_archive?)
77
+ end
34
78
 
35
- end
79
+ def prepare_opts
80
+ sorts = {
81
+ 'last' => 'created_at_last DESC',
82
+ 'first' => 'created_at_first DESC',
83
+ 'count' => 'count_all DESC',
84
+ 'level' => 'level_id DESC',
85
+ 'level_count' => 'level DESC, count_all DESC'
86
+ }
87
+
88
+ @opts = {
89
+ :archive => '0',
90
+ :sort_by => sorts['last'],
91
+ :category => nil
92
+ }
93
+
94
+ session[:erlgs_archive] = params[:archive] if params[:archive]
95
+ @opts[:archive] = session[:erlgs_archive]
96
+
97
+ session[:erlgs_sort_by] = params[:sort_by] if params[:sort_by]
98
+ @opts[:sort_by] = sorts[session[:erlgs_sort_by]]
99
+
100
+ session[:erlgs_category] = params[:category] if params[:category]
101
+ @opts[:category] = @errors_category = session[:erlgs_category]
102
+ end
103
+ end
36
104
  end
37
105
 
38
106
  class ActionController::Base
39
107
 
40
- rescue_from Exception, :with => :error_log_rescue
108
+ rescue_from Exception, :with => :error_log_rescue
41
109
 
42
- def self.error_logs
43
- append_view_path File.join(ErrorLog.path,'views')
44
- self.send(:include,ErrorLog::Controller)
45
- end
110
+ def self.error_logs
111
+ append_view_path File.join(ErrorLog.path,'views')
112
+ self.send(:include,ErrorLog::Controller)
113
+ end
46
114
 
47
- def error_log_rescue(e)
48
- err = ErrorLog::Model.new(
49
- :error => e.to_str,
50
- :backtrace => e.backtrace,
51
- :category => 'rails'
52
- )
53
- err.save
54
- raise e
55
- end
115
+ def error_log_rescue(e)
116
+ err = ErrorLog::Model.new(
117
+ :error => e.to_str,
118
+ :backtrace => e.backtrace,
119
+ :category => 'rails'
120
+ )
121
+ err.save
122
+ raise e
123
+ end
56
124
 
57
125
  end
@@ -8,12 +8,10 @@ class Object
8
8
  yield
9
9
  return false
10
10
  rescue Exception => e
11
- ErrorLog::Model.create(
12
- :error => e.to_str,
13
- :backtrace => e.backtrace,
14
- :level => (options[:level] || :error),
15
- :category => category
16
- )
11
+ ErrorLog.log(options[:level] || :error, e.to_str,
12
+ :backtrace => e.backtrace,
13
+ :params => options[:params],
14
+ :category => category)
17
15
  end
18
16
  end
19
17
 
@@ -0,0 +1,26 @@
1
+ module ErrorLog
2
+
3
+ class Migration < ActiveRecord::Migration
4
+ def self.up
5
+ create_table :error_logs do |t|
6
+ t.text :error
7
+ t.text :backtrace
8
+ t.string :category
9
+ # note to future me: "hash" is a really bad name for the column
10
+ t.string :error_hash
11
+ t.integer :level_id
12
+ t.timestamp :created_at
13
+ t.boolean :viewed, :default => false
14
+ end
15
+
16
+ add_index :error_hash, :category
17
+ end
18
+ end
19
+
20
+ class UpgradeMigration1 < ActiveRecord::Migration
21
+ def self.up
22
+ add_column :error_logs, :params, :text
23
+ end
24
+ end
25
+
26
+ end
@@ -3,24 +3,18 @@ require 'digest/md5'
3
3
  module ErrorLog
4
4
  class Model < ActiveRecord::Base
5
5
 
6
- class Migration < ActiveRecord::Migration
7
- def self.up
8
- create_table :error_logs do |t|
9
- t.text :error
10
- t.text :backtrace
11
- t.string :category
12
- # note to future me: "hash" is a really bad name for the column
13
- t.string :error_hash
14
- t.integer :level_id
15
- t.timestamp :created_at
16
- t.boolean :viewed, :default => false
17
- end
18
- end
19
- end
20
-
21
6
  self.table_name = 'error_logs'
7
+
8
+ # Migrate database if needed
22
9
  unless self.table_exists?
23
10
  Migration.up
11
+ reset_column_information
12
+ end
13
+
14
+ # Upgrade if needed
15
+ unless column_names.include?('params')
16
+ UpgradeMigration1.up
17
+ reset_column_information
24
18
  end
25
19
 
26
20
  LEVELS = {
@@ -33,6 +27,9 @@ module ErrorLog
33
27
  :wtf => 5
34
28
  }
35
29
 
30
+ serialize :params, Hash
31
+ attr_accessor :count # used in grouping
32
+
36
33
  def level
37
34
  LEVELS.invert[self.level_id]
38
35
  end
@@ -1,3 +1,3 @@
1
1
  module ErrorLog
2
- VERSION = "0.0.2" unless defined?(::ErrorLog::VERSION)
2
+ VERSION = "0.0.5" unless defined?(::ErrorLog::VERSION)
3
3
  end
data/lib/error_log.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'pp'
1
2
 
2
3
  module ErrorLog
3
4
 
@@ -59,6 +60,34 @@ module ErrorLog
59
60
  Dir.glob(search_me).sort.each {|rb| require rb}
60
61
  end
61
62
 
63
+
64
+ def self.log(level,error,options={})
65
+ backtrace = options[:backtrace]
66
+ unless backtrace
67
+ # get current backtrace, I'm happy to learn any more clever way
68
+ begin
69
+ raise "wat?!"
70
+ rescue Exception => e
71
+ backtrace = e.backtrace[1..-1]
72
+ end
73
+ end
74
+
75
+ #TODO: silent rescues may not be optimal, for now they seem better than creating more mess
76
+ logger.error "\n\n\n#{Time.now}\n= #{error}\n#{backtrace.join("\n")}\n#{options[:params]}" rescue nil
77
+
78
+ ErrorLog::Model.create(
79
+ :error => error,
80
+ :backtrace => backtrace,
81
+ :level => level,
82
+ :params => options[:params],
83
+ :category => options[:category] || 'error_log'
84
+ ) rescue nil
85
+ end
86
+
87
+ def self.logger
88
+ @logger = Logger.new(File.join(Rails.root,'log','error.log'))
89
+ end
90
+
62
91
  end # module ErrorLog
63
92
 
64
93
 
@@ -0,0 +1,51 @@
1
+ - row_div_id = "error_log_row_#{error_log.error_hash}"
2
+
3
+ %tr{:class => cycle('odd','even'), :id => row_div_id}
4
+ %td
5
+ %div{:class => "level_box level_#{error_log.level}"}
6
+ = error_log.level
7
+ %span.time
8
+ -# when using select, activerecord returns strings only
9
+ = Time.parse(error_log.created_at_last).strftime('%Y-%m-%d %H:%M')
10
+ %span{:style => 'color: #7a7'}
11
+ (#{distance_of_time_in_words error_log.created_at_last,Time.now} ago)
12
+ %br
13
+ %br
14
+ [#{error_log.category}]
15
+ %b= error_log.error
16
+ %br
17
+ %br
18
+
19
+ -# Repeated N times
20
+ - if error_log.count_all.to_i > 1
21
+ %div{:style => "text-align: center; clear: both"}
22
+ Repeated
23
+ %b
24
+ %span{:style => "font-size: #{[12 + error_log.count_all.to_i,100].min}px;"}
25
+ = error_log.count_all
26
+ times.
27
+ %br
28
+ %span.time_first{:style => 'color: #aaa'}
29
+ %i in the last #{distance_of_time_in_words error_log.created_at_first,Time.now}
30
+
31
+ -# error params if logged
32
+ - if error_log.params && !error_log.params.empty?
33
+ %br
34
+ example params:
35
+ %pre
36
+ = error_log.params.pretty_inspect
37
+
38
+ -# backtrace
39
+ - bt = error_log.backtrace.split("\n")
40
+ %div.backtrace
41
+ = raw bt[0...3].join(" <br />")
42
+ - if bt.size > 4
43
+ - bid = "error_log_bt_#{error_log.id}"
44
+ = link_to_function '...', "$('#{bid}').show();"
45
+ %span{:style => "display: none", :id => bid}
46
+ = raw bt[4...-1].join(" <br />")
47
+ %span.actions
48
+ - if viewing_archive?
49
+ = link_to('delete premamently', { :action => :delete, :error_hash => error_log.error_hash, :row_div_id => row_div_id }, :remote => true, :onclick => "this.innerHTML = 'wait for it...';")
50
+ - else
51
+ = link_to('mark as read', { :action => :set_viewed, :error_hash => error_log.error_hash, :row_div_id => row_div_id }, :remote => true, :onclick => "this.innerHTML = 'wait for it...';")
@@ -0,0 +1,69 @@
1
+
2
+ <style type="text/css">
3
+
4
+ #error_logs_wrap td {
5
+ padding: 15px;
6
+ }
7
+
8
+ #error_logs tr.odd {
9
+ background-color: #fefefe;
10
+ }
11
+
12
+ #error_logs tr.even {
13
+ background-color: #f5f5f5;
14
+ }
15
+
16
+ table#error_logs {
17
+ border: 1px solid #333;
18
+ width: 100%;
19
+ border-collapse: collapse;
20
+ }
21
+
22
+ table#error_logs td {
23
+ border: 1px solid #999;
24
+ padding: 10px;
25
+ font-family: Verdana;
26
+ }
27
+
28
+ table#error_logs .level_error {
29
+ background-color: #ffa;
30
+ }
31
+
32
+ table#error_logs .level_fatal {
33
+ background-color: #f99;
34
+ }
35
+
36
+ table#error_logs .level_warn {
37
+ background-color: #9c9;
38
+ }
39
+
40
+ table#error_logs .level_box {
41
+ border: 1px solid #333;
42
+ padding: 10px;
43
+ font-weight: bold;
44
+ float: right;
45
+ margin: 20px;
46
+ }
47
+
48
+ table#error_logs .backtrace {
49
+ overflow: hidden;
50
+ width: 100%;
51
+ font-family: Monospace;
52
+ font-size: 0.9em;
53
+ color: #855;
54
+ }
55
+
56
+ table#error_logs .time {
57
+ font-size: 0.7em;
58
+ font-style: italic;
59
+ }
60
+
61
+ table#error_logs .actions {
62
+ font-size: 0.7em;
63
+ }
64
+
65
+ table#error_logs .time_first {
66
+ font-size: 0.7em;
67
+ }
68
+
69
+ </style>
@@ -0,0 +1,42 @@
1
+ = render :partial => '/styles'
2
+ %h1 Error logs #{viewing_archive? ? '[archive]' : ''}
3
+
4
+ - form_tag({},:method => :get) do
5
+ sort by:
6
+ = select_tag(:sort_by, options_for_select([['last error','last'],
7
+ ['first error','first'],
8
+ ['errors count','count'],
9
+ ['level','level'],
10
+ ['level then count','level_count']],
11
+ session[:erlgs_sort_by]), :onchange => 'this.form.submit();' )
12
+
13
+ %div{:style => 'text-align: right'}
14
+ - if viewing_archive?
15
+ = button_to "Delete all archived", :action => 'delete_all_archived'
16
+ - else
17
+ = button_to "Mark all as read", :action => 'set_all_viewed'
18
+ %br
19
+
20
+ -# Hell I love table layouts
21
+ %table#error_logs_wrap
22
+ %tr
23
+ %td{:valign=>"top"}
24
+ %b Categories:
25
+ %ul
26
+ %li
27
+ = link_to_if @errors_category, 'all', :action => :index
28
+ (#{@category_counts.values.sum})
29
+ - @category_counts.each_pair do |category,count|
30
+ %li
31
+ #{link_to_if (@errors_category != category), category, :action => :index, :category => category}&nbsp;(#{count})
32
+ %br
33
+ %br
34
+ %br
35
+ - if viewing_archive?
36
+ = link_to 'view current', :archive => '0'
37
+ - else
38
+ = link_to 'view archive', :archive => '1'
39
+ %td
40
+ %table#error_logs
41
+ - @error_logs.each do |error_log|
42
+ = render :partial => '/error_log', :locals => {:error_log => error_log}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: error_log
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kacper Ciesla
@@ -15,10 +15,23 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-07 00:00:00 +02:00
18
+ date: 2010-11-17 00:00:00 +01:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: haml
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
22
35
  description: Who cares about description, nobody reads it anyway.
23
36
  email:
24
37
  - kacper.ciesla@gmail.com
@@ -34,8 +47,12 @@ files:
34
47
  - lib/error_log/model.rb
35
48
  - lib/error_log/controller.rb
36
49
  - lib/error_log/core_ext.rb
37
- - views/index.html.erb
50
+ - lib/error_log/migrations.rb
51
+ - views/index.html.haml
52
+ - views/_styles.html.erb
53
+ - views/_error_log.html.haml
38
54
  - README.txt
55
+ - Changelog.txt
39
56
  has_rdoc: true
40
57
  homepage:
41
58
  licenses: []
data/views/index.html.erb DELETED
@@ -1,119 +0,0 @@
1
-
2
- <%# I'm sorry but view ain't beautiful quite yet. It will probably be totally rewritten %>
3
-
4
- <style type="text/css">
5
- #error_logs tr.odd {
6
- background-color: #fefefe;
7
- }
8
-
9
- #error_logs tr.even {
10
- background-color: #f5f5f5;
11
- }
12
-
13
- table#error_logs {
14
- border: 1px solid #333;
15
- width: 100%;
16
- border-collapse: collapse;
17
- }
18
-
19
- table#error_logs td {
20
- border: 1px solid #999;
21
- padding: 10px;
22
- font-family: Verdana;
23
- }
24
-
25
- table#error_logs .level_error {
26
- background-color: #ffa;
27
- }
28
-
29
- table#error_logs .level_fatal {
30
- background-color: #f99;
31
- }
32
-
33
- table#error_logs .level_warn {
34
- background-color: #9c9;
35
- }
36
-
37
- table#error_logs .level_box {
38
- border: 1px solid #333;
39
- padding: 10px;
40
- font-weight: bold;
41
- float: right;
42
- margin: 20px;
43
- }
44
-
45
- table#error_logs .backtrace {
46
- overflow: auto;
47
- font-family: Monospace;
48
- font-size: 0.9em;
49
- color: #999;
50
- }
51
-
52
- table#error_logs .time {
53
- font-size: 0.7em;
54
- font-style: italic;
55
- }
56
-
57
-
58
- </style>
59
-
60
- <h1>Error logs</h1>
61
-
62
- <div align="right">
63
- <%= button_to "Mark all as read", :action => 'set_all_viewed' %>
64
- </div>
65
- <br />
66
-
67
- <!-- Hell I love table layouts -->
68
- <table style="width: 100%" cellpadding="10">
69
- <tr><td valign="top">
70
- <ul>
71
- <li>
72
- <%= link_to_if @errors_category, 'all', :action => :index %> (<%= @category_counts.values.sum %>)
73
- </li>
74
- <% @category_counts.each_pair do |category,count| %>
75
- <li>
76
- <%= link_to_if (@errors_category != category), category, :action => :index, :errors_category => category %>&nbsp;(<%= count %>)
77
- </li>
78
- <% end %>
79
- </ul>
80
- </td><td>
81
-
82
- <table id="error_logs">
83
- <% @error_logs.each_pair do |hash,logs| %>
84
- <% error_log = logs.first %>
85
- <tr class="<%= cycle('odd','even') %>">
86
- <td>
87
- <div class="level_box level_<%= error_log.level %>">
88
- <%= error_log.level %>
89
- </div>
90
-
91
- <span class="time"><%= error_log.created_at %></span>
92
- <br />
93
- [<%= error_log.category %>]
94
- <b><%= error_log.error %></b>
95
- <br />
96
-
97
- <% if logs.count > 1 %>
98
- <div style="text-align: center">
99
- Repeated <b><span style="font-size: <%= [12 + logs.count,100].min %>px;"><%= logs.count %></span></b> times.<br />
100
- </div>
101
- <% end %>
102
-
103
- <br />
104
- <% bt = error_log.backtrace.split("\n") %>
105
- <div class="backtrace">
106
- <%= bt[0...3].join("\n") %>
107
- <% bid = "error_log_bt_#{error_log.id}" %>
108
- <%= link_to_function '...', "$('#{bid}').show();" %>
109
- <span style="display: none" id="<%= bid %>">
110
- <%= bt[4...-1].join("\n") %>
111
- </span>
112
- </div>
113
- </tr>
114
- </tr>
115
- <% end %>
116
- </table>
117
-
118
- </td></tr>
119
- </table>