vinted-log4r 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/doc/content/contact.html +22 -0
  3. data/doc/content/contribute.html +21 -0
  4. data/doc/content/index.html +90 -0
  5. data/doc/content/license.html +56 -0
  6. data/doc/content/manual.html +449 -0
  7. data/doc/dev/README.developers +55 -0
  8. data/doc/dev/checklist +23 -0
  9. data/doc/dev/things-to-do +5 -0
  10. data/doc/images/log4r-logo.png +0 -0
  11. data/doc/images/logo2.png +0 -0
  12. data/doc/log4r.css +111 -0
  13. data/doc/rdoc-log4r.css +696 -0
  14. data/doc/templates/main.html +147 -0
  15. data/examples/README +19 -0
  16. data/examples/ancestors.rb +53 -0
  17. data/examples/chainsaw_settings.xml +7 -0
  18. data/examples/customlevels.rb +34 -0
  19. data/examples/filelog.rb +25 -0
  20. data/examples/fileroll.rb +40 -0
  21. data/examples/gmail.rb +30 -0
  22. data/examples/gmail.yaml +95 -0
  23. data/examples/log4r_yaml.yaml +0 -0
  24. data/examples/logclient.rb +25 -0
  25. data/examples/logserver.rb +18 -0
  26. data/examples/moderate.xml +29 -0
  27. data/examples/moderateconfig.rb +66 -0
  28. data/examples/myformatter.rb +23 -0
  29. data/examples/outofthebox.rb +21 -0
  30. data/examples/rdoc-gen +2 -0
  31. data/examples/rrconfig.xml +63 -0
  32. data/examples/rrsetup.rb +42 -0
  33. data/examples/simpleconfig.rb +39 -0
  34. data/examples/syslogcustom.rb +52 -0
  35. data/examples/xmlconfig.rb +25 -0
  36. data/examples/yaml.rb +30 -0
  37. data/lib/log4r.rb +17 -0
  38. data/lib/log4r/GDC.rb +41 -0
  39. data/lib/log4r/MDC.rb +59 -0
  40. data/lib/log4r/NDC.rb +86 -0
  41. data/lib/log4r/base.rb +74 -0
  42. data/lib/log4r/config.rb +9 -0
  43. data/lib/log4r/configurator.rb +224 -0
  44. data/lib/log4r/formatter/formatter.rb +105 -0
  45. data/lib/log4r/formatter/log4jxmlformatter.rb +65 -0
  46. data/lib/log4r/formatter/patternformatter.rb +145 -0
  47. data/lib/log4r/lib/drbloader.rb +52 -0
  48. data/lib/log4r/lib/xmlloader.rb +24 -0
  49. data/lib/log4r/logevent.rb +28 -0
  50. data/lib/log4r/logger.rb +216 -0
  51. data/lib/log4r/loggerfactory.rb +89 -0
  52. data/lib/log4r/logserver.rb +28 -0
  53. data/lib/log4r/outputter/consoleoutputters.rb +18 -0
  54. data/lib/log4r/outputter/datefileoutputter.rb +117 -0
  55. data/lib/log4r/outputter/emailoutputter.rb +143 -0
  56. data/lib/log4r/outputter/fileoutputter.rb +57 -0
  57. data/lib/log4r/outputter/iooutputter.rb +55 -0
  58. data/lib/log4r/outputter/outputter.rb +134 -0
  59. data/lib/log4r/outputter/outputterfactory.rb +60 -0
  60. data/lib/log4r/outputter/remoteoutputter.rb +40 -0
  61. data/lib/log4r/outputter/rollingfileoutputter.rb +234 -0
  62. data/lib/log4r/outputter/scribeoutputter.rb +37 -0
  63. data/lib/log4r/outputter/staticoutputter.rb +30 -0
  64. data/lib/log4r/outputter/syslogoutputter.rb +126 -0
  65. data/lib/log4r/outputter/udpoutputter.rb +53 -0
  66. data/lib/log4r/rdoc/GDC +14 -0
  67. data/lib/log4r/rdoc/MDC +16 -0
  68. data/lib/log4r/rdoc/NDC +41 -0
  69. data/lib/log4r/rdoc/configurator +243 -0
  70. data/lib/log4r/rdoc/emailoutputter +103 -0
  71. data/lib/log4r/rdoc/formatter +39 -0
  72. data/lib/log4r/rdoc/log4jxmlformatter +21 -0
  73. data/lib/log4r/rdoc/log4r +89 -0
  74. data/lib/log4r/rdoc/logger +175 -0
  75. data/lib/log4r/rdoc/logserver +85 -0
  76. data/lib/log4r/rdoc/outputter +108 -0
  77. data/lib/log4r/rdoc/patternformatter +128 -0
  78. data/lib/log4r/rdoc/scribeoutputter +16 -0
  79. data/lib/log4r/rdoc/syslogoutputter +29 -0
  80. data/lib/log4r/rdoc/win32eventoutputter +7 -0
  81. data/lib/log4r/rdoc/yamlconfigurator +20 -0
  82. data/lib/log4r/repository.rb +88 -0
  83. data/lib/log4r/staticlogger.rb +49 -0
  84. data/lib/log4r/version.rb +4 -0
  85. data/lib/log4r/yamlconfigurator.rb +198 -0
  86. data/tests/README +10 -0
  87. data/tests/testGDC.rb +24 -0
  88. data/tests/testMDC.rb +40 -0
  89. data/tests/testNDC.rb +25 -0
  90. data/tests/test_helper.rb +12 -0
  91. data/tests/testall.rb +6 -0
  92. data/tests/testbase.rb +48 -0
  93. data/tests/testchainsaw.rb +42 -0
  94. data/tests/testconf.xml +37 -0
  95. data/tests/testcustom.rb +30 -0
  96. data/tests/testformatter.rb +31 -0
  97. data/tests/testlogger.rb +200 -0
  98. data/tests/testoutputter.rb +146 -0
  99. data/tests/testpatternformatter.rb +76 -0
  100. data/tests/testthreads.rb +31 -0
  101. data/tests/testxmlconf.rb +48 -0
  102. data/tests/testyaml.rb +39 -0
  103. data/tests/testyaml_arrays.yaml +25 -0
  104. data/tests/testyaml_injection.yaml +22 -0
  105. metadata +193 -0
