TwP-logging 0.9.8 → 0.9.8.1
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/History.txt +16 -1
- data/Rakefile +1 -1
- data/lib/logging/appender.rb +4 -56
- data/lib/logging/appenders/buffering.rb +2 -1
- data/lib/logging/appenders/console.rb +0 -2
- data/lib/logging/appenders/rolling_file.rb +0 -2
- data/lib/logging/appenders/string_io.rb +18 -19
- data/lib/logging/appenders/syslog.rb +0 -7
- data/lib/logging/appenders.rb +120 -0
- data/lib/logging/config/configurator.rb +1 -1
- data/lib/logging/config/yaml_configurator.rb +3 -7
- data/lib/logging/layout.rb +2 -4
- data/lib/logging/layouts/basic.rb +2 -4
- data/lib/logging/layouts/parseable.rb +211 -0
- data/lib/logging/layouts/pattern.rb +6 -8
- data/lib/logging/layouts.rb +47 -0
- data/lib/logging/log_event.rb +1 -1
- data/lib/logging/logger.rb +4 -4
- data/lib/logging.rb +51 -21
- data/lib/spec/logging_helper.rb +34 -0
- data/test/appenders/test_buffered_io.rb +26 -18
- data/test/appenders/test_console.rb +10 -10
- data/test/appenders/test_email.rb +18 -19
- data/test/appenders/test_file.rb +12 -12
- data/test/appenders/test_growl.rb +11 -12
- data/test/appenders/test_io.rb +14 -15
- data/test/appenders/test_rolling_file.rb +15 -24
- data/test/appenders/test_syslog.rb +10 -10
- data/test/layouts/test_basic.rb +4 -5
- data/test/layouts/test_json.rb +112 -0
- data/test/layouts/test_pattern.rb +9 -9
- data/test/layouts/test_yaml.rb +121 -0
- data/test/setup.rb +1 -1
- data/test/test_appender.rb +0 -14
- data/test/test_log_event.rb +1 -1
- data/test/test_logging.rb +3 -3
- metadata +10 -3
- data/logging.gemspec +0 -41
data/History.txt
CHANGED
@@ -1,7 +1,22 @@
|
|
1
|
+
== 1.0.0 / 2009-04-17
|
2
|
+
|
3
|
+
2 major enhancements
|
4
|
+
- Refactored access to the appenders
|
5
|
+
- Created a much cleaner way to initialize the logging framework
|
6
|
+
3 minor enhancements
|
7
|
+
- Added a YAML layout option
|
8
|
+
- Added a JSON layout option
|
9
|
+
- Cration of an "examples" directory or logging configurations
|
10
|
+
1 bug fix
|
11
|
+
- Logging initialization happens implicitly when a logger, layout, or
|
12
|
+
appender is created
|
13
|
+
|
1
14
|
== 0.9.8 / 2009-04-11
|
2
15
|
|
3
|
-
|
16
|
+
2 minor enhancements
|
4
17
|
- Adding a to_s method to the StringIo appender's StringIO object
|
18
|
+
- Added a Spec::LoggingHelper class that will capture log messages
|
19
|
+
when using rspec style testing
|
5
20
|
|
6
21
|
== 0.9.7 / 2009-03-17
|
7
22
|
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ PROJ.version = Logging::VERSION
|
|
25
25
|
PROJ.readme_file = 'README.rdoc'
|
26
26
|
PROJ.ignore_file = '.gitignore'
|
27
27
|
|
28
|
-
PROJ.exclude << %w[^tags$]
|
28
|
+
PROJ.exclude << %w[^tags$ logging.gemspec]
|
29
29
|
PROJ.rdoc.exclude << '^data'
|
30
30
|
#PROJ.rdoc.dir = 'doc/rdoc'
|
31
31
|
#PROJ.rdoc.remote_dir = 'rdoc'
|
data/lib/logging/appender.rb
CHANGED
@@ -16,58 +16,6 @@ module Logging
|
|
16
16
|
#
|
17
17
|
class Appender
|
18
18
|
|
19
|
-
@appenders = Hash.new
|
20
|
-
|
21
|
-
class << self
|
22
|
-
|
23
|
-
# call-seq:
|
24
|
-
# Appender[name]
|
25
|
-
#
|
26
|
-
# Returns the appender instance stroed in the Appender hash under the
|
27
|
-
# key _name_, or +nil+ if no appender has been created using that name.
|
28
|
-
#
|
29
|
-
def []( name ) @appenders[name] end
|
30
|
-
|
31
|
-
# call-seq:
|
32
|
-
# Appender[name] = appender
|
33
|
-
#
|
34
|
-
# Stores the given _appender_ instance in the Appender hash under the
|
35
|
-
# key _name_.
|
36
|
-
#
|
37
|
-
def []=( name, val ) @appenders[name] = val end
|
38
|
-
|
39
|
-
# call-seq:
|
40
|
-
# Appenders.remove( name )
|
41
|
-
#
|
42
|
-
# Removes the appender instance stored in the Appender hash under the
|
43
|
-
# key _name_.
|
44
|
-
#
|
45
|
-
def remove( name ) @appenders.delete(name) end
|
46
|
-
|
47
|
-
# call-seq:
|
48
|
-
# Appender.stdout
|
49
|
-
#
|
50
|
-
# Returns an instance of the Stdout Appender. Unless the user explicitly
|
51
|
-
# creates a new Stdout Appender, the instance returned by this method
|
52
|
-
# will always be the same:
|
53
|
-
#
|
54
|
-
# Appender.stdout.object_id == Appender.stdout.object_id #=> true
|
55
|
-
#
|
56
|
-
def stdout( ) self['stdout'] || ::Logging::Appenders::Stdout.new end
|
57
|
-
|
58
|
-
# call-seq:
|
59
|
-
# Appender.stderr
|
60
|
-
#
|
61
|
-
# Returns an instance of the Stderr Appender. Unless the user explicitly
|
62
|
-
# creates a new Stderr Appender, the instance returned by this method
|
63
|
-
# will always be the same:
|
64
|
-
#
|
65
|
-
# Appender.stderr.object_id == Appender.stderr.object_id #=> true
|
66
|
-
#
|
67
|
-
def stderr( ) self['stderr'] || ::Logging::Appenders::Stderr.new end
|
68
|
-
|
69
|
-
end # class << self
|
70
|
-
|
71
19
|
attr_reader :name, :layout, :level
|
72
20
|
|
73
21
|
# call-seq:
|
@@ -85,6 +33,8 @@ class Appender
|
|
85
33
|
# :level => the level at which to log
|
86
34
|
#
|
87
35
|
def initialize( name, opts = {} )
|
36
|
+
::Logging.init unless ::Logging.const_defined? :MAX_LEVEL_LENGTH
|
37
|
+
|
88
38
|
@name = name.to_s
|
89
39
|
@closed = false
|
90
40
|
|
@@ -102,7 +52,7 @@ class Appender
|
|
102
52
|
end
|
103
53
|
end
|
104
54
|
|
105
|
-
::Logging::
|
55
|
+
::Logging::Appenders[@name] = self
|
106
56
|
end
|
107
57
|
|
108
58
|
# call-seq:
|
@@ -217,7 +167,7 @@ class Appender
|
|
217
167
|
#
|
218
168
|
def close( footer = true )
|
219
169
|
return self if @closed
|
220
|
-
::Logging::
|
170
|
+
::Logging::Appenders.remove(@name)
|
221
171
|
@closed = true
|
222
172
|
|
223
173
|
sync {flush}
|
@@ -298,6 +248,4 @@ class Appender
|
|
298
248
|
end # class Appender
|
299
249
|
end # module Logging
|
300
250
|
|
301
|
-
Logging.require_all_libs_relative_to(__FILE__, 'appenders')
|
302
|
-
|
303
251
|
# EOF
|
@@ -117,8 +117,9 @@ module Logging::Appenders
|
|
117
117
|
# options.
|
118
118
|
#
|
119
119
|
def configure_buffering( opts )
|
120
|
-
|
120
|
+
::Logging.init unless ::Logging.const_defined? :MAX_LEVEL_LENGTH
|
121
121
|
|
122
|
+
@buffer = []
|
122
123
|
self.immediate_at = opts.getopt(:immediate_at, '')
|
123
124
|
self.auto_flushing = opts.getopt(:auto_flushing, true)
|
124
125
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
|
2
|
-
require 'stringio'
|
3
|
-
|
4
2
|
module Logging::Appenders
|
5
3
|
|
6
4
|
# This class provides an Appender that can write to a StringIO instance.
|
@@ -20,24 +18,8 @@ module Logging::Appenders
|
|
20
18
|
def initialize( name, opts = {} )
|
21
19
|
@sio = StringIO.new
|
22
20
|
@sio.extend IoToS
|
21
|
+
@pos = 0
|
23
22
|
super(name, @sio, opts)
|
24
|
-
clear
|
25
|
-
end
|
26
|
-
|
27
|
-
# Read a single line of text from the internal StringIO instance. +nil+
|
28
|
-
# is returned if the StringIO buffer is empty.
|
29
|
-
#
|
30
|
-
def readline
|
31
|
-
sync {
|
32
|
-
begin
|
33
|
-
@sio.seek @pos
|
34
|
-
line = @sio.readline
|
35
|
-
@pos = @sio.tell
|
36
|
-
line
|
37
|
-
rescue EOFError
|
38
|
-
nil
|
39
|
-
end
|
40
|
-
}
|
41
23
|
end
|
42
24
|
|
43
25
|
# Clears the internal StringIO instance. All log messages are removed
|
@@ -52,6 +34,23 @@ module Logging::Appenders
|
|
52
34
|
end
|
53
35
|
alias :reset :clear
|
54
36
|
|
37
|
+
%w[read readline readlines].each do|m|
|
38
|
+
class_eval <<-CODE
|
39
|
+
def #{m}( *args )
|
40
|
+
sync {
|
41
|
+
begin
|
42
|
+
@sio.seek @pos
|
43
|
+
rv = @sio.#{m}(*args)
|
44
|
+
@pos = @sio.tell
|
45
|
+
rv
|
46
|
+
rescue EOFError
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
CODE
|
52
|
+
end
|
53
|
+
|
55
54
|
# :stopdoc:
|
56
55
|
module IoToS
|
57
56
|
def to_s
|
@@ -0,0 +1,120 @@
|
|
1
|
+
|
2
|
+
module Logging
|
3
|
+
module Appenders
|
4
|
+
|
5
|
+
# Accessor / Factory for the Email appender.
|
6
|
+
#
|
7
|
+
def email( *args )
|
8
|
+
return ::Logging::Appenders::Email if args.empty?
|
9
|
+
::Logging::Appenders::Email.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Accessor / Factory for the File appender.
|
13
|
+
#
|
14
|
+
def file( *args )
|
15
|
+
return ::Logging::Appenders::File if args.empty?
|
16
|
+
::Logging::Appenders::File.new(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Accessor / Factory for the Growl appender.
|
20
|
+
#
|
21
|
+
def growl( *args )
|
22
|
+
return ::Logging::Appenders::Growl if args.empty?
|
23
|
+
::Logging::Appenders::Growl.new(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Accessor / Factory for the IO appender.
|
27
|
+
#
|
28
|
+
def io( *args )
|
29
|
+
return ::Logging::Appenders::IO if args.empty?
|
30
|
+
::Logging::Appenders::IO.new(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Accessor / Factory for the RollingFile appender.
|
34
|
+
#
|
35
|
+
def rolling_file( *args )
|
36
|
+
return ::Logging::Appenders::RollingFile if args.empty?
|
37
|
+
::Logging::Appenders::RollingFile.new(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Accessor / Factory for the Stderr appender.
|
41
|
+
#
|
42
|
+
def stderr( *args )
|
43
|
+
if args.empty?
|
44
|
+
return self['stderr'] || ::Logging::Appenders::Stderr.new
|
45
|
+
end
|
46
|
+
::Logging::Appenders::Stderr.new(*args)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Accessor / Factory for the Stdout appender.
|
50
|
+
#
|
51
|
+
def stdout( *args )
|
52
|
+
if args.empty?
|
53
|
+
return self['stdout'] || ::Logging::Appenders::Stdout.new
|
54
|
+
end
|
55
|
+
::Logging::Appenders::Stdout.new(*args)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Accessor / Factory for the StringIo appender.
|
59
|
+
#
|
60
|
+
def string_io( *args )
|
61
|
+
return ::Logging::Appenders::StringIo if args.empty?
|
62
|
+
::Logging::Appenders::StringIo.new(*args)
|
63
|
+
end
|
64
|
+
|
65
|
+
if HAVE_SYSLOG
|
66
|
+
# Accessor / Factory for the Syslog appender.
|
67
|
+
#
|
68
|
+
def syslog( *args )
|
69
|
+
return ::Logging::Appenders::Syslog if args.empty?
|
70
|
+
::Logging::Appenders::Syslog.new(*args)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# call-seq:
|
75
|
+
# Appenders[name]
|
76
|
+
#
|
77
|
+
# Returns the appender instance stroed in the appender hash under the
|
78
|
+
# key _name_, or +nil+ if no appender has been created using that name.
|
79
|
+
#
|
80
|
+
def []( name ) @appenders[name] end
|
81
|
+
|
82
|
+
# call-seq:
|
83
|
+
# Appenders[name] = appender
|
84
|
+
#
|
85
|
+
# Stores the given _appender_ instance in the appender hash under the
|
86
|
+
# key _name_.
|
87
|
+
#
|
88
|
+
def []=( name, value ) @appenders[name] = value end
|
89
|
+
|
90
|
+
# call-seq:
|
91
|
+
# Appenders.remove( name )
|
92
|
+
#
|
93
|
+
# Removes the appender instance stored in the appender hash under the
|
94
|
+
# key _name_.
|
95
|
+
#
|
96
|
+
def remove( name ) @appenders.delete(name) end
|
97
|
+
|
98
|
+
# call-seq:
|
99
|
+
# each {|appender| block}
|
100
|
+
#
|
101
|
+
# Yield each appender to the _block_.
|
102
|
+
#
|
103
|
+
def each( &block )
|
104
|
+
@appenders.values.each(&block)
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
extend self
|
109
|
+
@appenders = Hash.new
|
110
|
+
|
111
|
+
end # module Appenders
|
112
|
+
end # module Logging
|
113
|
+
|
114
|
+
|
115
|
+
%w[buffering io console email file growl rolling_file string_io syslog].
|
116
|
+
each do |fn|
|
117
|
+
require ::Logging.libpath('logging', 'appenders', fn)
|
118
|
+
end
|
119
|
+
|
120
|
+
# EOF
|
@@ -1,8 +1,5 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
module Logging
|
5
|
-
module Config
|
2
|
+
module Logging::Config
|
6
3
|
|
7
4
|
# The YamlConfigurator class is used to configure the Logging framework
|
8
5
|
# using information found in a YAML file.
|
@@ -137,7 +134,7 @@ module Config
|
|
137
134
|
l.trace = config['trace'] if l.respond_to? :trace=
|
138
135
|
|
139
136
|
if config.has_key?('appenders')
|
140
|
-
l.appenders = config['appenders'].map {|n| ::Logging::
|
137
|
+
l.appenders = config['appenders'].map {|n| ::Logging::Appenders[n]}
|
141
138
|
end
|
142
139
|
end
|
143
140
|
end
|
@@ -189,7 +186,6 @@ module Config
|
|
189
186
|
end
|
190
187
|
|
191
188
|
end # class YamlConfigurator
|
192
|
-
end # module Config
|
193
|
-
end # module Logging
|
189
|
+
end # module Logging::Config
|
194
190
|
|
195
191
|
# EOF
|
data/lib/logging/layout.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
|
2
|
-
require 'yaml'
|
3
|
-
|
4
2
|
module Logging
|
5
3
|
|
6
4
|
# The +Layout+ class provides methods for formatting log events into a
|
@@ -30,6 +28,8 @@ class Layout
|
|
30
28
|
# then <tt>:string</tt> is used.
|
31
29
|
#
|
32
30
|
def initialize( opts = {} )
|
31
|
+
::Logging.init unless ::Logging.const_defined? :MAX_LEVEL_LENGTH
|
32
|
+
|
33
33
|
default = ::Logging.const_defined?('OBJ_FORMAT') ?
|
34
34
|
::Logging::OBJ_FORMAT : nil
|
35
35
|
|
@@ -114,6 +114,4 @@ class Layout
|
|
114
114
|
end # class Layout
|
115
115
|
end # module Logging
|
116
116
|
|
117
|
-
Logging.require_all_libs_relative_to(__FILE__, 'layouts')
|
118
|
-
|
119
117
|
# EOF
|
@@ -1,6 +1,5 @@
|
|
1
1
|
|
2
|
-
module Logging
|
3
|
-
module Layouts
|
2
|
+
module Logging::Layouts
|
4
3
|
|
5
4
|
# The +Basic+ layout class provides methods for simple formatting of log
|
6
5
|
# events. The resulting string follows the format below.
|
@@ -28,7 +27,6 @@ module Layouts
|
|
28
27
|
end
|
29
28
|
|
30
29
|
end # class Basic
|
31
|
-
end # module Layouts
|
32
|
-
end # module Logging
|
30
|
+
end # module Logging::Layouts
|
33
31
|
|
34
32
|
# EOF
|
@@ -0,0 +1,211 @@
|
|
1
|
+
|
2
|
+
module Logging::Layouts
|
3
|
+
|
4
|
+
# This layout will produce parseable log output in either JSON or YAML
|
5
|
+
# format. This makes it much easier for machines to parse log files and
|
6
|
+
# perform analysis on those logs.
|
7
|
+
#
|
8
|
+
# The information about the log event can be configured when the layout is
|
9
|
+
# created. Any or all of the following labels can be set as the _items_ to
|
10
|
+
# log:
|
11
|
+
#
|
12
|
+
# 'logger' Used to output the name of the logger that generated the
|
13
|
+
# log event.
|
14
|
+
# 'timestamp' Used to output the timestamp of the log event.
|
15
|
+
# 'level' Used to output the level of the log event.
|
16
|
+
# 'message' Used to output the application supplied message
|
17
|
+
# associated with the log event.
|
18
|
+
# 'file' Used to output the file name where the logging request
|
19
|
+
# was issued.
|
20
|
+
# 'line' Used to output the line number where the logging request
|
21
|
+
# was issued.
|
22
|
+
# 'method' Used to output the method name where the logging request
|
23
|
+
# was issued.
|
24
|
+
# 'pid' Used to output the process ID of the currently running
|
25
|
+
# program.
|
26
|
+
# 'millis' Used to output the number of milliseconds elapsed from
|
27
|
+
# the construction of the Layout until creation of the log
|
28
|
+
# event.
|
29
|
+
# 'thread_id' Used to output the object ID of the thread that generated
|
30
|
+
# the log event.
|
31
|
+
# 'thread' Used to output the name of the thread that generated the
|
32
|
+
# log event. Name can be specified using Thread.current[:name]
|
33
|
+
# notation. Output empty string if name not specified. This
|
34
|
+
# option helps to create more human readable output for
|
35
|
+
# multithread application logs.
|
36
|
+
#
|
37
|
+
# These items are supplied to the layout as an array of strings. The items
|
38
|
+
# 'file', 'line', and 'method' will only work if the Logger generating the
|
39
|
+
# events is configured to generate tracing information. If this is not the
|
40
|
+
# case these fields will always be empty.
|
41
|
+
#
|
42
|
+
# When configured to output log events in YAML format, each log message
|
43
|
+
# will be formatted as a hash in it's own YAML document. The hash keys are
|
44
|
+
# the name of the item, and the value is what you would expect it to be.
|
45
|
+
# Therefore, for the default set of times log message would appear as
|
46
|
+
# follows:
|
47
|
+
#
|
48
|
+
# ---
|
49
|
+
# timestamp: 2009-04-17 16:15:42
|
50
|
+
# level: INFO
|
51
|
+
# logger: Foo::Bar
|
52
|
+
# message: this is a log message
|
53
|
+
# ---
|
54
|
+
# timestamp: 2009-04-17 16:15:43
|
55
|
+
# level: ERROR
|
56
|
+
# logger: Foo
|
57
|
+
# message: <RuntimeError> Oooops!!
|
58
|
+
#
|
59
|
+
# The output order of the fields is not guaranteed to be the same as the
|
60
|
+
# order specified in the _items_ list. This is because Ruby hashes are not
|
61
|
+
# ordered by default (unless your running this in Ruby 1.9).
|
62
|
+
#
|
63
|
+
# When configured to output log events in JSON format, each log message
|
64
|
+
# will be formatted as an object (in the JSON sense of the work) on it's
|
65
|
+
# own line in the log output. Therefore, to parse the output you must read
|
66
|
+
# it line by line and parse the individual objects. Taking the same
|
67
|
+
# example above the JSON output would be:
|
68
|
+
#
|
69
|
+
# {"timestamp":"2009-04-17 16:15:42","level":"INFO","logger":"Foo::Bar","message":"this is a log message"}
|
70
|
+
# {"timestamp":"2009-04-17 16:15:43","level":"ERROR","logger":"Foo","message":"<RuntimeError> Oooops!!"}
|
71
|
+
#
|
72
|
+
# The output order of the fields is guaranteed to be the same as the order
|
73
|
+
# specified in the _items_ list.
|
74
|
+
#
|
75
|
+
class Parseable < ::Logging::Layout
|
76
|
+
|
77
|
+
# :stopdoc:
|
78
|
+
# Arguments to sprintf keyed to directive letters
|
79
|
+
DIRECTIVE_TABLE = {
|
80
|
+
'logger' => 'event.logger',
|
81
|
+
'timestamp' => 'Time.now.strftime(Pattern::ISO8601)',
|
82
|
+
'level' => '::Logging::LNAMES[event.level]',
|
83
|
+
'message' => 'format_obj(event.data)',
|
84
|
+
'file' => 'event.file',
|
85
|
+
'line' => 'event.line',
|
86
|
+
'method' => 'event.method',
|
87
|
+
'pid' => 'Process.pid',
|
88
|
+
'millis' => 'Integer((Time.now-@created_at)*1000)',
|
89
|
+
'thread_id' => 'Thread.current.object_id',
|
90
|
+
'thread' => 'Thread.current[:name]'
|
91
|
+
}
|
92
|
+
|
93
|
+
# call-seq:
|
94
|
+
# Pattern.create_yaml_format_methods( layout )
|
95
|
+
#
|
96
|
+
# This method will create the +format+ method in the given Parseable
|
97
|
+
# _layout_ based on the configured items for the layout instance.
|
98
|
+
#
|
99
|
+
def self.create_yaml_format_method( layout )
|
100
|
+
code = "undef :format if method_defined? :format\n"
|
101
|
+
code << "def format( event )\nstr = {\n"
|
102
|
+
|
103
|
+
code << layout.items.map {|name|
|
104
|
+
"'#{name}' => #{Parseable::DIRECTIVE_TABLE[name]}"
|
105
|
+
}.join(",\n")
|
106
|
+
code << "\n}.to_yaml\nreturn str\nend\n"
|
107
|
+
|
108
|
+
(class << layout; self end).class_eval(code, __FILE__, __LINE__)
|
109
|
+
end
|
110
|
+
|
111
|
+
# call-seq:
|
112
|
+
# Pattern.create_json_format_methods( layout )
|
113
|
+
#
|
114
|
+
# This method will create the +format+ method in the given Parseable
|
115
|
+
# _layout_ based on the configured items for the layout instance.
|
116
|
+
#
|
117
|
+
def self.create_json_format_method( layout )
|
118
|
+
code = "undef :format if method_defined? :format\n"
|
119
|
+
code << "def format( event )\n\"{"
|
120
|
+
|
121
|
+
args = []
|
122
|
+
code << layout.items.map {|name|
|
123
|
+
args << "format_as_json(#{Parseable::DIRECTIVE_TABLE[name]})"
|
124
|
+
"\\\"#{name}\\\":%s"
|
125
|
+
}.join(',')
|
126
|
+
code << "}\\n\" % [#{args.join(', ')}]\nend"
|
127
|
+
|
128
|
+
(class << layout; self end).class_eval(code, __FILE__, __LINE__)
|
129
|
+
end
|
130
|
+
# :startdoc:
|
131
|
+
|
132
|
+
# call-seq:
|
133
|
+
# Parseable.json( opts )
|
134
|
+
#
|
135
|
+
# Create a new Parseable layout that outputs log events usig JSON style
|
136
|
+
# formatting. See the initializer documentation for available options.
|
137
|
+
#
|
138
|
+
def self.json( opts = {} )
|
139
|
+
opts[:style] = 'json'
|
140
|
+
new(opts)
|
141
|
+
end
|
142
|
+
|
143
|
+
# call-seq:
|
144
|
+
# Parseable.yaml( opts )
|
145
|
+
#
|
146
|
+
# Create a new Parseable layout that outputs log events usig YAML style
|
147
|
+
# formatting. See the initializer documentation for available options.
|
148
|
+
#
|
149
|
+
def self.yaml( opts = {} )
|
150
|
+
opts[:style] = 'yaml'
|
151
|
+
new(opts)
|
152
|
+
end
|
153
|
+
|
154
|
+
# call-seq:
|
155
|
+
# Parseable.new( opts )
|
156
|
+
#
|
157
|
+
# Creates a new Parseable layout using the following options:
|
158
|
+
#
|
159
|
+
# :style => :json or :yaml
|
160
|
+
# :items => %w[timestamp level logger message]
|
161
|
+
#
|
162
|
+
def initialize( opts = {} )
|
163
|
+
super
|
164
|
+
@created_at = Time.now
|
165
|
+
@style = opts.getopt(:style, 'json').to_s.intern
|
166
|
+
self.items = opts.getopt(:items, %w[timestamp level logger message])
|
167
|
+
end
|
168
|
+
|
169
|
+
attr_reader :items
|
170
|
+
|
171
|
+
# call-seq:
|
172
|
+
# layout.items = %w[timestamp level logger message]
|
173
|
+
#
|
174
|
+
# Set the log event items that will be formatted by this layout. These
|
175
|
+
# items, and only these items, will appear in the log output.
|
176
|
+
#
|
177
|
+
def items=( ary )
|
178
|
+
@items = Array(ary).map {|name| name.to_s.downcase}
|
179
|
+
valid = DIRECTIVE_TABLE.keys
|
180
|
+
@items.each do |name|
|
181
|
+
raise ArgumentError, "unknown item - #{name.inspect}" unless valid.include? name
|
182
|
+
end
|
183
|
+
create_format_method
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
# Take the given _value_ and format it into a JSON compatible string.
|
190
|
+
#
|
191
|
+
def format_as_json( value )
|
192
|
+
case value
|
193
|
+
when String, Integer, Float; value.inspect
|
194
|
+
when nil; 'null'
|
195
|
+
else value.to_s.inspect end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Call the appropriate class level create format method based on the
|
199
|
+
# style of this parseable layout.
|
200
|
+
#
|
201
|
+
def create_format_method
|
202
|
+
case @style
|
203
|
+
when :json; Parseable.create_json_format_method(self)
|
204
|
+
when :yaml; Parseable.create_yaml_format_method(self)
|
205
|
+
else raise ArgumentError, "unknown format style '#@style'" end
|
206
|
+
end
|
207
|
+
|
208
|
+
end # class Parseable
|
209
|
+
end # module Logging::Layouts
|
210
|
+
|
211
|
+
# EOF
|