formatted_rails_logger 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in formatted_rails_logger.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,58 @@
1
+ # FormattedRailsLogger
2
+
3
+ Monkey-patches Rails BufferedLogger (the standard Rails logger) to accept a formatter just like ruby Logger does. Provides a formatter that includes timestamp and severity in logs, while taking account of Rails habit of making space in the logfile by adding newlines to the beginning of log message.
4
+
5
+ It's only 80 lines of verbose code. I'd think a bazillion people would have done this before, but I didn't see any other gems to do it simply and flexibly, sorry for any duplication.
6
+
7
+ ## How to use
8
+
9
+ Should work for both Rails2 and Rails3.
10
+
11
+ Include the formatted_rails_logger gem in your project as appropriate for your Rails version.
12
+
13
+ I don't like magic, so it doesn't actually do anything just to include the gem. Instead create an initializer, say config/initializers/logging.rb:
14
+
15
+ require 'formatted_rails_logger'
16
+
17
+ #monkey-patch BufferedLogger
18
+ FormattedRailsLogger.patch_rails
19
+
20
+ #Use the supplied formatter that includes timestamp and severity
21
+ Rails.logger.formatter = FormattedRailsLogger::Formatter.new
22
+
23
+ You can of course also write your own formatter, which is just any
24
+ object that responds to #call(severity, datetime, progname, msg) . A proc or lambda with those arguments works. See ruby [Logger](http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/classes/Logger.html) ([source](https://github.com/ruby/ruby/blob/trunk/lib/logger.rb)).
25
+
26
+ There may be some fancier way to do things with Rails3 involving config.logger, I don't know, I'm in the middle of several rails 2->3 transitions, and needed something that would work with both, and this method should.
27
+
28
+ ## What it does
29
+
30
+ It monkey patches BufferedLogger to accept a #formatter just like standard ruby Logger. Had to copy and paste the whole #add method to monkey patch it, sorry. Hopefully it won't change much in the foreseeable future.
31
+
32
+ Then it provides a Logger-style formatter object that formats the way I'd like. It's got a timestamp, I decided that miliseconds were probably useful but Logger's default of including microseconds was a ridiculous waste of screen columns. I decided [Logger](https://github.com/ruby/ruby/blob/trunk/lib/logger.rb)'s default inclusion of PID and progname weren't worth the columns, and I have no idea why Logger's default formatter includes the severity twice in two different ways, so I didn't do that.
33
+
34
+ I did more or less copy the format that my 2.3.x Rails app outputs (from WebBrick?) before Rails hijacks with the buffered logger. But with miliseconds.
35
+
36
+ I did use a regexp to look for newlines at the very beginning of a log message, and insert the timestamp/severity _after_ those newlines, so they can still serve the desired spacing function and everything looks how you'd want.
37
+
38
+ [2011-08-04 15:29:21.606] INFO Completed in 1811ms (View: 1392, DB: 204) | 200 OK [http://X.X.X.edu/catalog?q=anarchy&search_field=all_fields]
39
+
40
+
41
+ [2011-08-04 15:29:21.834] INFO Processing CatalogController#range_limit (for X.X.X.X at 2011-08-04 15:29:21) [GET]
42
+
43
+
44
+ ## Things I'm Baffled About
45
+
46
+ * Why has Rails always thought it better to exclude timestamps and severity from logfiles? Me, I need to be able to grep logfiles for "ERROR" or "FATAL" or "WARN" to see how my app's doing, and I need to be able to have timestamps to correlate human observed problems to the logs. Am I really alone here?
47
+
48
+ * Why does Rails BufferedLogger not provide the same formatter functionality a usual ruby Logger, either by sub-classing Logger, or duck-typing the formatter functionality too?
49
+
50
+ * Why does ruby 1.8.7 Time.strftime not accept an %L formatting string, even though the [documentation](http://www.ruby-doc.org/core/classes/Time.html#M000392) says it should? Did they fix this in 1.9? I don't know.
51
+
52
+ ## Things I didn't do
53
+
54
+ * No, there are no unit tests. I just hacked this out cause I was sick of Rails logging. If you wanted to help out and add em, that'd be great.
55
+
56
+ * I sort of feel like someone should actually propose this as a patch to Rails itself (at least the part where BufferedLogger can take a #formatter), but I lack the psychic energy, and it still wouldn't help me right now on current stable versions of Rails.
57
+
58
+
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
+ require "formatted_rails_logger/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "formatted_rails_logger"
7
+ s.version = FormattedRailsLogger::VERSION
8
+ s.authors = ["Jonathan Rochkind"]
9
+ s.email = ["jonathan@dnil.net"]
10
+ s.homepage = "https://github.com/jrochkind/formatted_rails_logger"
11
+ s.summary = %q{Formatting capabilities for Rails BufferedLogger}
12
+
13
+ s.rubyforge_project = "formatted_rails_logger"
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 "formatted_rails_logger/version"
2
+ require 'formatted_rails_logger/formatter'
3
+
4
+ module FormattedRailsLogger
5
+ def self.patch_rails
6
+ load File.expand_path("../formatted_rails_logger/buffered_logger_inject.rb", __FILE__)
7
+ end
8
+ end
@@ -0,0 +1,51 @@
1
+ # intentionally raise if not already defined. For some reason I feel like
2
+ # doing this rather than declaring Rails a dependency.
3
+ ActiveSupport::BufferedLogger.class
4
+
5
+ class ActiveSupport::BufferedLogger
6
+ attr_accessor :formatter
7
+ # use pure ruby class method, Rails provides ones with
8
+ # better semantics for inheritance, but they keep changing
9
+ # version to version, so nope.
10
+ class << self ; attr_accessor :default_formatter ; end
11
+
12
+
13
+
14
+
15
+ # Have to over-ride/replace BufferedLogger's usual #add
16
+ # to use formatter
17
+ def add(severity, message = nil, progname = nil, &block)
18
+ return if @level > severity
19
+ message = (message || (block && block.call) || progname).to_s
20
+
21
+ # our custom formatting
22
+ message = format_message(format_severity(severity), Time.now, progname, message)
23
+
24
+ # If a newline is necessary then create a new message ending with a newline.
25
+ # Ensures that the original message is not mutated.
26
+ message = "#{message}\n" unless message[-1] == ?\n
27
+ buffer << message
28
+ auto_flush
29
+ message
30
+ end
31
+
32
+ protected
33
+
34
+ # why does BufferedLogger not give us a way to translate from integer
35
+ # constant to actual severity lable? argh. copied from Logger
36
+ # Severity label for logging. (max 5 char)
37
+ SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL UNKNOWN)
38
+ def format_severity(severity)
39
+ SEV_LABEL[severity] || 'UNKNOWN'
40
+ end
41
+
42
+ def format_message(severity, datetime, progname, msg)
43
+ if formatter = (@formatter || self.class.default_formatter)
44
+ formatter.call(severity, datetime, progname, msg)
45
+ else
46
+ msg
47
+ end
48
+ end
49
+
50
+ end
51
+
@@ -0,0 +1,29 @@
1
+ #
2
+ # A Logger::Formatter that includes timestamp and severity, and works
3
+ # well with Rails, taking account of preceding newlines in msg for spacing.
4
+ class FormattedRailsLogger::Formatter
5
+ # Unlike Logger, not seeing a need to include the PID, the progname,
6
+ # or the Severity twice.
7
+ @@format_str = "[%s] %5s %s"
8
+ @@datetime_format = nil
9
+
10
+ def call(severity, time, progname, msg)
11
+ # see no need for micro-seconds like in Logger, milis suffices.
12
+ # No idea why documented %L and other such useful things
13
+ # do not work in strftime.
14
+ formatted_time = if @@datetime_format
15
+ time.strftime(@@datetime_format)
16
+ else
17
+ time.strftime("%Y-%m-%d %H:%M:%S.") << time.usec.to_s[0..2].rjust(3)
18
+ end
19
+
20
+ # Rails likes to log with some preceding newlines for spacing in the
21
+ # logfile. We want to preserve those when present,
22
+ # but prefix actual content with our prefix.
23
+ msg = "" if msg.nil? # regexp won't like nil, but will be okay with ""
24
+ matchData = ( /^(\n*)/.match(msg) )
25
+ matchData[0] + (@@format_str % [formatted_time, severity, matchData.post_match])
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,3 @@
1
+ module FormattedRailsLogger
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: formatted_rails_logger
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jonathan Rochkind
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-04 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email:
24
+ - jonathan@dnil.net
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - README.markdown
35
+ - Rakefile
36
+ - formatted_rails_logger.gemspec
37
+ - lib/formatted_rails_logger.rb
38
+ - lib/formatted_rails_logger/buffered_logger_inject.rb
39
+ - lib/formatted_rails_logger/formatter.rb
40
+ - lib/formatted_rails_logger/version.rb
41
+ has_rdoc: true
42
+ homepage: https://github.com/jrochkind/formatted_rails_logger
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ requirements: []
69
+
70
+ rubyforge_project: formatted_rails_logger
71
+ rubygems_version: 1.6.2
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Formatting capabilities for Rails BufferedLogger
75
+ test_files: []
76
+