logging 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 12 2007-01-14 20:03:40Z tim_pease $
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
@@ -1,6 +1,6 @@
1
- # $Id: appender.rb 12 2007-01-14 20:03:40Z tim_pease $
1
+ # $Id: appender.rb 20 2007-01-26 20:18:42Z tim_pease $
2
2
 
3
- require 'sync'
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
- @level = 0
43
- self.layout = opts[:layout] if opts.include? :layout
42
+
43
+ layout = opts[:layout] || opts['layout']
44
+ self.layout = layout unless layout.nil?
44
45
  @layout ||= ::Logging::Layouts::Basic.new
45
46
 
46
- @sync = Sync.new
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
- if Thread.current == @sync.sync_ex_locker then yield
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 2 2007-01-09 18:10:50Z tim_pease $
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 StdOut< ::Logging::Appenders::IO
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
- super('stdout', STDOUT, opts)
21
+ def initialize( name = nil, opts = {} )
22
+ name ||= 'stdout'
23
+ STDOUT.sync = true
24
+ super(name, STDOUT, opts)
23
25
  end
24
- end # class StdOut
26
+ end # class Stdout
25
27
 
26
28
  #
27
29
  # This class provides an Appender that can write to STDERR.
28
30
  #
29
- class StdErr< ::Logging::Appenders::IO
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
- super('stderr', STDERR, opts)
41
+ def initialize( name = nil, opts = {} )
42
+ name ||= 'stderr'
43
+ STDERR.sync = true
44
+ super(name, STDERR, opts)
41
45
  end
42
- end # class StdErr
46
+ end # class Stderr
43
47
 
44
48
  end # module Appenders
45
49
  end # module Logging
@@ -1,9 +1,8 @@
1
- # $Id: file.rb 2 2007-01-09 18:10:50Z tim_pease $
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 _filename_ as the
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 be
22
- # truncated before writing begins; otherwise, log messages will be appened
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( filename, opts = {} )
26
- mode = opts.delete(:truncate) ? 'w' : 'a'
27
-
28
- if ::File.exist?(filename)
29
- if not ::File.file?(filename)
30
- raise StandardError, "#{filename} is not a regular file"
31
- elsif not ::File.writable?(filename)
32
- raise StandardError, "#{filename} is not writeable"
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(filename))
35
- raise StandardError, "#{::File.dirname(filename)} is not writable"
37
+ elsif not ::File.writable?(::File.dirname(@fn))
38
+ raise StandardError, "#{::File.dirname(@fn)} is not writable"
36
39
  end
37
40
 
38
- super(filename, ::File.new(filename, mode), opts)
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
@@ -1,4 +1,4 @@
1
- # $Id: io.rb 10 2007-01-12 18:57:07Z tim_pease $
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
- sync do
45
- super(*args)
46
- @io.close unless [STDIN, STDERR, STDOUT].include?(@io)
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