@@ -0,0 +1,55 @@
1
+ # :nodoc:
2
+ require "log4r/outputter/outputter"
3
+ require "log4r/staticlogger"
4
+
5
+ module Log4r
6
+
7
+ ##
8
+ # IO Outputter invokes print then flush on the wrapped IO
9
+ # object. If the IO stream dies, IOOutputter sets itself to OFF
10
+ # and the system continues on its merry way.
11
+ #
12
+ # To find out why an IO stream died, create a logger named 'log4r'
13
+ # and look at the output.
14
+
15
+ class IOOutputter < Outputter
16
+
17
+ # IOOutputter needs an IO object to write to.
18
+ def initialize(_name, _out, hash={})
19
+ super(_name, hash)
20
+ @out = _out
21
+ end
22
+
23
+ def closed?
24
+ @out.closed?
25
+ end
26
+
27
+ # Close the IO and sets level to OFF
28
+ def close
29
+ @out.close unless @out.nil? || closed?
30
+ @level = OFF
31
+ OutputterFactory.create_methods(self)
32
+ Logger.log_internal {"Outputter '#{@name}' closed IO and set to OFF"}
33
+ end
34
+
35
+ #######
36
+ private
37
+ #######
38
+
39
+ # perform the write
40
+ def write(data)
41
+ begin
42
+ @out.print data
43
+ @out.flush
44
+ rescue IOError => ioe # recover from this instead of crash
45
+ Logger.log_internal {"IOError in Outputter '#{@name}'!"}
46
+ Logger.log_internal {ioe}
47
+ close
48
+ rescue NameError => ne
49
+ Logger.log_internal {"Outputter '#{@name}' IO is #{@out.class}!"}
50
+ Logger.log_internal {ne}
51
+ close
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,134 @@
1
+ # :include: ../rdoc/outputter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+ # Author:: Leon Torres <leon@ugcs.caltech.edu>
7
+
8
+ require "thread"
9
+
10
+ require "log4r/outputter/outputterfactory"
11
+ require "log4r/formatter/formatter"
12
+ require "log4r/staticlogger"
13
+
14
+ require 'monitor'
15
+
16
+ module Log4r
17
+
18
+ class Outputter < Monitor
19
+ attr_reader :name, :level, :formatter
20
+ @@outputters = Hash.new
21
+
22
+ # An Outputter needs a name. RootLogger will be loaded if not already
23
+ # done. The hash arguments are as follows:
24
+ #
25
+ # [<tt>:level</tt>] Logger level. Optional, defaults to root level
26
+ # [<tt>:formatter</tt>] A Formatter. Defaults to DefaultFormatter
27
+
28
+ def initialize(_name, hash={})
29
+ super()
30
+ if _name.nil?
31
+ raise ArgumentError, "Bad arguments. Name and IO expected.", caller
32
+ end
33
+ @name = _name
34
+ validate_hash(hash)
35
+ @@outputters[@name] = self
36
+ end
37
+
38
+ # dynamically change the level
39
+ def level=(_level)
40
+ Log4rTools.validate_level(_level)
41
+ @level = _level
42
+ OutputterFactory.create_methods(self)
43
+ Logger.log_internal {"Outputter '#{@name}' level is #{LNAMES[_level]}"}
44
+ end
45
+
46
+ # Set the levels to log. All others will be ignored
47
+ def only_at(*levels)
48
+ raise ArgumentError, "Gimme some levels!", caller if levels.empty?
49
+ raise ArgumentError, "Can't log only_at ALL", caller if levels.include? ALL
50
+ levels.each {|level| Log4rTools.validate_level(level)}
51
+ @level = levels.sort.first
52
+ OutputterFactory.create_methods self, levels
53
+ Logger.log_internal {
54
+ "Outputter '#{@name}' writes only on " +
55
+ levels.collect{|l| LNAMES[l]}.join(", ")
56
+ }
57
+ end
58
+
59
+ # Dynamically change the formatter. You can just specify a Class
60
+ # object and the formatter will invoke +new+ or +instance+
61
+ # on it as appropriate.
62
+
63
+ def formatter=(_formatter)
64
+ if _formatter.kind_of?(Formatter)
65
+ @formatter = _formatter
66
+ elsif _formatter.kind_of?(Class) and _formatter <= Formatter
67
+ if _formatter.respond_to? :instance
68
+ @formatter = _formatter.instance
69
+ else
70
+ @formatter = _formatter.new
71
+ end
72
+ else
73
+ raise TypeError, "Argument was not a Formatter!", caller
74
+ end
75
+ Logger.log_internal {"Outputter '#{@name}' using #{@formatter.class}"}
76
+ end
77
+
78
+ # Call flush to force an outputter to write out any buffered
79
+ # log events. Similar to IO#flush, so use in a similar fashion.
80
+
81
+ def flush
82
+ end
83
+
84
+ #########
85
+ protected
86
+ #########
87
+
88
+ # Validates the common hash arguments. For now, that would be
89
+ # +:level+, +:formatter+ and the string equivalents
90
+ def validate_hash(hash)
91
+ # default to root level and DefaultFormatter
92
+ if hash.empty?
93
+ self.level = Logger.root.level
94
+ @formatter = DefaultFormatter.new
95
+ return
96
+ end
97
+ self.level = (hash[:level] or hash['level'] or Logger.root.level)
98
+ self.formatter = (hash[:formatter] or hash['formatter'] or DefaultFormatter.new)
99
+ end
100
+
101
+ #######
102
+ private
103
+ #######
104
+
105
+ # This method handles all log events passed to a typical Outputter.
106
+ # Overload this to change the overall behavior of an outputter. Make
107
+ # sure that the new behavior is thread safe.
108
+
109
+ def canonical_log(logevent)
110
+ synch { write(format(logevent)) }
111
+ end
112
+
113
+ # Common method to format data. All it does is call the resident
114
+ # formatter's format method. If a different formatting behavior is
115
+ # needed, then overload this method.
116
+
117
+ def format(logevent)
118
+ # @formatter is guaranteed to be DefaultFormatter if no Formatter
119
+ # was specified
120
+ @formatter.format(logevent)
121
+ end
122
+
123
+ # Abstract method to actually write the data to a destination.
124
+ # Custom outputters should overload this to specify how the
125
+ # formatted data should be written and to where.
126
+
127
+ def write(data)
128
+ end
129
+
130
+ def synch; synchronize { yield } end
131
+
132
+ end
133
+
134
+ end
@@ -0,0 +1,60 @@
1
+ # :nodoc:
2
+ # Version: $Id$
3
+
4
+ require "log4r/base"
5
+ require "log4r/repository"
6
+
7
+ require 'monitor'
8
+
9
+ module Log4r
10
+ class Outputter < Monitor
11
+
12
+ class OutputterFactory #:nodoc:
13
+ include Singleton
14
+
15
+ # handles two cases: logging above a level (no second arg specified)
16
+ # or logging a set of levels (passed into the second argument)
17
+ def self.create_methods(out, levels=nil)
18
+ Logger.root # force levels to be loaded
19
+
20
+ # first, undefine all the log levels
21
+ for mname in LNAMES
22
+ undefine_log(mname.downcase, out)
23
+ end
24
+ if not levels.nil? and levels.include? OFF
25
+ raise TypeError, "Can't log only_at OFF", caller[1..-1]
26
+ end
27
+ return out if out.level == OFF
28
+
29
+ if levels.nil? # then define the log methods for lev >= outlev
30
+ for lev in out.level...LEVELS
31
+ define_log(LNAMES[lev].downcase, lev, out)
32
+ end
33
+ else # define the logs only for assigned levels
34
+ for lev in levels
35
+ define_log(LNAMES[lev].downcase, lev, out)
36
+ end
37
+ end
38
+ return out
39
+ end
40
+
41
+ # we need to synch the actual write/format for thread safteyness
42
+ def self.define_log(mname, level, out)
43
+ return if mname == 'off' || mname == 'all'
44
+ mstr = %-
45
+ def out.#{mname}(logevent)
46
+ canonical_log(logevent)
47
+ end
48
+ -
49
+ module_eval mstr
50
+ end
51
+
52
+ def self.undefine_log(mname, out)
53
+ return if mname == 'off' || mname == 'all'
54
+ mstr = "def out.#{mname}(logevent); end"
55
+ module_eval mstr
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,40 @@
1
+ # :nodoc:
2
+ require 'log4r/lib/drbloader'
3
+ require 'log4r/outputter/outputter'
4
+
5
+ module Log4r
6
+ # See log4r/logserver.rb
7
+ class RemoteOutputter < Outputter
8
+
9
+ def initialize(_name, hash={})
10
+ super(_name, hash)
11
+ @uri = (hash[:uri] or hash['uri'])
12
+ @buffsize = (hash[:buffsize] or hash['buffsize'] or 1).to_i
13
+ @buff = []
14
+ connect
15
+ end
16
+
17
+ if HAVE_ROMP
18
+ include ROMPClient
19
+ else
20
+ def initialize(*args)
21
+ raise RuntimeError, "LogServer not supported. ROMP is required", caller
22
+ end
23
+ end
24
+
25
+
26
+ # Call flush to send any remaining LogEvents to the remote server.
27
+ def flush
28
+ synch { send_buffer }
29
+ end
30
+
31
+ private
32
+
33
+ def canonical_log(logevent)
34
+ synch {
35
+ @buff.push logevent
36
+ send_buffer if @buff.size >= @buffsize
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,234 @@
1
+
2
+ # :nodoc:
3
+ # Version:: $Id: rollingfileoutputter.rb,v 1.2 2009/09/29 18:13:13 colbygk Exp $
4
+
5
+ require "log4r/outputter/fileoutputter"
6
+ require "log4r/staticlogger"
7
+
8
+ require 'fileutils'
9
+
10
+ module Log4r
11
+
12
+ # RollingFileOutputter - subclass of FileOutputter that rolls files on size
13
+ # or time. So, given a filename of "error.log", the first log file will be "error000001.log".
14
+ # When its check condition is exceeded, it'll create and log to "error000002.log", etc.
15
+ #
16
+ # Additional hash arguments are:
17
+ #
18
+ # [<tt>:maxsize</tt>] Maximum size of the file in bytes.
19
+ # [<tt>:maxtime</tt>] Maximum age of the file in seconds.
20
+ # [<tt>:max_backups</tt>] Maxium number of prior log files to maintain. If max_backups is a positive number,
21
+ # then each time a roll happens, RollingFileOutputter will delete the oldest backup log files in excess
22
+ # of this number (if any). So, if max_backups is 10, then a maximum of 11 files will be maintained (the current
23
+ # log, plus 10 backups). If max_backups is 0, no backups will be kept. If it is negative (the default),
24
+ # there will be no limit on the number of files created. Note that the sequence numbers will continue to escalate;
25
+ # old sequence numbers are not reused.
26
+ # [<tt>:trunc</tt>] If true, deletes ALL existing log files (based on :filename) upon initialization,
27
+ # and the sequence numbering will start over at 000001. Otherwise continues logging where it left off
28
+ # last time (i.e. either to the file with the highest sequence number, or a new file, as appropriate).
29
+ class RollingFileOutputter < FileOutputter
30
+
31
+ attr_reader :current_sequence_number, :maxsize, :maxtime, :start_time, :max_backups
32
+
33
+ def initialize(_name, hash={})
34
+ super( _name, hash.merge({:create => false}) )
35
+ if hash.has_key?(:maxsize) || hash.has_key?('maxsize')
36
+ _maxsize = (hash[:maxsize] or hash['maxsize']).to_i
37
+ if _maxsize.class != Fixnum
38
+ raise TypeError, "Argument 'maxsize' must be an Fixnum", caller
39
+ end
40
+ if _maxsize == 0
41
+ raise TypeError, "Argument 'maxsize' must be > 0", caller
42
+ end
43
+ @maxsize = _maxsize
44
+ end
45
+ if hash.has_key?(:maxtime) || hash.has_key?('maxtime')
46
+ _maxtime = (hash[:maxtime] or hash['maxtime']).to_i
47
+ if _maxtime.class != Fixnum
48
+ raise TypeError, "Argument 'maxtime' must be an Fixnum", caller
49
+ end
50
+ if _maxtime == 0
51
+ raise TypeError, "Argument 'maxtime' must be > 0", caller
52
+ end
53
+ @maxtime = _maxtime
54
+ end
55
+ if hash.has_key?(:max_backups) || hash.has_key?('max_backups')
56
+ _max_backups = (hash[:max_backups] or hash['max_backups']).to_i
57
+ if _max_backups.class != Fixnum
58
+ raise TypeError, "Argument 'max_backups' must be an Fixnum", caller
59
+ end
60
+ @max_backups = _max_backups
61
+ else
62
+ @max_backups = -1
63
+ end
64
+ # @filename starts out as the file (including path) provided by the user, e.g. "\usr\logs\error.log".
65
+ # It will get assigned the current log file (including sequence number)
66
+ # @log_dir is the directory in which we'll log, e.g. "\usr\logs"
67
+ # @file_extension is the file's extension (if any) including any period, e.g. ".log"
68
+ # @core_file_name is the part of the log file's name, sans sequence digits or extension, e.g. "error"
69
+ @log_dir = File.dirname(@filename)
70
+ @file_extension = File.extname(@filename) # Note: the File API doc comment states that this doesn't include the period, but its examples and behavior do include it. We'll depend on the latter.
71
+ @core_file_name = File.basename(@filename, @file_extension)
72
+ if (@trunc)
73
+ purge_log_files(0)
74
+ end
75
+ @current_sequence_number = get_current_sequence_number()
76
+ makeNewFilename
77
+ # Now @filename points to a properly sequenced filename, which may or may not yet exist.
78
+ open_log_file('a')
79
+
80
+ # Note: it's possible we're already in excess of our time or size constraint for the current file;
81
+ # no worries -- if a new file needs to be started, it'll happen during the write() call.
82
+ end
83
+
84
+ #######
85
+ private
86
+ #######
87
+
88
+ # Delete all but the latest number_to_keep log files.
89
+ def purge_log_files(number_to_keep)
90
+ Dir.chdir(@log_dir) do
91
+ # Make a list of the log files to delete. Start with all of the matching log files...
92
+ glob = "#{@core_file_name}[0-9][0-9][0-9][0-9][0-9][0-9]#{@file_extension}"
93
+ files = Dir.glob(glob)
94
+
95
+ # ... if there are fewer than our threshold, just return...
96
+ if (files.size() <= number_to_keep )
97
+ # Logger.log_internal {"No log files need purging."}
98
+ return
99
+ end
100
+ # ...then remove those that we want to keep (i.e. the most recent #{number_to_keep} files).
101
+ files.sort!().slice!(-number_to_keep, number_to_keep)
102
+
103
+ # Delete the files. We use force (rm_f), so in case any files can't be deleted (e.g. someone's got one
104
+ # open in an editor), we'll swallow the error and keep going.
105
+ FileUtils.rm_f(files)
106
+ Logger.log_internal { "Purged #{files.length} log files: #{files}" }
107
+ end
108
+ end
109
+
110
+ # Get the highest existing log file sequence number, or 1 if there are no existing log files.
111
+ def get_current_sequence_number()
112
+ max_seq_no = 0
113
+ Dir.foreach(@log_dir) do |child|
114
+ if child =~ /^#{@core_file_name}(\d+)#{@file_extension}$/
115
+ seq_no = $1.to_i
116
+ if (seq_no > max_seq_no)
117
+ max_seq_no = seq_no
118
+ end
119
+ end
120
+ end
121
+ return [max_seq_no, 1].max
122
+ end
123
+
124
+ # perform the write
125
+ def write(data)
126
+ # we have to keep track of the file size ourselves - File.size doesn't
127
+ # seem to report the correct size when the size changes rapidly
128
+ @datasize += data.size + 1 # the 1 is for newline
129
+ roll if requiresRoll
130
+ super
131
+ end
132
+
133
+ # Constructs a new filename from the @current_sequence_number, @core_file_name, and @file_extension,
134
+ # and assigns it to @filename
135
+ def makeNewFilename
136
+ # note use of hard coded 6 digit sequence width - is this enough files?
137
+ padded_seq_no = "0" * (6 - @current_sequence_number.to_s.length) + @current_sequence_number.to_s
138
+ newbase = "#{@core_file_name}#{padded_seq_no}#{@file_extension}"
139
+ @filename = File.join(@log_dir, newbase)
140
+ end
141
+
142
+ # Open @filename with the given mode:
143
+ # 'a' - appends to the end of the file if it exists; otherwise creates it.
144
+ # 'w' - truncates the file to zero length if it exists, otherwise creates it.
145
+ # Re-initializes @datasize and @startime appropriately.
146
+ def open_log_file(mode)
147
+ # It appears that if a file has been recently deleted then recreated, calls like
148
+ # File.ctime can return the erstwhile creation time. File.size? can similarly return
149
+ # old information. So instead of simply doing ctime and size checks after File.new, we
150
+ # do slightly more complicated checks beforehand:
151
+ if (mode == 'w' || !File.exists?(@filename))
152
+ @start_time = Time.now()
153
+ @datasize = 0
154
+ else
155
+ @start_time = File.ctime(@filename)
156
+ @datasize = File.size?(@filename) || 0 # File.size? returns nil even if the file exists but is empty; we convert it to 0.
157
+ end
158
+ @out = File.new(@filename, mode)
159
+ Logger.log_internal {"File #{@filename} opened with mode #{mode}"}
160
+ end
161
+
162
+ # does the file require a roll?
163
+ def requiresRoll
164
+ if !@maxsize.nil? && @datasize > @maxsize
165
+ Logger.log_internal { "Rolling because #{@filename} (#{@datasize} bytes) has exceded the maxsize limit (#{@maxsize} bytes)." }
166
+ return true
167
+ end
168
+ if !@maxtime.nil? && (Time.now - @start_time) > @maxtime
169
+ Logger.log_internal { "Rolling because #{@filename} (created: #{@start_time}) has exceded the maxtime age (#{@maxtime} seconds)." }
170
+ return true
171
+ end
172
+ false
173
+ end
174
+
175
+ # roll the file
176
+ def roll
177
+ begin
178
+ # If @baseFilename == @filename, then this method is about to
179
+ # try to close out a file that is not actually opened because
180
+ # fileoutputter has been called with the parameter roll=true
181
+ # TODO: Is this check valid any more? I suspect not. Am commenting out...:
182
+ #if ( @baseFilename != @filename ) then
183
+ @out.close
184
+ #end
185
+ rescue
186
+ Logger.log_internal {
187
+ "RollingFileOutputter '#{@name}' could not close #{@filename}"
188
+ }
189
+ end
190
+
191
+ # Prepare the next file. (Note: if max_backups is zero, we can skip this; we'll
192
+ # just overwrite the existing log file)
193
+ if (@max_backups != 0)
194
+ @current_sequence_number += 1
195
+ makeNewFilename
196
+ end
197
+
198
+ open_log_file('w')
199
+
200
+ # purge any excess log files (unless max_backups is negative, which means don't purge).
201
+ if (@max_backups >= 0)
202
+ purge_log_files(@max_backups + 1)
203
+ end
204
+
205
+ end
206
+
207
+ end
208
+
209
+ end
210
+
211
+ # this can be found in examples/fileroll.rb as well
212
+ if __FILE__ == $0
213
+ require 'log4r'
214
+ include Log4r
215
+
216
+
217
+ timeLog = Logger.new 'WbExplorer'
218
+ timeLog.outputters = RollingFileOutputter.new("WbExplorer", { "filename" => "TestTime.log", "maxtime" => 10, "trunc" => true })
219
+ timeLog.level = DEBUG
220
+
221
+ 100.times { |t|
222
+ timeLog.info "blah #{t}"
223
+ sleep(1.0)
224
+ }
225
+
226
+ sizeLog = Logger.new 'WbExplorer'
227
+ sizeLog.outputters = RollingFileOutputter.new("WbExplorer", { "filename" => "TestSize.log", "maxsize" => 16000, "trunc" => true })
228
+ sizeLog.level = DEBUG
229
+
230
+ 10000.times { |t|
231
+ sizeLog.info "blah #{t}"
232
+ }
233
+
234
+ end