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 +4 -0
- data/Gemfile +4 -0
- data/README.markdown +58 -0
- data/Rakefile +1 -0
- data/formatted_rails_logger.gemspec +19 -0
- data/lib/formatted_rails_logger.rb +8 -0
- data/lib/formatted_rails_logger/buffered_logger_inject.rb +51 -0
- data/lib/formatted_rails_logger/formatter.rb +29 -0
- data/lib/formatted_rails_logger/version.rb +3 -0
- metadata +76 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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,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
|
+
|
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
|
+
|