better_logging 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+ gem 'rake'
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ better_logging (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ rake (0.9.2.2)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ better_logging!
16
+ rake
data/README.textile ADDED
@@ -0,0 +1,179 @@
1
+ h1. "Better Logging" Rails plugin
2
+
3
+ "http://github.com/pauldowman/better_logging":http://github.com/pauldowman/better_logging
4
+
5
+ This is a Rails plugin that improves the log format, and adds an optional "Exception" parameter to the warn() and error() methods to print a stack trace automatically.
6
+
7
+ h2. Improved log format
8
+
9
+ It adds severity level (with colour, if colour is enabled), time (in "ISO8601 format":http://en.wikipedia.org/wiki/ISO_8601), hostname and process ID to each log line, and it and adds warn() and exception() methods that take an exception as an argument and print the stack trace.
10
+
11
+ For example, here's how the Rails log looks normally, without the better_logging plugin installed:
12
+
13
+ <pre>
14
+ Session ID: 7eeb00aa62b395698a28bf033e56b7c5
15
+ Parameters: {"action"=>"show", "id"=>"1", "controller"=>"people"}
16
+ User Load (0.4ms) SELECT * FROM `users` WHERE (id = '1') LIMIT 1
17
+ User Columns (2.1ms) SHOW FIELDS FROM `users`
18
+ Rendering template within layouts/application
19
+ Rendering people/show
20
+ Rendered layouts/_head (3.1ms)
21
+ Rendered layouts/_navigation (2.2ms)
22
+ Adding Cache-Control header
23
+ Completed in 164ms (View: 116, DB: 21) | 200 OK [http://localhost/people/1]
24
+ </pre>
25
+
26
+ Here's how the same thing would look with the better_logging plugin installed in development mode. Note that the severity (INFO, WARN, ERROR, etc), is printed in colour (if colour is enabled for the log, which it is by default in development mode).
27
+
28
+ <pre>
29
+ INFO Session ID: 7eeb00aa62b395698a28bf033e56b7c5
30
+ INFO Parameters: {"action"=>"show", "id"=>"1", "controller"=>"people"}
31
+ DEBUG User Load (0.4ms) SELECT * FROM `users` WHERE (id = '1') LIMIT 1
32
+ DEBUG User Columns (2.1ms) SHOW FIELDS FROM `users`
33
+ INFO Rendering template within layouts/application
34
+ INFO Rendering people/show
35
+ DEBUG Rendered layouts/_head (3.1ms)
36
+ DEBUG Rendered layouts/_navigation (2.2ms)
37
+ INFO Adding Cache-Control header
38
+ INFO Completed in 164ms (View: 116, DB: 21) | 200 OK [http://localhost/people/1]
39
+ </pre>
40
+
41
+ And here's how it would look with the better_logging plugin installed in production mode, on a host named "akash", with process id 27471:
42
+
43
+ <pre>
44
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Session ID: 7eeb00aa62b395698a28bf033e56b7c5
45
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Parameters: {"action"=>"show", "id"=>"1", "controller"=>"people"}
46
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Rendering template within layouts/application
47
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Rendering people/show
48
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Adding Cache-Control header
49
+ akash.27471 2011-10-14T15:39:17.063613-04:00 INFO Completed in 164ms (View: 116, DB: 21) | 200 OK [http://localhost/people/1]
50
+ </pre>
51
+
52
+
53
+ And here's how it would look in production mode on a host with a long name. This host name is "myreallybigserver-7.mydomain.com".
54
+
55
+ <pre>
56
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Session ID: 7eeb00aa62b395698a28bf033e56b7c5
57
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Parameters: {"action"=>"show", "id"=>"1", "controller"=>"people"}
58
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Rendering template within layouts/application
59
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Rendering people/show
60
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Adding Cache-Control header
61
+ igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Completed in 164ms (View: 116, DB: 21) | 200 OK [http://localhost/people/1]
62
+ </pre>
63
+
64
+ Note that the hostname & process ID is added to the beginning of each line of a multi-line log statement. So even if you call logger.error() with a string that has newlines in it, the host & process ID will be added to each line, not only the first.
65
+
66
+ This is so that you can filter your log with a regular expression like /^igserver-7\.27471/ and not miss lines.
67
+
68
+
69
+ h2. Improved warn() and error() methods
70
+
71
+ The warn() and error() methods now allow an Exception object to be given as an optional second parameter. If the exception is given, then the stack trace will be automatically logged.
72
+
73
+ For example:
74
+
75
+ <pre>
76
+ begin
77
+ # do something that raises an exception
78
+ rescue Exception => e
79
+ Rails.logger.error "Oops", e
80
+ end
81
+ </pre>
82
+
83
+ The above code will log "Oops", and then log the stack trace.
84
+
85
+
86
+ h2. Why?
87
+
88
+ h3. Adding severity
89
+
90
+ All lines printed to the log have a "severity" level, this can be "DEBUG", "WARN", "ERROR", etc. Normally this isn't included in the log output, so it's impossible to search a log file for warnings or errors, or filter based on severity, and it's just a useful thing to see.
91
+
92
+ h3. Adding hostname and process ID
93
+
94
+ Normally, when not in development mode, a Rails app consists of more than one Rails process responding to requests at the same time. Those processes may be printing lines to the log at the same time, and it's hard to know which process printed a certain line.
95
+
96
+ Also, it's common to have multiple servers working in parallel, and a user's session might involve requests to multiple servers. If the log files are combined it's useful to know which process on which server printed a given line.
97
+
98
+ This makes it possible to filter a Rails log to show output from one process only, and to combine the log files from multiple servers.
99
+
100
+ The hostname is truncated (by default to 10 characters but this is configurable). The end of the hostname is printed, rather than the beginning, because often the end of the hostname is more unique.
101
+
102
+ h3. Adding a timestamp
103
+
104
+ This should be pretty obvious, but the log file isn't too useful for debugging errors if you don't know what time anything happened. The first line printed by each Rails action does include a timestamp, but it's common to have other processes that aren't responding to web requests, and these are likely printing to your Rails log also (e.g. a background queue, etc).
105
+
106
+ h3. Adding a custom string
107
+
108
+ You can also add a custom string that will appear as the first column in the output, for example:
109
+
110
+ <pre>
111
+ my-custom-string igserver-7.27471 2011-10-14T15:39:17.063613-04:00 INFO Completed in 164ms (View: 116, DB: 21) | 200 OK [http://localhost/people/1]
112
+ </pre>
113
+
114
+
115
+ h2. Why not log to syslog?
116
+
117
+ It's a single point of failure, and it will become a scalability bottleneck. There are good arguments for using a common syslog server, but I prefer to just log locally on each server and combine them via post-processing.
118
+
119
+
120
+ h2. Installation
121
+
122
+ h3. Rails 2.3.x
123
+
124
+ @./script/plugin install git://github.com/pauldowman/better_logging.git@
125
+
126
+ h3. Rails 3.0
127
+
128
+ @rails plugin install git://github.com/pauldowman/better_logging.git@
129
+
130
+ h3. Rails 3.2
131
+
132
+ Add to your Gemfile:
133
+ @gem 'better_logging'@
134
+
135
+
136
+ h2. Configuration
137
+
138
+ By default it behaves differently in development mode, it doesn't log the time, process ID or hostname. If RAILS_ENV is not "development" those will be logged.
139
+
140
+ There are some options that can be set, add these lines to an initializer:
141
+
142
+ @PaulDowman::RailsPlugins::BetterLogging.verbose = false@
143
+ * This suppresses printing of the hostname, process ID and timestamp. This defaults to false in development mode, true otherwise.
144
+
145
+ @PaulDowman::RailsPlugins::BetterLogging.hostname_maxlen = 15@
146
+ * This sets the maximum number of characters of the hostname that will be printed. The beginning of the hostname is truncated, rather than the end, because often the end of the hostname is more unique than the beginning. The default is 10.
147
+
148
+ @PaulDowman::RailsPlugins::BetterLogging.custom = "my-custom-string"@
149
+ * This sets a custom string that will be printed at the beginning of the output, if desired.
150
+
151
+
152
+ h2. Viewing log files
153
+
154
+ On OS X I like to use Console.app to view log files. It can load huge files easily and it can filter based on a regular expression (e.g. you can show only lines from one particular Rails process). On *NIX I just use "less".
155
+
156
+
157
+ h2. Requirements
158
+
159
+ This has only been tested with Rails 2.2 so far. It probably won't work with Rails 1.x. If you try it with another version, please let me know and I'll update this document (and try to fix the problem).
160
+
161
+
162
+ h2. How does it work?
163
+
164
+ It works by modifying ActiveSupport::BufferedLogger (the Rails logger class).
165
+
166
+
167
+ h2. License
168
+
169
+ This is distributed under a Creative Commons "Attribution-Share Alike" license. For details see:
170
+ "http://creativecommons.org/licenses/by-sa/3.0/":http://creativecommons.org/licenses/by-sa/3.0/
171
+
172
+
173
+ h2. Bugs?
174
+
175
+ This was written by "Paul Dowman":http://pauldowman.com/.
176
+
177
+ Please let me know if you find any bugs. File a "bug report":http://github.com/pauldowman/better_logging/issues or, if you don't have a GitHub account then "contact me directly":http://pauldowman.com/contact/.
178
+
179
+ Or even better, send me a patch or GitHub pull request!
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "better_logging"
6
+ s.version = "1.0.0"
7
+ s.authors = ["Paul Dowman"]
8
+ s.email = ["paul@pauldowman.com"]
9
+ s.homepage = "https://github.com/pauldowman/better_logging"
10
+ s.summary = %q{Better logging for Rails}
11
+ s.description = %q{A Rails plugin that improves the log format, and adds an optional “Exception” parameter to the warn() and error() methods to print a stack trace automatically.}
12
+
13
+ s.rubyforge_project = "better_logging"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,8 @@
1
+ require 'active_support'
2
+ require 'better_logging/better_logging'
3
+
4
+ module BetterLogging
5
+ class Railtie < ::Rails::Railtie
6
+ ActiveSupport::BufferedLogger.send(:include, ::PaulDowman::RailsPlugins::BetterLogging)
7
+ end
8
+ end
@@ -0,0 +1,145 @@
1
+ # This module, when included into ActiveSupport::BufferedLogger, improves the
2
+ # logging format. See the README file for more info.
3
+ #
4
+ # This is distributed under a Creative Commons "Attribution-Share Alike"
5
+ # license: for details see:
6
+ # http://creativecommons.org/licenses/by-sa/3.0/
7
+ #
8
+ module PaulDowman
9
+ module RailsPlugins
10
+ module BetterLogging
11
+
12
+ LENGTH = ActiveSupport::BufferedLogger::Severity.constants.map{|c| c.to_s.length}.max
13
+
14
+ def self.included(base)
15
+ base.class_eval do
16
+ alias_method_chain :add, :extra_info
17
+ alias_method_chain :error, :exception_param
18
+ alias_method_chain :warn, :exception_param
19
+ end
20
+
21
+ # Get the length to format the output so that the pid column lines up.
22
+ # The severity levels probably won't change but this avoids hard-coding
23
+ # them anyway, just in case.
24
+ # Most of this is done with class_eval so it should only be done once
25
+ # while the class is being loaded.
26
+ if_stmts = ""
27
+ for c in ActiveSupport::BufferedLogger::Severity.constants
28
+ if_stmts += <<-EOT
29
+ if severity == #{c}
30
+ severity_name = sprintf("%1$*2$s", "#{c}", #{LENGTH * -1})
31
+ use_colour = false
32
+ if Rails.version.to_i >= 3
33
+ use_colour = true if ActiveSupport::LogSubscriber.colorize_logging
34
+ else
35
+ use_colour = true if defined?(ActiveRecord) && ActiveRecord::Base.colorize_logging
36
+ end
37
+ if use_colour
38
+ if severity == INFO
39
+ severity_name = "\033[32m" + severity_name + "\033[0m"
40
+ elsif severity == WARN
41
+ severity_name = "\033[33m" + severity_name + "\033[0m"
42
+ elsif severity == ERROR || severity == FATAL
43
+ severity_name = "\033[31m" + severity_name + "\033[0m"
44
+ end
45
+ end
46
+ return severity_name
47
+ end
48
+ EOT
49
+ end
50
+ base.class_eval <<-EOT, __FILE__, __LINE__
51
+ def self.severity_name(severity)
52
+ #{if_stmts}
53
+ return "UNKNOWN"
54
+ end
55
+ EOT
56
+ end
57
+
58
+ def self.fraction_digits=(num)
59
+ @@fraction_digits = num
60
+ end
61
+
62
+ def self.verbose=(boolean)
63
+ @@verbose = boolean
64
+ end
65
+
66
+ def self.custom=(string)
67
+ @@custom = string
68
+ @@line_prefix = format_line_prefix
69
+ end
70
+
71
+ def self.hostname_maxlen=(integer)
72
+ @@hostname_maxlen = integer
73
+ @@line_prefix = format_line_prefix
74
+ end
75
+
76
+ def self.format_line_prefix
77
+ if @@full_hostname.length < @@hostname_maxlen
78
+ hostname = @@full_hostname
79
+ else
80
+ hostname = @@full_hostname[-(@@hostname_maxlen)..-1]
81
+ end
82
+
83
+ line_prefix = sprintf("%1$*2$s", "#{hostname}.#{@@pid} ", -(7 + hostname.length))
84
+ line_prefix = "#{@@custom} #{line_prefix}" if @@custom
85
+ return line_prefix
86
+ end
87
+
88
+ def self.get_hostname
89
+ `hostname -s`.strip
90
+ end
91
+
92
+ # The following are cached as class variables for speed.
93
+
94
+ # These are configurable, put something like the following in an initializer:
95
+ # PaulDowman::RailsPlugins::BetterLogging.verbose = false
96
+ @@verbose = Rails.env != "development"
97
+ @@full_hostname = get_hostname
98
+ @@hostname_maxlen = 10
99
+ @@custom = nil
100
+ @@fraction_digits = 6
101
+
102
+
103
+ # These are not configurable
104
+ @@pid = $$
105
+ @@line_prefix = format_line_prefix
106
+
107
+
108
+ # the cached pid can be wrong after a fork(), this checks if it has changed and
109
+ # re-caches the line_prefix
110
+ def update_pid
111
+ if @@pid != $$
112
+ @@pid = $$
113
+ @@line_prefix = BetterLogging.format_line_prefix
114
+ end
115
+ end
116
+
117
+ def add_with_extra_info(severity, message = nil, progname = nil, &block)
118
+ update_pid
119
+ time = @@verbose ? "#{Time.now.iso8601(@@fraction_digits)} " : ""
120
+ message = "#{time}#{ActiveSupport::BufferedLogger.severity_name(severity)} #{message}"
121
+
122
+ # Make sure every line has the PID and hostname and custom string
123
+ # so we can use grep to isolate output from one process or server.
124
+ # gsub works even when the output contains "\n", though there's
125
+ # probably a small performance cost.
126
+ message = message.gsub(/^/, @@line_prefix) if @@verbose
127
+
128
+ add_without_extra_info(severity, message, progname, &block)
129
+ end
130
+
131
+
132
+ # add an optional second parameter to the error & warn methods to allow a stack trace:
133
+
134
+ def error_with_exception_param(message, exception = nil)
135
+ message += "\n#{exception.inspect}\n#{exception.backtrace.join("\n")}" if exception
136
+ error_without_exception_param(message)
137
+ end
138
+
139
+ def warn_with_exception_param(message, exception = nil)
140
+ message += "\n#{exception.inspect}\n#{exception.backtrace.join("\n")}" if exception
141
+ warn_without_exception_param(message)
142
+ end
143
+ end
144
+ end
145
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_logging
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Dowman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-10 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: A Rails plugin that improves the log format, and adds an optional “Exception”
15
+ parameter to the warn() and error() methods to print a stack trace automatically.
16
+ email:
17
+ - paul@pauldowman.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - README.textile
26
+ - Rakefile
27
+ - better_logging.gemspec
28
+ - lib/better_logging.rb
29
+ - lib/better_logging/better_logging.rb
30
+ homepage: https://github.com/pauldowman/better_logging
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project: better_logging
50
+ rubygems_version: 1.8.15
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: Better logging for Rails
54
+ test_files: []