formatted_rails_logger 0.1.0

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