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