sml-log4r 1.0.6
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/doc/content/contact.html +22 -0
- data/doc/content/contribute.html +21 -0
- data/doc/content/index.html +90 -0
- data/doc/content/license.html +56 -0
- data/doc/content/manual.html +449 -0
- data/doc/dev/README.developers +40 -0
- data/doc/dev/checklist +14 -0
- data/doc/dev/things-to-do +2 -0
- data/doc/images/crush/logo2.png +0 -0
- data/doc/images/log4r-logo.png +0 -0
- data/doc/images/logo2.png +0 -0
- data/doc/log4r.css +111 -0
- data/doc/old/manual.html +348 -0
- data/doc/templates/main.html +147 -0
- data/examples/README +19 -0
- data/examples/customlevels.rb +34 -0
- data/examples/fileroll.rb +40 -0
- data/examples/log4r_yaml.yaml +0 -0
- data/examples/logclient.rb +25 -0
- data/examples/logserver.rb +18 -0
- data/examples/moderate.xml +29 -0
- data/examples/moderateconfig.rb +66 -0
- data/examples/myformatter.rb +23 -0
- data/examples/outofthebox.rb +21 -0
- data/examples/rrconfig.xml +63 -0
- data/examples/rrsetup.rb +42 -0
- data/examples/simpleconfig.rb +39 -0
- data/examples/xmlconfig.rb +25 -0
- data/examples/yaml.rb +30 -0
- data/src/log4r.rb +17 -0
- data/src/log4r/base.rb +74 -0
- data/src/log4r/config.rb +9 -0
- data/src/log4r/configurator.rb +224 -0
- data/src/log4r/formatter/formatter.rb +105 -0
- data/src/log4r/formatter/patternformatter.rb +108 -0
- data/src/log4r/lib/drbloader.rb +52 -0
- data/src/log4r/lib/xmlloader.rb +24 -0
- data/src/log4r/logevent.rb +28 -0
- data/src/log4r/logger.rb +194 -0
- data/src/log4r/loggerfactory.rb +89 -0
- data/src/log4r/logserver.rb +28 -0
- data/src/log4r/outputter/consoleoutputters.rb +18 -0
- data/src/log4r/outputter/datefileoutputter.rb +110 -0
- data/src/log4r/outputter/emailoutputter.rb +115 -0
- data/src/log4r/outputter/fileoutputter.rb +49 -0
- data/src/log4r/outputter/iooutputter.rb +55 -0
- data/src/log4r/outputter/outputter.rb +132 -0
- data/src/log4r/outputter/outputterfactory.rb +59 -0
- data/src/log4r/outputter/remoteoutputter.rb +40 -0
- data/src/log4r/outputter/rollingfileoutputter.rb +126 -0
- data/src/log4r/outputter/staticoutputter.rb +30 -0
- data/src/log4r/outputter/syslogoutputter.rb +75 -0
- data/src/log4r/rdoc/configurator +243 -0
- data/src/log4r/rdoc/emailoutputter +103 -0
- data/src/log4r/rdoc/formatter +39 -0
- data/src/log4r/rdoc/log4r +89 -0
- data/src/log4r/rdoc/logger +175 -0
- data/src/log4r/rdoc/logserver +85 -0
- data/src/log4r/rdoc/outputter +108 -0
- data/src/log4r/rdoc/patternformatter +128 -0
- data/src/log4r/rdoc/syslogoutputter +29 -0
- data/src/log4r/rdoc/yamlconfigurator +20 -0
- data/src/log4r/repository.rb +65 -0
- data/src/log4r/staticlogger.rb +49 -0
- data/src/log4r/yamlconfigurator.rb +0 -0
- data/tests/include.rb +7 -0
- data/tests/runtest.rb +6 -0
- data/tests/testbase.rb +45 -0
- data/tests/testcustom.rb +33 -0
- data/tests/testdefault.rb +25 -0
- data/tests/testformatter.rb +29 -0
- data/tests/testlogger.rb +198 -0
- data/tests/testoutputter.rb +112 -0
- data/tests/testpatternformatter.rb +26 -0
- data/tests/testxmlconf.rb +51 -0
- data/tests/xml/testconf.xml +37 -0
- metadata +140 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# :include: ../rdoc/formatter
|
2
|
+
#
|
3
|
+
# Version:: $Id: formatter.rb,v 1.7 2003/09/01 22:33:20 cepheus Exp $
|
4
|
+
|
5
|
+
require "singleton"
|
6
|
+
|
7
|
+
require "log4r/base"
|
8
|
+
|
9
|
+
module Log4r
|
10
|
+
|
11
|
+
# Formatter is an abstract class and a null object
|
12
|
+
class Formatter
|
13
|
+
def initialize(hash={})
|
14
|
+
end
|
15
|
+
# Define this method in a subclass to format data.
|
16
|
+
def format(logevent)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# SimpleFormatter produces output like this:
|
21
|
+
#
|
22
|
+
# WARN loggername> Danger, Will Robinson, danger!
|
23
|
+
#
|
24
|
+
# Does not write traces and does not inspect objects.
|
25
|
+
|
26
|
+
class SimpleFormatter < Formatter
|
27
|
+
def format(event)
|
28
|
+
sprintf("%*s %s> %s\n", MaxLevelLength, LNAMES[event.level],
|
29
|
+
event.name, event.data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# BasicFormatter produces output like this:
|
34
|
+
#
|
35
|
+
# WARN loggername: I dropped my Wookie!
|
36
|
+
#
|
37
|
+
# Or like this if trace is on:
|
38
|
+
#
|
39
|
+
# WARN loggername(file.rb at 12): Hot potato!
|
40
|
+
#
|
41
|
+
# Also, it will pretty-print any Exception it gets and
|
42
|
+
# +inspect+ everything else.
|
43
|
+
#
|
44
|
+
# Hash arguments include:
|
45
|
+
#
|
46
|
+
# +depth+:: How many lines of the stacktrace to display.
|
47
|
+
|
48
|
+
class BasicFormatter < SimpleFormatter
|
49
|
+
@@basicformat = "%*s %s"
|
50
|
+
|
51
|
+
def initialize(hash={})
|
52
|
+
@depth = (hash[:depth] or hash['depth'] or 7).to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
def format(event)
|
56
|
+
buff = sprintf(@@basicformat, MaxLevelLength, LNAMES[event.level],
|
57
|
+
event.name)
|
58
|
+
buff += (event.tracer.nil? ? "" : "(#{event.tracer[0]})") + ": "
|
59
|
+
buff += format_object(event.data) + "\n"
|
60
|
+
buff
|
61
|
+
end
|
62
|
+
|
63
|
+
# Formats data according to its class:
|
64
|
+
#
|
65
|
+
# String:: Prints it out as normal.
|
66
|
+
# Exception:: Produces output similar to command-line exceptions.
|
67
|
+
# Object:: Prints the type of object, then the output of
|
68
|
+
# +inspect+. An example -- Array: [1, 2, 3]
|
69
|
+
|
70
|
+
def format_object(obj)
|
71
|
+
if obj.kind_of? Exception
|
72
|
+
return "Caught #{obj.class}: #{obj.message}\n\t" +\
|
73
|
+
obj.backtrace[0...@depth].join("\n\t")
|
74
|
+
elsif obj.kind_of? String
|
75
|
+
return obj
|
76
|
+
else # inspect the object
|
77
|
+
return "#{obj.class}: #{obj.inspect}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Formats objects the same way irb does:
|
83
|
+
#
|
84
|
+
# loggername:foo.rb in 12>
|
85
|
+
# [1, 3, 4]
|
86
|
+
# loggername:foo.rb in 13>
|
87
|
+
# {1=>"1"}
|
88
|
+
#
|
89
|
+
# Strings don't get inspected. just printed. The trace is optional.
|
90
|
+
|
91
|
+
class ObjectFormatter < Formatter
|
92
|
+
def format(event)
|
93
|
+
buff = event.logger.name
|
94
|
+
buff += (event.tracer.nil? ? "" : ":#{event.tracer[0]}") + ">\n"
|
95
|
+
buff += (event.data.kind_of?(String) ? event.data : event.data.inspect)
|
96
|
+
buff += "\n"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Outputters that don't define a Formatter will get this, which
|
101
|
+
# is currently BasicFormatter
|
102
|
+
class DefaultFormatter < BasicFormatter
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# :include: ../rdoc/patternformatter
|
2
|
+
#
|
3
|
+
# == Other Info
|
4
|
+
#
|
5
|
+
# Version:: $Id: patternformatter.rb,v 1.2 2002/01/28 16:05:05 cepheus Exp $
|
6
|
+
# Author:: Leon Torres <leon@ugcs.caltech.edu>
|
7
|
+
|
8
|
+
require "log4r/formatter/formatter"
|
9
|
+
|
10
|
+
module Log4r
|
11
|
+
# See log4r/formatter/patternformatter.rb
|
12
|
+
class PatternFormatter < BasicFormatter
|
13
|
+
|
14
|
+
# Arguments to sprintf keyed to directive letters
|
15
|
+
DirectiveTable = {
|
16
|
+
"c" => 'event.name',
|
17
|
+
"C" => 'event.fullname',
|
18
|
+
"d" => 'format_date',
|
19
|
+
"t" => 'event.tracer[0]',
|
20
|
+
"m" => 'event.data',
|
21
|
+
"M" => 'format_object(event.data)',
|
22
|
+
"l" => 'LNAMES[event.level]',
|
23
|
+
"%" => '"%"'
|
24
|
+
}
|
25
|
+
|
26
|
+
# Matches the first directive encountered and the stuff around it.
|
27
|
+
#
|
28
|
+
# * $1 is the stuff before directive or "" if not applicable
|
29
|
+
# * $2 is the directive group or nil if there's none
|
30
|
+
# * $3 is the %#.# match within directive group
|
31
|
+
# * $4 is the .# match which we don't use (it's there to match properly)
|
32
|
+
# * $5 is the directive letter
|
33
|
+
# * $6 is the stuff after the directive or "" if not applicable
|
34
|
+
|
35
|
+
DirectiveRegexp = /([^%]*)((%-?\d*(\.\d+)?)([cCdtmMl%]))?(.*)/
|
36
|
+
|
37
|
+
# default date format
|
38
|
+
ISO8601 = "%Y-%m-%d %H:%M:%S"
|
39
|
+
|
40
|
+
attr_reader :pattern, :date_pattern, :date_method
|
41
|
+
|
42
|
+
# Accepts the following hash arguments (either a string or a symbol):
|
43
|
+
#
|
44
|
+
# [<tt>pattern</tt>] A pattern format string.
|
45
|
+
# [<tt>date_pattern</tt>] A Time#strftime format string. See the
|
46
|
+
# Ruby Time class for details.
|
47
|
+
# [+date_method+]
|
48
|
+
# As an option to date_pattern, specify which
|
49
|
+
# Time.now method to call. For
|
50
|
+
# example, +usec+ or +to_s+.
|
51
|
+
# Specify it as a String or Symbol.
|
52
|
+
#
|
53
|
+
# The default date format is ISO8601, which looks like this:
|
54
|
+
#
|
55
|
+
# yyyy-mm-dd hh:mm:ss => 2001-01-12 13:15:50
|
56
|
+
|
57
|
+
def initialize(hash={})
|
58
|
+
super(hash)
|
59
|
+
@pattern = (hash['pattern'] or hash[:pattern] or nil)
|
60
|
+
@date_pattern = (hash['date_pattern'] or hash[:date_pattern] or nil)
|
61
|
+
@date_method = (hash['date_method'] or hash[:date_method] or nil)
|
62
|
+
@date_pattern = ISO8601 if @date_pattern.nil? and @date_method.nil?
|
63
|
+
PatternFormatter.create_format_methods(self)
|
64
|
+
end
|
65
|
+
|
66
|
+
# PatternFormatter works by dynamically defining a <tt>format</tt> method
|
67
|
+
# based on the supplied pattern format. This method contains a call to
|
68
|
+
# Kernel#sptrintf with arguments containing the data requested in
|
69
|
+
# the pattern format.
|
70
|
+
#
|
71
|
+
# How is this magic accomplished? First, we visit each directive
|
72
|
+
# and change the %#.# component to %#.#s. The directive letter is then
|
73
|
+
# used to cull an appropriate entry from the DirectiveTable for the
|
74
|
+
# sprintf argument list. After assembling the method definition, we
|
75
|
+
# run module_eval on it, and voila.
|
76
|
+
|
77
|
+
def PatternFormatter.create_format_methods(pf) #:nodoc:
|
78
|
+
# first, define the format_date method
|
79
|
+
if pf.date_method
|
80
|
+
module_eval "def pf.format_date; Time.now.#{pf.date_method}; end"
|
81
|
+
else
|
82
|
+
module_eval <<-EOS
|
83
|
+
def pf.format_date
|
84
|
+
Time.now.strftime "#{pf.date_pattern}"
|
85
|
+
end
|
86
|
+
EOS
|
87
|
+
end
|
88
|
+
# and now the main format method
|
89
|
+
ebuff = "def pf.format(event)\n sprintf(\""
|
90
|
+
_pattern = pf.pattern.dup
|
91
|
+
args = [] # the args to sprintf which we'll append to ebuff lastly
|
92
|
+
while true # work on each match in turn
|
93
|
+
match = DirectiveRegexp.match _pattern
|
94
|
+
ebuff += match[1] unless match[1].empty?
|
95
|
+
break if match[2].nil?
|
96
|
+
# deal with the directive by inserting a %#.#s where %#.# is copied
|
97
|
+
# directy from the match
|
98
|
+
ebuff += match[3] + "s"
|
99
|
+
args << DirectiveTable[match[5]] # cull the data for our argument list
|
100
|
+
break if match[6].empty?
|
101
|
+
_pattern = match[6]
|
102
|
+
end
|
103
|
+
ebuff += '\n", ' + args.join(', ') + ")\n"
|
104
|
+
ebuff += "end\n"
|
105
|
+
module_eval ebuff
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#:nodoc:
|
2
|
+
module Log4r
|
3
|
+
begin
|
4
|
+
require 'romp'
|
5
|
+
HAVE_ROMP = true
|
6
|
+
rescue LoadError
|
7
|
+
HAVE_ROMP = false
|
8
|
+
end
|
9
|
+
|
10
|
+
if HAVE_ROMP
|
11
|
+
|
12
|
+
module ROMPServer #:nodoc:
|
13
|
+
private
|
14
|
+
def start_server(_uri, accept)
|
15
|
+
@server = ROMP::Server.new(_uri, accept) # what if accept is nil?
|
16
|
+
@server.bind(self, "Log4r::LogServer")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ROMPClient #:nodoc:
|
21
|
+
private
|
22
|
+
def connect
|
23
|
+
begin
|
24
|
+
@client = ROMP::Client.new(@uri, false)
|
25
|
+
@remote_logger = @client.resolve("Log4r::LogServer")
|
26
|
+
rescue Exception => e
|
27
|
+
Logger.log_internal(-2) {
|
28
|
+
"RemoteOutputter '#{@name}' failed to connect to #{@uri}!"
|
29
|
+
}
|
30
|
+
Logger.log_internal {e}
|
31
|
+
self.level = OFF
|
32
|
+
end
|
33
|
+
end
|
34
|
+
# we use propagated = true
|
35
|
+
def send_buffer
|
36
|
+
begin
|
37
|
+
@buff.each {|levent|
|
38
|
+
lname = LNAMES[levent.level].downcase
|
39
|
+
@remote_logger.oneway(lname, levent, true)
|
40
|
+
}
|
41
|
+
rescue Exception => e
|
42
|
+
Logger.log_internal(-2) {"RemoteOutputter '#{@name}' can't log!"}
|
43
|
+
Logger.log_internal {e}
|
44
|
+
self.level = OFF
|
45
|
+
ensure @buff.clear
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#:nodoc:
|
2
|
+
module Log4r
|
3
|
+
begin
|
4
|
+
require 'rexml/document'
|
5
|
+
HAVE_REXML = true
|
6
|
+
rescue LoadError
|
7
|
+
HAVE_REXML = false
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if Log4r::HAVE_REXML
|
12
|
+
module REXML #:nodoc: all
|
13
|
+
class Element
|
14
|
+
def value_of(elmt)
|
15
|
+
val = attributes[elmt]
|
16
|
+
if val.nil?
|
17
|
+
sub = elements[elmt]
|
18
|
+
val = sub.text unless sub.nil?
|
19
|
+
end
|
20
|
+
val
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# :nodoc:
|
2
|
+
module Log4r
|
3
|
+
|
4
|
+
##
|
5
|
+
# LogEvent wraps up all the miscellaneous data associated with a logging
|
6
|
+
# statement. It gets passed around to the varied components of Log4r and
|
7
|
+
# should be of interest to those creating extensions.
|
8
|
+
#
|
9
|
+
# Data contained:
|
10
|
+
#
|
11
|
+
# [level] The integer level of the log event. Use LNAMES[level]
|
12
|
+
# to get the actual level name.
|
13
|
+
# [tracer] The execution stack returned by <tt>caller</tt> at the
|
14
|
+
# log event. It is nil if the invoked Logger's trace is false.
|
15
|
+
# [data] The object that was passed into the logging method.
|
16
|
+
# [name] The name of the logger that was invoked.
|
17
|
+
# [fullname] The fully qualified name of the logger that was invoked.
|
18
|
+
#
|
19
|
+
# Note that creating timestamps is a task left to formatters.
|
20
|
+
|
21
|
+
class LogEvent
|
22
|
+
attr_reader :level, :tracer, :data, :name, :fullname
|
23
|
+
def initialize(level, logger, tracer, data)
|
24
|
+
@level, @tracer, @data = level, tracer, data
|
25
|
+
@name, @fullname = logger.name, logger.fullname
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/src/log4r/logger.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# :include: rdoc/logger
|
2
|
+
#
|
3
|
+
# == Other Info
|
4
|
+
#
|
5
|
+
# Version:: $Id: logger.rb,v 1.24 2004/03/17 19:13:07 fando Exp $
|
6
|
+
# Author:: Leon Torres <leon(at)ugcs.caltech.edu>
|
7
|
+
|
8
|
+
require "log4r/outputter/outputter"
|
9
|
+
require "log4r/repository"
|
10
|
+
require "log4r/loggerfactory"
|
11
|
+
require "log4r/staticlogger"
|
12
|
+
|
13
|
+
module Log4r
|
14
|
+
|
15
|
+
# See log4r/logger.rb
|
16
|
+
class Logger
|
17
|
+
attr_reader :name, :fullname, :path, :level, :parent
|
18
|
+
attr_reader :additive, :trace, :outputters
|
19
|
+
|
20
|
+
# Logger requires a name. The last 3 parameters are:
|
21
|
+
#
|
22
|
+
# level:: Do I have a level? (Otherwise, I'll inherit my parent's)
|
23
|
+
# additive:: Am I additive?
|
24
|
+
# trace:: Do I record the execution trace? (slows things a wee bit)
|
25
|
+
|
26
|
+
def initialize(_fullname, _level=nil, _additive=true, _trace=false)
|
27
|
+
# validation
|
28
|
+
raise ArgumentError, "Logger must have a name", caller if _fullname.nil?
|
29
|
+
Log4rTools.validate_level(_level) unless _level.nil?
|
30
|
+
validate_name(_fullname)
|
31
|
+
|
32
|
+
# create the logger
|
33
|
+
@fullname = _fullname
|
34
|
+
@outputters = []
|
35
|
+
@additive = _additive
|
36
|
+
deal_with_inheritance(_level)
|
37
|
+
LoggerFactory.define_methods(self)
|
38
|
+
self.trace = _trace
|
39
|
+
Repository[@fullname] = self
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_name(_fullname)
|
43
|
+
parts = _fullname.split Log4rConfig::LoggerPathDelimiter
|
44
|
+
for part in parts
|
45
|
+
raise ArgumentError, "Malformed path", caller[1..-1] if part.empty?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
private :validate_name
|
49
|
+
|
50
|
+
# Parses name for location in heiarchy, sets the parent, and
|
51
|
+
# deals with level inheritance
|
52
|
+
|
53
|
+
def deal_with_inheritance(_level)
|
54
|
+
mypath = @fullname.split Log4rConfig::LoggerPathDelimiter
|
55
|
+
@name = mypath.pop
|
56
|
+
if mypath.empty? # then root is my daddy
|
57
|
+
@path = ""
|
58
|
+
# This is one of the guarantees that RootLogger gets created
|
59
|
+
@parent = Logger.root
|
60
|
+
else
|
61
|
+
@path = mypath.join(Log4rConfig::LoggerPathDelimiter)
|
62
|
+
@parent = Repository.find_ancestor(@path)
|
63
|
+
@parent = Logger.root if @parent.nil?
|
64
|
+
end
|
65
|
+
# inherit the level if no level defined
|
66
|
+
if _level.nil? then @level = @parent.level
|
67
|
+
else @level = _level end
|
68
|
+
Repository.reassign_any_children(self)
|
69
|
+
end
|
70
|
+
private :deal_with_inheritance
|
71
|
+
|
72
|
+
# Set the logger level dynamically. Does not affect children.
|
73
|
+
def level=(_level)
|
74
|
+
Log4rTools.validate_level(_level)
|
75
|
+
@level = _level
|
76
|
+
LoggerFactory.define_methods(self)
|
77
|
+
Logger.log_internal {"Logger '#{@fullname}' set to #{LNAMES[@level]}"}
|
78
|
+
@level
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set the additivity of the logger dynamically. True or false.
|
82
|
+
def additive=(_additive)
|
83
|
+
@additive = _additive
|
84
|
+
LoggerFactory.define_methods(self)
|
85
|
+
Logger.log_internal {"Logger '#{@fullname}' is additive"}
|
86
|
+
@additive
|
87
|
+
end
|
88
|
+
|
89
|
+
# Set whether the logger traces. Can be set dynamically. Defaults
|
90
|
+
# to false and understands the strings 'true' and 'false'.
|
91
|
+
def trace=(_trace)
|
92
|
+
@trace =
|
93
|
+
case _trace
|
94
|
+
when "true", true then true
|
95
|
+
else false end
|
96
|
+
LoggerFactory.define_methods(self)
|
97
|
+
Logger.log_internal {"Logger '#{@fullname}' is tracing"} if @trace
|
98
|
+
@trace
|
99
|
+
end
|
100
|
+
|
101
|
+
# Please don't reset the parent
|
102
|
+
def parent=(parent)
|
103
|
+
@parent = parent
|
104
|
+
end
|
105
|
+
|
106
|
+
# Set the Outputters dynamically by name or reference. Can be done any
|
107
|
+
# time.
|
108
|
+
def outputters=(_outputters)
|
109
|
+
@outputters.clear
|
110
|
+
add(*_outputters)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Add outputters by name or by reference. Can be done any time.
|
114
|
+
def add(*_outputters)
|
115
|
+
for thing in _outputters
|
116
|
+
o = (thing.kind_of?(Outputter) ? thing : Outputter[thing])
|
117
|
+
# some basic validation
|
118
|
+
if not o.kind_of?(Outputter)
|
119
|
+
raise TypeError, "Expected kind of Outputter, got #{o.class}", caller
|
120
|
+
elsif o.nil?
|
121
|
+
raise TypeError, "Couldn't find Outputter '#{thing}'", caller
|
122
|
+
end
|
123
|
+
@outputters.push o
|
124
|
+
Logger.log_internal {"Added outputter '#{o.name}' to '#{@fullname}'"}
|
125
|
+
end
|
126
|
+
@outputters
|
127
|
+
end
|
128
|
+
|
129
|
+
# Remove outputters from this logger by name only. Can be done any time.
|
130
|
+
def remove(*_outputters)
|
131
|
+
for name in _outputters
|
132
|
+
o = Outputter[name]
|
133
|
+
@outputters.delete o
|
134
|
+
Logger.log_internal {"Removed outputter '#{o.name}' from '#{@fullname}'"}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def is_root?; false end
|
139
|
+
|
140
|
+
def ==(other)
|
141
|
+
return true if object_id == other.object_id
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# RootLogger should be retrieved with Logger.root or Logger.global.
|
147
|
+
# It's supposed to be transparent.
|
148
|
+
#--
|
149
|
+
# We must guarantee the creation of RootLogger before any other Logger
|
150
|
+
# or Outputter gets their logging methods defined. There are two
|
151
|
+
# guarantees in the code:
|
152
|
+
#
|
153
|
+
# * Logger#deal_with_inheritance - calls RootLogger.instance when
|
154
|
+
# a new Logger is created without a parent. Parents must exist, therefore
|
155
|
+
# RootLogger is forced to be created.
|
156
|
+
#
|
157
|
+
# * OutputterFactory.create_methods - Calls Logger.root first. So if
|
158
|
+
# an Outputter is created, RootLogger is also created.
|
159
|
+
#
|
160
|
+
# When RootLogger is created, it calls
|
161
|
+
# Log4r.define_levels(*Log4rConfig::LogLevels). This ensures that the
|
162
|
+
# default levels are loaded if no custom ones are.
|
163
|
+
|
164
|
+
class RootLogger < Logger
|
165
|
+
include Singleton
|
166
|
+
|
167
|
+
def initialize
|
168
|
+
Log4r.define_levels(*Log4rConfig::LogLevels) # ensure levels are loaded
|
169
|
+
@level = ALL
|
170
|
+
@outputters = []
|
171
|
+
Repository['root'] = self
|
172
|
+
Repository['global'] = self
|
173
|
+
LoggerFactory.undefine_methods(self)
|
174
|
+
end
|
175
|
+
|
176
|
+
def is_root?; true end
|
177
|
+
|
178
|
+
# Set the global level. Any loggers defined thereafter will
|
179
|
+
# not log below the global level regardless of their levels.
|
180
|
+
|
181
|
+
def level=(alevel); @level = alevel end
|
182
|
+
|
183
|
+
# Does nothing
|
184
|
+
def outputters=(foo); end
|
185
|
+
# Does nothing
|
186
|
+
def trace=(foo); end
|
187
|
+
# Does nothing
|
188
|
+
def additive=(foo); end
|
189
|
+
# Does nothing
|
190
|
+
def add(*foo); end
|
191
|
+
# Does nothing
|
192
|
+
def remove(*foo); end
|
193
|
+
end
|
194
|
+
end
|