mtn_log4r 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +15 -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/GDC.rb +41 -0
  38. data/lib/log4r/MDC.rb +59 -0
  39. data/lib/log4r/NDC.rb +86 -0
  40. data/lib/log4r/base.rb +74 -0
  41. data/lib/log4r/config.rb +9 -0
  42. data/lib/log4r/configurator.rb +224 -0
  43. data/lib/log4r/formatter/formatter.rb +109 -0
  44. data/lib/log4r/formatter/log4jxmlformatter.rb +65 -0
  45. data/lib/log4r/formatter/patternformatter.rb +145 -0
  46. data/lib/log4r/lib/drbloader.rb +52 -0
  47. data/lib/log4r/lib/xmlloader.rb +24 -0
  48. data/lib/log4r/logevent.rb +28 -0
  49. data/lib/log4r/logger.rb +199 -0
  50. data/lib/log4r/loggerfactory.rb +89 -0
  51. data/lib/log4r/logserver.rb +28 -0
  52. data/lib/log4r/outputter/consoleoutputters.rb +18 -0
  53. data/lib/log4r/outputter/datefileoutputter.rb +117 -0
  54. data/lib/log4r/outputter/emailoutputter.rb +143 -0
  55. data/lib/log4r/outputter/fileoutputter.rb +56 -0
  56. data/lib/log4r/outputter/iooutputter.rb +55 -0
  57. data/lib/log4r/outputter/outputter.rb +134 -0
  58. data/lib/log4r/outputter/outputterfactory.rb +61 -0
  59. data/lib/log4r/outputter/rabbitoutputter.rb +70 -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 +130 -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/lib/log4r.rb +18 -0
  87. data/tests/README +10 -0
  88. data/tests/testGDC.rb +24 -0
  89. data/tests/testMDC.rb +40 -0
  90. data/tests/testNDC.rb +25 -0
  91. data/tests/test_helper.rb +12 -0
  92. data/tests/testall.rb +6 -0
  93. data/tests/testbase.rb +48 -0
  94. data/tests/testchainsaw.rb +42 -0
  95. data/tests/testconf.xml +37 -0
  96. data/tests/testcustom.rb +30 -0
  97. data/tests/testformatter.rb +31 -0
  98. data/tests/testlogger.rb +200 -0
  99. data/tests/testoutputter.rb +143 -0
  100. data/tests/testpatternformatter.rb +76 -0
  101. data/tests/testthreads.rb +31 -0
  102. data/tests/testxmlconf.rb +48 -0
  103. data/tests/testyaml.rb +39 -0
  104. data/tests/testyaml_arrays.yaml +25 -0
  105. data/tests/testyaml_injection.yaml +22 -0
  106. metadata +193 -0
