logging 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/logging.yaml +63 -0
- data/lib/logging.rb +23 -2
- data/lib/logging/appender.rb +9 -7
- data/lib/logging/appenders/console.rb +13 -9
- data/lib/logging/appenders/file.rb +25 -23
- data/lib/logging/appenders/io.rb +4 -8
- data/lib/logging/appenders/rolling_file.rb +189 -0
- data/lib/logging/config/yaml_configurator.rb +190 -0
- data/lib/logging/layout.rb +10 -8
- data/lib/logging/layouts/pattern.rb +7 -9
- data/lib/logging/logger.rb +37 -7
- data/test/appenders/test_console.rb +7 -7
- data/test/appenders/test_file.rb +20 -10
- data/test/appenders/test_rolling_file.rb +141 -0
- data/test/config/test_yaml_configurator.rb +47 -0
- data/test/layouts/test_pattern.rb +2 -2
- data/test/setup.rb +3 -1
- data/test/test_layout.rb +7 -7
- data/test/test_log_event.rb +3 -3
- data/test/test_logger.rb +37 -1
- data/test/test_logging.rb +82 -2
- data/test/test_root_logger.rb +17 -1
- metadata +7 -2
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
purpose : TestA
|
3
|
+
description: This is the 1st YAML doc
|
4
|
+
say : Hi
|
5
|
+
|
6
|
+
---
|
7
|
+
# *** YAML2LOGGING ***
|
8
|
+
logging_config:
|
9
|
+
# define all pre config ...
|
10
|
+
pre_config:
|
11
|
+
define_levels:
|
12
|
+
- DEB
|
13
|
+
- INF
|
14
|
+
- PRT
|
15
|
+
- WRN
|
16
|
+
- ERR
|
17
|
+
- FAT
|
18
|
+
format_as : inspect
|
19
|
+
root:
|
20
|
+
level : WRN
|
21
|
+
|
22
|
+
# define all loggers ...
|
23
|
+
loggers:
|
24
|
+
- name : mylogger
|
25
|
+
level : DEB
|
26
|
+
additive : false
|
27
|
+
trace : false
|
28
|
+
appenders:
|
29
|
+
- stderr
|
30
|
+
- logfile
|
31
|
+
|
32
|
+
- name : yourlogger
|
33
|
+
level : INF
|
34
|
+
appenders:
|
35
|
+
- stderr
|
36
|
+
- logfile
|
37
|
+
|
38
|
+
# define all appenders (incl. layouts)
|
39
|
+
appenders:
|
40
|
+
- type : Stderr
|
41
|
+
name : stderr
|
42
|
+
level : DEB
|
43
|
+
layout:
|
44
|
+
type : Basic
|
45
|
+
format_as : string
|
46
|
+
|
47
|
+
- type : File
|
48
|
+
name : logfile
|
49
|
+
level : DEB
|
50
|
+
filename : 'temp.log'
|
51
|
+
truncate : true
|
52
|
+
layout:
|
53
|
+
type : Pattern
|
54
|
+
date_method : to_s
|
55
|
+
pattern : '[%d] %l %c : %m\n'
|
56
|
+
|
57
|
+
---
|
58
|
+
purpose : TestB
|
59
|
+
description: This is the last YAML doc
|
60
|
+
say : Bye
|
61
|
+
|
62
|
+
|
63
|
+
# EOF
|
data/lib/logging.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
-
# $Id: logging.rb
|
1
|
+
# $Id: logging.rb 22 2007-01-29 16:20:54Z tim_pease $
|
2
2
|
|
3
3
|
require 'logging/repository'
|
4
4
|
|
5
5
|
# require all appenders
|
6
6
|
require 'logging/appenders/console'
|
7
7
|
require 'logging/appenders/file'
|
8
|
+
require 'logging/appenders/rolling_file'
|
8
9
|
require 'logging/appenders/static_appender'
|
9
10
|
|
10
11
|
# require all layouts
|
11
12
|
require 'logging/layouts/basic'
|
12
13
|
require 'logging/layouts/pattern'
|
13
14
|
|
15
|
+
# require all configurators
|
16
|
+
require 'logging/config/yaml_configurator'
|
17
|
+
|
14
18
|
|
15
19
|
#
|
16
20
|
#
|
@@ -21,6 +25,21 @@ module Logging
|
|
21
25
|
LNAMES = {} # :nodoc:
|
22
26
|
|
23
27
|
class << self
|
28
|
+
#
|
29
|
+
# call-seq:
|
30
|
+
# Logging.configure( filename )
|
31
|
+
#
|
32
|
+
# Configures the Logging framework using the configuration information
|
33
|
+
# found in the given file. The file extension should be either '.yaml'
|
34
|
+
# or '.yml' (XML configuration is not yet supported).
|
35
|
+
#
|
36
|
+
def configure( filename )
|
37
|
+
case File.extname(filename)
|
38
|
+
when '.yaml', '.yml':
|
39
|
+
::Logging::Config::YamlConfigurator.load(filename)
|
40
|
+
else raise ArgumentError, 'unknown configuration file format' end
|
41
|
+
end
|
42
|
+
|
24
43
|
#
|
25
44
|
# call-seq:
|
26
45
|
# define_levels( levels )
|
@@ -99,6 +118,8 @@ module Logging
|
|
99
118
|
# +:inspect+, +:yaml+ is passed to this method.
|
100
119
|
#
|
101
120
|
def format_as( f )
|
121
|
+
f = f.intern if f.instance_of? String
|
122
|
+
|
102
123
|
unless [:string, :inspect, :yaml].include? f
|
103
124
|
raise ArgumentError, "unknown object format '#{f}'"
|
104
125
|
end
|
@@ -119,7 +140,7 @@ module Logging
|
|
119
140
|
case l
|
120
141
|
when 'all': 0
|
121
142
|
when 'off': LEVELS.length
|
122
|
-
else LEVELS[l] end
|
143
|
+
else begin; Integer(l); rescue ArgumentError; LEVELS[l] end end
|
123
144
|
end
|
124
145
|
# :startdoc:
|
125
146
|
end
|
data/lib/logging/appender.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# $Id: appender.rb
|
1
|
+
# $Id: appender.rb 20 2007-01-26 20:18:42Z tim_pease $
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'thread'
|
4
4
|
require 'logging'
|
5
5
|
require 'logging/logger'
|
6
6
|
require 'logging/layout'
|
@@ -39,11 +39,14 @@ module Logging
|
|
39
39
|
def initialize( name, opts = {} )
|
40
40
|
@name = name.to_s
|
41
41
|
@closed = false
|
42
|
-
|
43
|
-
|
42
|
+
|
43
|
+
layout = opts[:layout] || opts['layout']
|
44
|
+
self.layout = layout unless layout.nil?
|
44
45
|
@layout ||= ::Logging::Layouts::Basic.new
|
45
46
|
|
46
|
-
|
47
|
+
self.level = opts[:level] || opts['level']
|
48
|
+
|
49
|
+
@mutex = Mutex.new
|
47
50
|
sync {write(@layout.header)}
|
48
51
|
|
49
52
|
::Logging::Appender[@name] = self
|
@@ -195,8 +198,7 @@ module Logging
|
|
195
198
|
# can call +sync+ multiple times without hanging the thread.
|
196
199
|
#
|
197
200
|
def sync
|
198
|
-
|
199
|
-
else @sync.synchronize(:EX) {yield} end
|
201
|
+
@mutex.synchronize {yield}
|
200
202
|
end
|
201
203
|
|
202
204
|
end # class Appender
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: console.rb
|
1
|
+
# $Id: console.rb 17 2007-01-20 18:47:43Z tim_pease $
|
2
2
|
|
3
3
|
require 'logging/appenders/io'
|
4
4
|
|
@@ -8,7 +8,7 @@ module Appenders
|
|
8
8
|
#
|
9
9
|
# This class provides an Appender that can write to STDOUT.
|
10
10
|
#
|
11
|
-
class
|
11
|
+
class Stdout< ::Logging::Appenders::IO
|
12
12
|
|
13
13
|
#
|
14
14
|
# call-seq:
|
@@ -18,15 +18,17 @@ module Appenders
|
|
18
18
|
# Creates a new StdOut Appender. The name 'stdout' will always be used for
|
19
19
|
# this appender.
|
20
20
|
#
|
21
|
-
def initialize( opts = {} )
|
22
|
-
|
21
|
+
def initialize( name = nil, opts = {} )
|
22
|
+
name ||= 'stdout'
|
23
|
+
STDOUT.sync = true
|
24
|
+
super(name, STDOUT, opts)
|
23
25
|
end
|
24
|
-
end # class
|
26
|
+
end # class Stdout
|
25
27
|
|
26
28
|
#
|
27
29
|
# This class provides an Appender that can write to STDERR.
|
28
30
|
#
|
29
|
-
class
|
31
|
+
class Stderr< ::Logging::Appenders::IO
|
30
32
|
|
31
33
|
#
|
32
34
|
# call-seq:
|
@@ -36,10 +38,12 @@ module Appenders
|
|
36
38
|
# Creates a new StdErr Appender. The name 'stderr' will always be used for
|
37
39
|
# this appender.
|
38
40
|
#
|
39
|
-
def initialize( opts = {} )
|
40
|
-
|
41
|
+
def initialize( name = nil, opts = {} )
|
42
|
+
name ||= 'stderr'
|
43
|
+
STDERR.sync = true
|
44
|
+
super(name, STDERR, opts)
|
41
45
|
end
|
42
|
-
end # class
|
46
|
+
end # class Stderr
|
43
47
|
|
44
48
|
end # module Appenders
|
45
49
|
end # module Logging
|
@@ -1,9 +1,8 @@
|
|
1
|
-
# $Id: file.rb
|
1
|
+
# $Id: file.rb 22 2007-01-29 16:20:54Z tim_pease $
|
2
2
|
|
3
3
|
require 'logging/appenders/io'
|
4
4
|
|
5
|
-
module Logging
|
6
|
-
module Appenders
|
5
|
+
module Logging::Appenders
|
7
6
|
|
8
7
|
#
|
9
8
|
# This class provides an Appender that can write to a File.
|
@@ -12,34 +11,37 @@ module Appenders
|
|
12
11
|
|
13
12
|
#
|
14
13
|
# call-seq:
|
15
|
-
# File.new( filename )
|
16
|
-
# File.new( filename, :truncate => true )
|
17
|
-
# File.new( filename, :layout => layout )
|
14
|
+
# File.new( name, :filename => 'file' )
|
15
|
+
# File.new( name, :filename => 'file', :truncate => true )
|
16
|
+
# File.new( name, :filename => 'file', :layout => layout )
|
18
17
|
#
|
19
|
-
# Creates a new File Appender that will use the given
|
18
|
+
# Creates a new File Appender that will use the given filename as the
|
20
19
|
# logging destination. If the file does not already exist it will be
|
21
|
-
# created. If the :truncate option is set to +true+ then the file will
|
22
|
-
# truncated before writing begins; otherwise, log messages will be
|
23
|
-
# to the file.
|
20
|
+
# created. If the :truncate option is set to +true+ then the file will
|
21
|
+
# be truncated before writing begins; otherwise, log messages will be
|
22
|
+
# appened to the file.
|
24
23
|
#
|
25
|
-
def initialize(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
def initialize( name, opts = {} )
|
25
|
+
@fn = opts.delete(:filename) || opts.delete('filename')
|
26
|
+
raise ArgumentError, 'no filename was given' if @fn.nil?
|
27
|
+
|
28
|
+
mode = opts.delete(:truncate) || opts.delete('truncate')
|
29
|
+
mode = mode ? 'w' : 'a'
|
30
|
+
|
31
|
+
if ::File.exist?(@fn)
|
32
|
+
if not ::File.file?(@fn)
|
33
|
+
raise StandardError, "#{@fn} is not a regular file"
|
34
|
+
elsif not ::File.writable?(@fn)
|
35
|
+
raise StandardError, "#{@fn} is not writeable"
|
33
36
|
end
|
34
|
-
elsif not ::File.writable?(::File.dirname(
|
35
|
-
raise StandardError, "#{::File.dirname(
|
37
|
+
elsif not ::File.writable?(::File.dirname(@fn))
|
38
|
+
raise StandardError, "#{::File.dirname(@fn)} is not writable"
|
36
39
|
end
|
37
40
|
|
38
|
-
super(
|
41
|
+
super(name, ::File.new(@fn, mode), opts)
|
39
42
|
end
|
40
43
|
|
41
44
|
end # class FileAppender
|
42
|
-
end # module Appenders
|
43
|
-
end # module Logging
|
45
|
+
end # module Logging::Appenders
|
44
46
|
|
45
47
|
# EOF
|
data/lib/logging/appenders/io.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: io.rb
|
1
|
+
# $Id: io.rb 21 2007-01-26 20:23:32Z tim_pease $
|
2
2
|
|
3
3
|
require 'logging/appender'
|
4
4
|
|
@@ -25,8 +25,6 @@ module Appenders
|
|
25
25
|
end
|
26
26
|
|
27
27
|
@io = io
|
28
|
-
@io.sync = true
|
29
|
-
|
30
28
|
super(name, opts)
|
31
29
|
end
|
32
30
|
|
@@ -41,11 +39,9 @@ module Appenders
|
|
41
39
|
#
|
42
40
|
def close( *args )
|
43
41
|
return self if @io.nil?
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@io = nil
|
48
|
-
end
|
42
|
+
super(*args)
|
43
|
+
io, @io = @io, nil
|
44
|
+
io.close unless [STDIN, STDERR, STDOUT].include?(io)
|
49
45
|
self
|
50
46
|
end
|
51
47
|
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# $Id: rolling_file.rb 22 2007-01-29 16:20:54Z tim_pease $
|
2
|
+
|
3
|
+
require 'logging/appenders/file'
|
4
|
+
|
5
|
+
module Logging::Appenders
|
6
|
+
|
7
|
+
#
|
8
|
+
# An appender that writes to a file and ensures that the file size or age
|
9
|
+
# never exceeds some user specified level.
|
10
|
+
#
|
11
|
+
# The goal of this class is to write log messages to a file. When the file
|
12
|
+
# age or size exceeds a given limit then the log file is closed, the name
|
13
|
+
# is changed to indicate it is an older log file, and a new log file is
|
14
|
+
# created.
|
15
|
+
#
|
16
|
+
# The name of the log file is changed by inserting the age of the log file
|
17
|
+
# (as a single number) between the log file name and the extension. If the
|
18
|
+
# file has no extension then the number is appended to the filename. Here
|
19
|
+
# is a simple example:
|
20
|
+
#
|
21
|
+
# /var/log/ruby.log => /var/log/ruby.1.log
|
22
|
+
#
|
23
|
+
# New log messages will be appended to a newly opened log file of the same
|
24
|
+
# name (<tt>/var/log/ruby.log</tt> in our example above). The age number for
|
25
|
+
# all older log files is incremented when the log file is rolled. The number
|
26
|
+
# of older log files to keep can be given, otherwise all the log files are
|
27
|
+
# kept.
|
28
|
+
#
|
29
|
+
# The actual process of rolling all the log file names can be expensive if
|
30
|
+
# there are many, many older log files to process.
|
31
|
+
#
|
32
|
+
class RollingFile < ::Logging::Appenders::File
|
33
|
+
|
34
|
+
#
|
35
|
+
# call-seq:
|
36
|
+
# RollingFile.new( name, opts )
|
37
|
+
#
|
38
|
+
# Creates a new Rolling File Appender. The _name_ is the unique Appender
|
39
|
+
# name used to retrieve this appender from the Appender hash. The only
|
40
|
+
# required option is the filename to use for creating log files.
|
41
|
+
#
|
42
|
+
# [:filename] The base filename to use when constructing new log
|
43
|
+
# filenames.
|
44
|
+
#
|
45
|
+
# The following options are optional:
|
46
|
+
#
|
47
|
+
# [:layout] The Layout that will be used by this appender. The Basic
|
48
|
+
# layout will be used if none is given.
|
49
|
+
# [:truncate] When set to true any existing log files will be rolled
|
50
|
+
# immediately and a new, empty log file will be created.
|
51
|
+
# [:max_size] The maximum allowed size (in bytes) of a log file before
|
52
|
+
# it is rolled.
|
53
|
+
# [:max_age] The maximum age (in seconds) of a log file before it is
|
54
|
+
# rolled.
|
55
|
+
# [:keep] The number of rolled log files to keep.
|
56
|
+
#
|
57
|
+
def initialize( name, opts = {} )
|
58
|
+
# raise an error if a filename was not given
|
59
|
+
@fn = opts[:filename] || opts['filename']
|
60
|
+
raise ArgumentError, 'no filename was given' if @fn.nil?
|
61
|
+
|
62
|
+
# grab the information we need to properly roll files
|
63
|
+
ext = ::File.extname(@fn)
|
64
|
+
bn = ::File.join(::File.dirname(@fn), ::File.basename(@fn, ext))
|
65
|
+
@rgxp = %r/\.(\d+)#{Regexp.escape(ext)}\z/
|
66
|
+
@glob = "#{bn}.*#{ext}"
|
67
|
+
@logname_fmt = "#{bn}.%d#{ext}"
|
68
|
+
|
69
|
+
# if the truncate flag was set to true, then roll
|
70
|
+
roll_now = opts.delete(:truncate) || opts.delete('truncate')
|
71
|
+
roll_files if roll_now
|
72
|
+
|
73
|
+
# grab out our options
|
74
|
+
@keep = opts.delete(:keep) || opts.delete('keep')
|
75
|
+
@max_size = opts.delete(:max_size) || opts.delete('max_size')
|
76
|
+
@max_age = opts.delete(:max_age) || opts.delete('max_age')
|
77
|
+
|
78
|
+
@keep = Integer(@keep) unless @keep.nil?
|
79
|
+
@max_size = Integer(@max_size) unless @max_size.nil?
|
80
|
+
unless @max_age.nil?
|
81
|
+
@max_age = Integer(@max_age)
|
82
|
+
@start_time = Time.now
|
83
|
+
end
|
84
|
+
|
85
|
+
@file_size = (::File.exist?(@fn) ? ::File.size(@fn) : 0)
|
86
|
+
super(name, opts)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
#
|
91
|
+
# call-seq:
|
92
|
+
# write( str )
|
93
|
+
#
|
94
|
+
# Write the given string to the log file. The log file will be rolled
|
95
|
+
# if the maximum file size is exceeded or if the file is older than the
|
96
|
+
# maximum age.
|
97
|
+
#
|
98
|
+
def write( str )
|
99
|
+
super
|
100
|
+
@file_size += str.size # keep track of the size internally since
|
101
|
+
roll if roll_required? # the file IO stream is probably not being
|
102
|
+
end # flushed to disk immediately
|
103
|
+
|
104
|
+
#
|
105
|
+
# call-seq:
|
106
|
+
# roll
|
107
|
+
#
|
108
|
+
# Close the currently open log file, roll all the log files, and open a
|
109
|
+
# new log file.
|
110
|
+
#
|
111
|
+
def roll
|
112
|
+
begin; @io.close; rescue; end
|
113
|
+
roll_files
|
114
|
+
@io = ::File.new(@fn, 'w')
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# call-seq:
|
119
|
+
# roll_required?
|
120
|
+
#
|
121
|
+
# Returns +true+ if the log file needs to be rolled.
|
122
|
+
#
|
123
|
+
def roll_required?
|
124
|
+
# check if max size has been exceeded
|
125
|
+
if @max_size and @file_size > @max_size
|
126
|
+
@file_size = 0
|
127
|
+
return true
|
128
|
+
end
|
129
|
+
|
130
|
+
# check if max age has been exceeded
|
131
|
+
if @max_age and (Time.now - @start_time) > @max_age
|
132
|
+
@start_time = Time.now
|
133
|
+
return true
|
134
|
+
end
|
135
|
+
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# call-seq:
|
141
|
+
# roll_files
|
142
|
+
#
|
143
|
+
# Roll the log files. This is accomplished by renaming the log files
|
144
|
+
# starting with the oldest and working towards the youngest.
|
145
|
+
#
|
146
|
+
# test.10.log => deleted (we are only keeping 10)
|
147
|
+
# test.9.log => test.10.log
|
148
|
+
# test.8.log => test.9.log
|
149
|
+
# ...
|
150
|
+
# test.1.log => test.2.log
|
151
|
+
#
|
152
|
+
# Lastly the current log file is rolled to a numbered log file.
|
153
|
+
#
|
154
|
+
# test.log => test.1.log
|
155
|
+
#
|
156
|
+
# This method leaves no <tt>test.log</tt> file when it is done. This
|
157
|
+
# file will be created elsewhere.
|
158
|
+
#
|
159
|
+
def roll_files
|
160
|
+
return unless ::File.exist?(@fn)
|
161
|
+
|
162
|
+
files = Dir.glob(@glob).find_all {|fn| @rgxp =~ fn}
|
163
|
+
unless files.empty?
|
164
|
+
# sort the files in revese order based on their count number
|
165
|
+
files = files.sort do |a,b|
|
166
|
+
a = Integer(@rgxp.match(a)[1])
|
167
|
+
b = Integer(@rgxp.match(b)[1])
|
168
|
+
b <=> a
|
169
|
+
end
|
170
|
+
|
171
|
+
# for each file, roll its count number one higher
|
172
|
+
files.each do |fn|
|
173
|
+
cnt = Integer(@rgxp.match(fn)[1])
|
174
|
+
if @keep and cnt >= @keep
|
175
|
+
::File.delete fn
|
176
|
+
next
|
177
|
+
end
|
178
|
+
::File.rename fn, sprintf(@logname_fmt, cnt+1)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# finally reanme the base log file
|
183
|
+
::File.rename(@fn, sprintf(@logname_fmt, 1))
|
184
|
+
end
|
185
|
+
|
186
|
+
end # class RollingFile
|
187
|
+
end # module Logging::Appenders
|
188
|
+
|
189
|
+
# EOF
|