@@ -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,61 @@
1
+ # :nodoc:
2
+ # Version: $Id$
3
+
4
+ require "log4r/base"
5
+ require "log4r/repository"
6
+ require "log4r/logger"
7
+
8
+ require 'monitor'
9
+
10
+ module Log4r
11
+ class Outputter < Monitor
12
+
13
+ class OutputterFactory #:nodoc:
14
+ include Singleton
15
+
16
+ # handles two cases: logging above a level (no second arg specified)
17
+ # or logging a set of levels (passed into the second argument)
18
+ def self.create_methods(out, levels=nil)
19
+ Logger.root # force levels to be loaded
20
+
21
+ # first, undefine all the log levels
22
+ for mname in LNAMES
23
+ undefine_log(mname.downcase, out)
24
+ end
25
+ if not levels.nil? and levels.include? OFF
26
+ raise TypeError, "Can't log only_at OFF", caller[1..-1]
27
+ end
28
+ return out if out.level == OFF
29
+
30
+ if levels.nil? # then define the log methods for lev >= outlev
31
+ for lev in out.level...LEVELS
32
+ define_log(LNAMES[lev].downcase, lev, out)
33
+ end
34
+ else # define the logs only for assigned levels
35
+ for lev in levels
36
+ define_log(LNAMES[lev].downcase, lev, out)
37
+ end
38
+ end
39
+ return out
40
+ end
41
+
42
+ # we need to synch the actual write/format for thread safteyness
43
+ def self.define_log(mname, level, out)
44
+ return if mname == 'off' || mname == 'all'
45
+ mstr = %-
46
+ def out.#{mname}(logevent)
47
+ canonical_log(logevent)
48
+ end
49
+ -
50
+ module_eval mstr
51
+ end
52
+
53
+ def self.undefine_log(mname, out)
54
+ return if mname == 'off' || mname == 'all'
55
+ mstr = "def out.#{mname}(logevent); end"
56
+ module_eval mstr
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,70 @@
1
+ # :nodoc:
2
+ require "rubygems"
3
+ require 'logger'
4
+ require "log4r/outputter/outputter"
5
+ require 'bunny'
6
+ require 'yaml'
7
+
8
+ module Log4r
9
+ # See log4r/logserver.rb
10
+ class RabbitOutputter < Outputter
11
+
12
+ def initialize(_name, hash={})
13
+ # Configuration defaults
14
+ super(_name, hash)
15
+ stderr_log "Unable to find rabbit configuration file" unless load_config
16
+ @config ||= {:host => "localhost"}
17
+ @config.symbolize_keys!
18
+ @queue_name = @config.delete(:queue) || ''
19
+ start_bunny rescue nil
20
+ end
21
+
22
+ def load_config_file(name)
23
+ path = "#{Rails.root}/config/#{name}"
24
+ if File.exist?(path)
25
+ @config = YAML::load(IO.read(path))
26
+ end
27
+ end
28
+
29
+ def load_config
30
+ @config = if load_config_file("bunny.yml")
31
+ @config[Rails.env]
32
+ else
33
+ load_config_file("rabbitmq.yml")
34
+ end
35
+ end
36
+
37
+ def start_bunny
38
+ begin
39
+ stderr_log "Starting Bunny Client"
40
+ config = @config.clone
41
+ config[:pass] &&= "**redacted**"
42
+ stderr_log config
43
+ @conn = Bunny.new @config
44
+ @conn.start
45
+ create_channel
46
+ rescue Bunny::TCPConnectionFailed => e
47
+ stderr_log "rescued from: #{e}. Unable to connect to Rabbit Server"
48
+ end
49
+ end
50
+
51
+ def stderr_log(msg)
52
+ $stderr.puts "[#{Time.now.utc}] #{msg}"
53
+ end
54
+
55
+ def create_channel
56
+ ch = @conn.create_channel
57
+ @queue = ch.queue(@queue_name, auto_delete: false, durable: true)
58
+ end
59
+
60
+ private
61
+
62
+ def write(data)
63
+ @queue.publish data, { routing_key: @queue.name } if @conn.connected? and @queue
64
+ rescue Exception => e
65
+ @conn.send(:handle_network_failure, e)
66
+ create_channel if @conn.connected?
67
+ end
68
+
69
+ end
70
+ 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
@@ -0,0 +1,37 @@
1
+ # :nodoc:
2
+ # Version:: $Id$
3
+
4
+ require "log4r/outputter/outputter"
5
+ require "rubygems"
6
+ require "scribe"
7
+
8
+ module Log4r
9
+ class ScribeOutputter < Outputter
10
+ attr_reader :host, :port, :category
11
+
12
+ def initialize(_name, hash={})
13
+ super(_name, hash)
14
+ @host = (hash[:host] or hash[:host] or 'localhost')
15
+ @port = (hash[:port] or hash[:port] or '1463')
16
+ @category = (hash[:category] or hash[:category] or 'default')
17
+
18
+ @client = Scribe.new("#{@host}:#{@port}", category=@category, add_newlines=false)
19
+ end
20
+
21
+ private
22
+
23
+ def write(data)
24
+ begin
25
+ @client.log(data.strip, @category)
26
+ rescue ScribeThrift::Client::TransportException => e
27
+ Logger.log_internal(-2) {
28
+ "Caught TransportException, is the scribe server alive?"
29
+ }
30
+ rescue ThriftClient::NoServersAvailable => e
31
+ Logger.log_internal(-2) {
32
+ "No scribe servers are available!"
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ # :nodoc:
2
+ module Log4r
3
+
4
+ class Outputter < Monitor
5
+ # Retrieve an outputter.
6
+ def self.[](name)
7
+ out = @@outputters[name]
8
+ if out.nil?
9
+ return case name
10
+ when 'stdout' then StdoutOutputter.new 'stdout'
11
+ when 'stderr' then StderrOutputter.new 'stderr'
12
+ else nil end
13
+ end
14
+ out
15
+ end
16
+ def self.stdout; Outputter['stdout'] end
17
+ def self.stderr; Outputter['stderr'] end
18
+ # Set an outputter.
19
+ def self.[]=(name, outputter)
20
+ @@outputters[name] = outputter
21
+ end
22
+ # Yields each outputter's name and reference.
23
+ def self.each
24
+ @@outputters.each {|name, outputter| yield name, outputter}
25
+ end
26
+ def self.each_outputter
27
+ @@outputters.each_value {|outputter| yield outputter}
28
+ end
29
+ end
30
+ end