path-log4r 1.1.10
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/INSTALL +11 -0
- data/LICENSE +90 -0
- data/LICENSE.LGPLv3 +165 -0
- data/README +95 -0
- data/Rakefile +74 -0
- data/TODO +2 -0
- 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 +55 -0
- data/doc/dev/checklist +23 -0
- data/doc/dev/things-to-do +5 -0
- data/doc/images/log4r-logo.png +0 -0
- data/doc/images/logo2.png +0 -0
- data/doc/log4r.css +111 -0
- data/doc/rdoc-log4r.css +696 -0
- data/doc/templates/main.html +147 -0
- data/examples/README +19 -0
- data/examples/ancestors.rb +53 -0
- data/examples/chainsaw_settings.xml +7 -0
- data/examples/customlevels.rb +34 -0
- data/examples/filelog.rb +25 -0
- data/examples/fileroll.rb +40 -0
- data/examples/gmail.rb +30 -0
- data/examples/gmail.yaml +95 -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/rdoc-gen +2 -0
- data/examples/rrconfig.xml +63 -0
- data/examples/rrsetup.rb +42 -0
- data/examples/simpleconfig.rb +39 -0
- data/examples/syslogcustom.rb +52 -0
- data/examples/xmlconfig.rb +25 -0
- data/examples/yaml.rb +30 -0
- data/lib/log4r.rb +20 -0
- data/lib/log4r/GDC.rb +41 -0
- data/lib/log4r/MDC.rb +59 -0
- data/lib/log4r/NDC.rb +86 -0
- data/lib/log4r/base.rb +74 -0
- data/lib/log4r/config.rb +9 -0
- data/lib/log4r/configurator.rb +224 -0
- data/lib/log4r/formatter/formatter.rb +105 -0
- data/lib/log4r/formatter/log4jxmlformatter.rb +61 -0
- data/lib/log4r/formatter/patternformatter.rb +145 -0
- data/lib/log4r/lib/drbloader.rb +52 -0
- data/lib/log4r/lib/xmlloader.rb +24 -0
- data/lib/log4r/logevent.rb +28 -0
- data/lib/log4r/logger.rb +199 -0
- data/lib/log4r/loggerfactory.rb +89 -0
- data/lib/log4r/logserver.rb +28 -0
- data/lib/log4r/outputter/consoleoutputters.rb +18 -0
- data/lib/log4r/outputter/datefileoutputter.rb +117 -0
- data/lib/log4r/outputter/emailoutputter.rb +143 -0
- data/lib/log4r/outputter/fileoutputter.rb +56 -0
- data/lib/log4r/outputter/iooutputter.rb +55 -0
- data/lib/log4r/outputter/outputter.rb +134 -0
- data/lib/log4r/outputter/outputterfactory.rb +61 -0
- data/lib/log4r/outputter/remoteoutputter.rb +40 -0
- data/lib/log4r/outputter/rollingfileoutputter.rb +234 -0
- data/lib/log4r/outputter/scribeoutputter.rb +37 -0
- data/lib/log4r/outputter/staticoutputter.rb +30 -0
- data/lib/log4r/outputter/syslogoutputter.rb +130 -0
- data/lib/log4r/outputter/udpoutputter.rb +53 -0
- data/lib/log4r/rdoc/GDC +14 -0
- data/lib/log4r/rdoc/MDC +16 -0
- data/lib/log4r/rdoc/NDC +41 -0
- data/lib/log4r/rdoc/configurator +243 -0
- data/lib/log4r/rdoc/emailoutputter +103 -0
- data/lib/log4r/rdoc/formatter +39 -0
- data/lib/log4r/rdoc/log4r +89 -0
- data/lib/log4r/rdoc/logger +175 -0
- data/lib/log4r/rdoc/logserver +85 -0
- data/lib/log4r/rdoc/outputter +108 -0
- data/lib/log4r/rdoc/patternformatter +128 -0
- data/lib/log4r/rdoc/scribeoutputter +16 -0
- data/lib/log4r/rdoc/syslogoutputter +29 -0
- data/lib/log4r/rdoc/win32eventoutputter +7 -0
- data/lib/log4r/rdoc/yamlconfigurator +20 -0
- data/lib/log4r/repository.rb +88 -0
- data/lib/log4r/staticlogger.rb +49 -0
- data/lib/log4r/yamlconfigurator.rb +196 -0
- data/tests/README +10 -0
- data/tests/testGDC.rb +26 -0
- data/tests/testMDC.rb +42 -0
- data/tests/testNDC.rb +27 -0
- data/tests/testall.rb +6 -0
- data/tests/testbase.rb +49 -0
- data/tests/testchainsaw.rb +48 -0
- data/tests/testconf.xml +37 -0
- data/tests/testcustom.rb +27 -0
- data/tests/testformatter.rb +27 -0
- data/tests/testlogger.rb +196 -0
- data/tests/testoutputter.rb +132 -0
- data/tests/testpatternformatter.rb +78 -0
- data/tests/testthreads.rb +35 -0
- data/tests/testxmlconf.rb +45 -0
- metadata +184 -0
|
@@ -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
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# :include: ../rdoc/syslogoutputter
|
|
2
|
+
#
|
|
3
|
+
# Version:: $Id$
|
|
4
|
+
# Author:: Steve Lumos
|
|
5
|
+
# Author:: Leon Torres
|
|
6
|
+
|
|
7
|
+
require 'log4r/formatter/formatter'
|
|
8
|
+
require 'log4r/outputter/outputter'
|
|
9
|
+
require 'log4r/configurator'
|
|
10
|
+
require 'syslog'
|
|
11
|
+
|
|
12
|
+
module Log4r
|
|
13
|
+
|
|
14
|
+
SYSLOGNAMES = Hash.new
|
|
15
|
+
|
|
16
|
+
class SyslogOutputter < Outputter
|
|
17
|
+
include Syslog::Constants
|
|
18
|
+
|
|
19
|
+
# maps default log4r levels to syslog priorities (logevents never see ALL and OFF)
|
|
20
|
+
# SYSLOG Levels are:
|
|
21
|
+
# "DEBUG" => Syslog::LOG_DEBUG
|
|
22
|
+
# "INFO" => Syslog::LOG_INFO
|
|
23
|
+
# "NOTICE" => Syslog::LOG_NOTICE
|
|
24
|
+
# "WARN" => Syslog::LOG_WARN
|
|
25
|
+
# "ERROR" => Syslog::LOG_ERROR
|
|
26
|
+
# "FATAL" => Syslog::LOG_FATAL
|
|
27
|
+
# "ALERT" => Syslog::LOG_ALERT
|
|
28
|
+
# "EMERG" => Syslog::LOG_EMERG
|
|
29
|
+
SYSLOG_LEVELS_MAP = {
|
|
30
|
+
"DEBUG" => LOG_DEBUG,
|
|
31
|
+
"INFO" => LOG_INFO,
|
|
32
|
+
"NOTICE" => LOG_NOTICE, # by default NOTICE is not in log4r
|
|
33
|
+
"WARN" => LOG_WARNING,
|
|
34
|
+
"ERROR" => LOG_ERR,
|
|
35
|
+
"FATAL" => LOG_CRIT,
|
|
36
|
+
"ALERT" => LOG_ALERT, # by default ALERT is not in log4r
|
|
37
|
+
"EMERG" => LOG_EMERG, # by default EMERG is not in log4r
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# mapping from Log4r default levels to syslog, by string name
|
|
41
|
+
# "DEBUG" => "DEBUG"
|
|
42
|
+
# "INFO" => "INFO"
|
|
43
|
+
# "WARN" => "WARN"
|
|
44
|
+
# "ERROR" => "ERROR"
|
|
45
|
+
# "FATAL" => "FATAL"
|
|
46
|
+
SYSLOG_LOG4R_MAP = {
|
|
47
|
+
"DEBUG" => "DEBUG",
|
|
48
|
+
"INFO" => "INFO",
|
|
49
|
+
"WARN" => "WARN",
|
|
50
|
+
"ERROR" => "ERROR",
|
|
51
|
+
"FATAL" => "FATAL"
|
|
52
|
+
# "NOTICE" => "INFO", # by default NOTICE is not in log4r
|
|
53
|
+
# "ALERT" => "FATAL", # by default ALERT is not in log4r
|
|
54
|
+
# "EMERG" => "FATAL" # by default EMERG is not in log4r
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@levels_map = SYSLOG_LOG4R_MAP
|
|
58
|
+
|
|
59
|
+
# There are 3 hash arguments
|
|
60
|
+
#
|
|
61
|
+
# [<tt>:ident</tt>] syslog ident, defaults to _name
|
|
62
|
+
# [<tt>:logopt</tt>] syslog logopt, defaults to LOG_PID | LOG_CONS
|
|
63
|
+
# [<tt>:facility</tt>] syslog facility, defaults to LOG_USER
|
|
64
|
+
def initialize(_name, hash={})
|
|
65
|
+
super(_name, hash)
|
|
66
|
+
ident = (hash[:ident] or hash['ident'] or _name)
|
|
67
|
+
logopt = (hash[:logopt] or hash['logopt'] or LOG_PID | LOG_CONS).to_i
|
|
68
|
+
facility = (hash[:facility] or hash['facility'] or LOG_USER).to_i
|
|
69
|
+
map_levels_by_name_to_syslog()
|
|
70
|
+
if ( Syslog.opened? ) then
|
|
71
|
+
Logger.log_internal { "Syslog already initialized, to alter, " +
|
|
72
|
+
"you must close first"}
|
|
73
|
+
end
|
|
74
|
+
@syslog = ( Syslog.opened? ) ? Syslog : Syslog.open(ident, logopt, facility)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def closed?
|
|
78
|
+
return !@syslog.opened?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def close
|
|
82
|
+
@syslog.close unless @syslog.nil?
|
|
83
|
+
@level = OFF
|
|
84
|
+
OutputterFactory.create_methods(self)
|
|
85
|
+
Logger.log_internal {"Outputter '#{@name}' closed Syslog and set to OFF"}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# A single hash argument that maps custom names to syslog names
|
|
89
|
+
#
|
|
90
|
+
# [<tt>levels_map</tt>] A map that will create a linkage between levels
|
|
91
|
+
# in a hash and underlying syslog levels.
|
|
92
|
+
# By default, these are direct mapping of the log4r
|
|
93
|
+
# levels (e.g. "DEBUG" => "DEBUG")
|
|
94
|
+
# If you have defined your own custom levels, you
|
|
95
|
+
# should provide this underlying mapping, otherwise
|
|
96
|
+
# all messages will be mapped to the underlying syslog
|
|
97
|
+
# level of INFO by default.
|
|
98
|
+
# e.g.
|
|
99
|
+
# You have created custom levels called:
|
|
100
|
+
# <tt>Configurator.custom_levels "HIGH", "MEDIUM", "LOW"</tt>
|
|
101
|
+
# To map these to 'equivilent' syslog levels, after instantiatin
|
|
102
|
+
# a syslogoutputter:
|
|
103
|
+
# <tt>SyslogOutputter.map_levels_by_name_to_syslog(
|
|
104
|
+
# { "HIGH" => "ALERT", "MEDIUM" => "WARN", "LOW" => "INFO" }
|
|
105
|
+
# )</tt>
|
|
106
|
+
def map_levels_by_name_to_syslog( lmap = SYSLOG_LOG4R_MAP )
|
|
107
|
+
@levels_map = lmap
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def get_levels_map()
|
|
111
|
+
return @levels_map
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def canonical_log(logevent)
|
|
117
|
+
pri = SYSLOG_LEVELS_MAP[@levels_map[LNAMES[logevent.level]]] rescue pri = LOG_INFO
|
|
118
|
+
o = format(logevent)
|
|
119
|
+
if o.kind_of? Exception then
|
|
120
|
+
msg = "#{o.class} at (#{o.backtrace[0]}): #{o.message}"
|
|
121
|
+
elsif o.respond_to? :to_str then
|
|
122
|
+
msg = o.to_str
|
|
123
|
+
else
|
|
124
|
+
msg = o.inspect
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
@syslog.log(pri, '%s', msg)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# :include: ../rdoc/outputter
|
|
2
|
+
#
|
|
3
|
+
# == Other Info
|
|
4
|
+
#
|
|
5
|
+
# Version:: $Id$
|
|
6
|
+
# Author:: Leon Torres <leon@ugcs.caltech.edu>
|
|
7
|
+
|
|
8
|
+
require "log4r/outputter/outputter"
|
|
9
|
+
require 'log4r/staticlogger'
|
|
10
|
+
require "socket"
|
|
11
|
+
|
|
12
|
+
module Log4r
|
|
13
|
+
|
|
14
|
+
class UDPOutputter < Outputter
|
|
15
|
+
attr_reader :host, :port
|
|
16
|
+
attr_accessor :udpsock
|
|
17
|
+
|
|
18
|
+
def initialize(_name, hash={})
|
|
19
|
+
super(_name, hash)
|
|
20
|
+
@host = hash[:hostname]
|
|
21
|
+
@port = hash[:port]
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
Logger.log_internal {
|
|
25
|
+
"UDPOutputter will send to #{@host}:#{@port}"
|
|
26
|
+
}
|
|
27
|
+
@udpsock = UDPSocket.new
|
|
28
|
+
@udpsock.connect( @host, @port )
|
|
29
|
+
rescue Exception => e
|
|
30
|
+
Logger.log_internal(ERROR) {
|
|
31
|
+
"UDPOutputter failed to create UDP socket: #{e}"
|
|
32
|
+
}
|
|
33
|
+
Logger.log_internal {e}
|
|
34
|
+
self.level = OFF
|
|
35
|
+
raise e
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#######
|
|
40
|
+
private
|
|
41
|
+
#######
|
|
42
|
+
|
|
43
|
+
def write(data)
|
|
44
|
+
@udpsock.send(data, 0)
|
|
45
|
+
rescue Exception => e
|
|
46
|
+
Logger.log_internal(ERROR) {
|
|
47
|
+
"UDPOutputter failed to send data to #{@host}:#{@port}, #{e}"
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
data/lib/log4r/rdoc/GDC
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
= GDC
|
|
2
|
+
|
|
3
|
+
The GDC class implements a copy of the Global Diagnostic Context, which
|
|
4
|
+
is not part of the Apache Log4j library, as of this writing (10 Jan 2009).
|
|
5
|
+
|
|
6
|
+
The GDC is like the NDC and MDC classes, only it is global to the
|
|
7
|
+
application (see NDC and MDC for details on those classes).
|
|
8
|
+
|
|
9
|
+
The GDC is local to the main thread, and any new threads will return
|
|
10
|
+
the value of the current GDC set in the main thread.
|
|
11
|
+
|
|
12
|
+
Only the main thread can set the GDC, any other threads that
|
|
13
|
+
attempt to will raise an exception.
|
|
14
|
+
|
data/lib/log4r/rdoc/MDC
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
= MDC
|
|
2
|
+
|
|
3
|
+
The MDC class implements a copy of the Mapped Diagnostic Context, which
|
|
4
|
+
is part of the Apache Log4j library. See the NDC documentation for
|
|
5
|
+
more details. MDCs are much like NDCs, but instead of a stack context
|
|
6
|
+
it uses a map for holding this information.
|
|
7
|
+
|
|
8
|
+
This allows for selection of information out of the map when
|
|
9
|
+
the log message is being created.
|
|
10
|
+
|
|
11
|
+
MDCs are thread safe, and are unique to each thread.
|
|
12
|
+
|
|
13
|
+
An important difference between MDCs in Log4r vs Log4j is that they
|
|
14
|
+
only inherit from the main thread. Ruby treats all new threads as
|
|
15
|
+
being the children of the main thread, even if they are started
|
|
16
|
+
from a thread that is not main.
|
data/lib/log4r/rdoc/NDC
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
= NDC
|
|
2
|
+
|
|
3
|
+
The NDC class implements a copy of the Nested Diagnostic Context, which
|
|
4
|
+
is part of the Apache Log4j library. Nested Diagnostic Contexts were
|
|
5
|
+
derived from Neil Harrison's article on "Patterns for Logging
|
|
6
|
+
Diagnostic Messages", part of the book "Pattern Languages of Program
|
|
7
|
+
Design 3" edited by Martin et al.
|
|
8
|
+
|
|
9
|
+
NDCs in Log4r are thread safe.
|
|
10
|
+
|
|
11
|
+
NDCs in log4r are close enough to NDCs in Log4j that I include its
|
|
12
|
+
documentation directly:
|
|
13
|
+
|
|
14
|
+
...
|
|
15
|
+
A Nested Diagnostic Context, or NDC in short, is an instrument to
|
|
16
|
+
distinguish interleaved log output from different sources. Log output
|
|
17
|
+
is typically interleaved when a server handles multiple clients
|
|
18
|
+
near-simultaneously.
|
|
19
|
+
|
|
20
|
+
Interleaved log output can still be meaningful if each log entry from
|
|
21
|
+
different contexts had a distinctive stamp. This is where NDCs come into
|
|
22
|
+
play.
|
|
23
|
+
|
|
24
|
+
Note that NDCs are managed on a per thread basis. NDC operations such as
|
|
25
|
+
push, pop(), clear(), getDepth() and setMaxDepth(int) affect the NDC of
|
|
26
|
+
the current thread only. NDCs of other threads remain unaffected.
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
An important difference between NDCs in Log4r vs Log4j is that you
|
|
30
|
+
do not have to called NDC.remove() when exiting a thread.
|
|
31
|
+
|
|
32
|
+
This class will automatically create Thread specific storage for the
|
|
33
|
+
current thread on the first call to any of its methods, i.e.
|
|
34
|
+
|
|
35
|
+
NDC.push( "client accept" );
|
|
36
|
+
|
|
37
|
+
New threads may inherit the NDC of the parent thread by making use of
|
|
38
|
+
the clone_stack() and inherit() methods. By default, the NDC is not
|
|
39
|
+
inherited automatically. This is unlike MDCs, which will inherit from
|
|
40
|
+
the main thread.
|
|
41
|
+
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
= Configuring Log4r with Log4r::Configurator
|
|
2
|
+
|
|
3
|
+
The Configurator class allows one to set up Log4r via XML.
|
|
4
|
+
Additionally, Configurator contains methods to configure any Log4r
|
|
5
|
+
defaults. In particular, Configurator provides a method to
|
|
6
|
+
customize the logging levels.
|
|
7
|
+
|
|
8
|
+
Log4r is also configurable using YAML. For that, there is
|
|
9
|
+
a class similar to Configurator called Log4r::YamlConfigurator. Please see
|
|
10
|
+
log4r/yamlconfigurator.rb for details.
|
|
11
|
+
|
|
12
|
+
REXML is required for XML configuration. Get REXML at
|
|
13
|
+
http://www.ruby-lang.org/en/raa-list.rhtml?name=REXML
|
|
14
|
+
|
|
15
|
+
To use the Configurator class,
|
|
16
|
+
|
|
17
|
+
require 'log4r/configurator'
|
|
18
|
+
|
|
19
|
+
== Custom Levels
|
|
20
|
+
|
|
21
|
+
Suppose you want the following levels and ranks:
|
|
22
|
+
|
|
23
|
+
Foo < Bar < Baz
|
|
24
|
+
|
|
25
|
+
This is easily accomplished:
|
|
26
|
+
|
|
27
|
+
Configurator.custom_levels('Foo', 'Bar', :Baz)
|
|
28
|
+
|
|
29
|
+
The method accepts strings or symbols. However, custom levels must have names
|
|
30
|
+
that are valid for Ruby constants. Also, custom levels should be set before
|
|
31
|
+
anything else is done with Log4r, otherwise the default levels will be loaded.
|
|
32
|
+
|
|
33
|
+
You can set custom levels in XML. That's covered in the following section.
|
|
34
|
+
|
|
35
|
+
== XML Configuration
|
|
36
|
+
|
|
37
|
+
If you have REXML, you can configure Log4r with XML.
|
|
38
|
+
To do this, first write an XML configuration (which you can learn by
|
|
39
|
+
studying this document and the examples provided in the distribution)
|
|
40
|
+
and then load up the XML from within your program as follows:
|
|
41
|
+
|
|
42
|
+
Configurator.load_xml_file('/path/to/file.xml')
|
|
43
|
+
|
|
44
|
+
The Log4r XML configuration system is very flexible and powerful. In fact,
|
|
45
|
+
it is somewhat preferable to configuring Log4r in Ruby. In order to take
|
|
46
|
+
full advantage of this feature, there are several concepts one must know.
|
|
47
|
+
They are covered in the following three sections.
|
|
48
|
+
|
|
49
|
+
=== Concept: XML Directives
|
|
50
|
+
|
|
51
|
+
The expressive power of Ruby has enabled a feature I call
|
|
52
|
+
<i>XML directives</i>. An XML directive is a name-value pair belonging to
|
|
53
|
+
some element. It
|
|
54
|
+
may be represented as an attribute (name="value") of the element, or
|
|
55
|
+
as a child (<name>value</name>) of the element. Therefore, you are
|
|
56
|
+
free to specify information about an object as either an attribute
|
|
57
|
+
or an element. An example should clarify:
|
|
58
|
+
|
|
59
|
+
<object data="value"/>
|
|
60
|
+
|
|
61
|
+
Is equivalent to:
|
|
62
|
+
|
|
63
|
+
<object>
|
|
64
|
+
<data>value</data>
|
|
65
|
+
</object>
|
|
66
|
+
|
|
67
|
+
You can assume this behavior except where noted elsewhere in the API.
|
|
68
|
+
|
|
69
|
+
=== Concept: XML Parameters
|
|
70
|
+
|
|
71
|
+
A scheme which I call <i>XML parameters</i> enables one to utilize the XML
|
|
72
|
+
configuratin system for custom Outputters and Formatters.
|
|
73
|
+
This requires <b>no</b> extra work on your part, so long as your objects
|
|
74
|
+
are set up using hash arguments and can decode string values. That is, once
|
|
75
|
+
you've written a custom Outputter, it is automatically configurable in XML
|
|
76
|
+
without having to write any extra code.
|
|
77
|
+
|
|
78
|
+
An XML parameter is analogous to a hash argument to some object's <tt>new</tt>
|
|
79
|
+
method. Consider these hash arguments to FileOutputter:
|
|
80
|
+
|
|
81
|
+
:filename => '/path/to/logs/my.log'
|
|
82
|
+
:trunc => 'true'
|
|
83
|
+
|
|
84
|
+
We can specify them in XML like this:
|
|
85
|
+
|
|
86
|
+
<outputter type="FileOutputter" trunc="true">
|
|
87
|
+
<filename>/path/to/logs/my.log</filename>
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
The name of the element/attribute is just the name of the parameter. Note that
|
|
91
|
+
the input will be a string, thus it's wise to convert the data in from
|
|
92
|
+
strings in any custom classes (to_i for integers, etc). Now let's suppose you
|
|
93
|
+
have defined a custom Outputter named MyOutputter with the following
|
|
94
|
+
additional hash args:
|
|
95
|
+
|
|
96
|
+
:myarg1 => 'foo'
|
|
97
|
+
:myarg2 => 123
|
|
98
|
+
|
|
99
|
+
Automagically, you can configure your Outputter like so:
|
|
100
|
+
|
|
101
|
+
<outputter type="MyOutputter" myarg2="123">
|
|
102
|
+
<myarg1>foo</myarg1>
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
Isn't that nice? <tt>:-)</tt>
|
|
106
|
+
|
|
107
|
+
=== Concept: Variable Substitution
|
|
108
|
+
|
|
109
|
+
To kill the need for preprocessors, Configurator provides a means of variable
|
|
110
|
+
substitution for XML parameters at runtime. If you specify
|
|
111
|
+
<tt>#{foo}</tt> in an XML parameter value, Configurator will replace it with
|
|
112
|
+
the value of 'foo' in its parameter hashtable. The primary idea is that you
|
|
113
|
+
can figure stuff out in your program,
|
|
114
|
+
say the log path, and relay that information to the XML while it's being
|
|
115
|
+
loaded. Secondarily, it is a way to have aliases within an XML document.
|
|
116
|
+
|
|
117
|
+
There are two ways to tell Configurator about these variables. The first
|
|
118
|
+
method we'll cover is done within a Ruby program with Configurator[].
|
|
119
|
+
|
|
120
|
+
Configurator['logpath'] = '/path/to/logs'
|
|
121
|
+
|
|
122
|
+
Thereafter, any occurence of <tt>#{logpath}</tt> in each and every XML
|
|
123
|
+
parameter will be substituted with '/path/to/logs'. For example:
|
|
124
|
+
|
|
125
|
+
<filename>#{logpath}/mylog.log</filename>
|
|
126
|
+
|
|
127
|
+
Becomes,
|
|
128
|
+
|
|
129
|
+
<filename>/path/to/logs/mylog.log</filename>
|
|
130
|
+
|
|
131
|
+
Aside from Configurator[], another way to define XML parameter variables
|
|
132
|
+
is to define <tt>parameters</tt> under the <tt><pre_config></tt> element
|
|
133
|
+
of an XML configuration:
|
|
134
|
+
|
|
135
|
+
<pre_config>
|
|
136
|
+
<parameter name="logpath" value="/path/to/logs'/>
|
|
137
|
+
<parameter name="other" value="somethingelse'/>
|
|
138
|
+
...
|
|
139
|
+
</pre_config>
|
|
140
|
+
|
|
141
|
+
Alternatively,
|
|
142
|
+
|
|
143
|
+
<pre_config>
|
|
144
|
+
<parameters>
|
|
145
|
+
<logpath>/path/to/logs</logpath>
|
|
146
|
+
<other>somethingelse</other>
|
|
147
|
+
...
|
|
148
|
+
</parameters>
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
The end result is the same as using Configurator[]. However, this method
|
|
152
|
+
is not dynamic. Configurator[] should be used when you want to set variables
|
|
153
|
+
from within Ruby.
|
|
154
|
+
|
|
155
|
+
= XML Grammar
|
|
156
|
+
|
|
157
|
+
And now, here's the XML grammar we use to configure Log4r.
|
|
158
|
+
|
|
159
|
+
== Root Element
|
|
160
|
+
|
|
161
|
+
The root element is <tt><log4r_config></tt>. It can be embedded as a node of
|
|
162
|
+
any other element in an XML file. For instance:
|
|
163
|
+
|
|
164
|
+
<my-xml-thing>
|
|
165
|
+
<customize-libraries>
|
|
166
|
+
<log4r_config>
|
|
167
|
+
<!-- log4r configuratin goes here -->
|
|
168
|
+
</log4r_config>
|
|
169
|
+
...
|
|
170
|
+
|
|
171
|
+
== Pre-config element
|
|
172
|
+
|
|
173
|
+
The pre_config element is a child of log4r_config and contains:
|
|
174
|
+
|
|
175
|
+
* 'custom_levels' element
|
|
176
|
+
* 'global' element
|
|
177
|
+
* 'parameters' element
|
|
178
|
+
* any number of 'parameter' elements
|
|
179
|
+
|
|
180
|
+
=== Pre_config: Custom Levels
|
|
181
|
+
|
|
182
|
+
The custom_levels element is not an <i>XML directive</i> of pre_config. It
|
|
183
|
+
<b>must</b> be specified like this:
|
|
184
|
+
|
|
185
|
+
<custom_levels>Foo, Bar, Baz</custom_levels>
|
|
186
|
+
|
|
187
|
+
And <b>not</b> like this:
|
|
188
|
+
|
|
189
|
+
<!-- NOT SUPPORTED -->
|
|
190
|
+
<custom_levels levels="Foo, Bar, Baz"/>
|
|
191
|
+
|
|
192
|
+
=== Pre_config: Global Level
|
|
193
|
+
|
|
194
|
+
<global level="DEBUG"/>
|
|
195
|
+
|
|
196
|
+
or
|
|
197
|
+
|
|
198
|
+
<global><level>DEBUG</level></global>
|
|
199
|
+
|
|
200
|
+
Here, level is an XML directive of global.
|
|
201
|
+
|
|
202
|
+
=== Pre_config: Parameters
|
|
203
|
+
|
|
204
|
+
Parameters are variables that will be substituted later on. Please
|
|
205
|
+
see the <b>Concept: Variable Substitution</b> section above. Parameters
|
|
206
|
+
are <i>XML Directives</i>, which means they can be expressed using elements
|
|
207
|
+
or attributes. Here is an example:
|
|
208
|
+
|
|
209
|
+
<parameter name="param name 1" value="param value 1">
|
|
210
|
+
<parameter name="param name 2" value="param value 2">
|
|
211
|
+
...
|
|
212
|
+
<parameters>
|
|
213
|
+
<param3>value3</param3>
|
|
214
|
+
<param4>value3</param4>
|
|
215
|
+
...
|
|
216
|
+
|
|
217
|
+
=== Pre_config: Complete Example
|
|
218
|
+
|
|
219
|
+
<log4r_config>
|
|
220
|
+
|
|
221
|
+
<pre_config>
|
|
222
|
+
<custom_levels>
|
|
223
|
+
Foo,Bar, Baz
|
|
224
|
+
</custom_levels>
|
|
225
|
+
<global level="Bar"/>
|
|
226
|
+
<parameters>
|
|
227
|
+
<logpath>/var/log/foo</logpath>
|
|
228
|
+
<mypattern>%l [%d] %m</mypattern>
|
|
229
|
+
</parameters>
|
|
230
|
+
</pre_config>
|
|
231
|
+
|
|
232
|
+
<!-- define some outputters and loggers -->
|
|
233
|
+
|
|
234
|
+
</log4r_config>
|
|
235
|
+
|
|
236
|
+
== Configuring Log4r Objects
|
|
237
|
+
|
|
238
|
+
The XML configuration grammar for Loggers, Outputters and the like are
|
|
239
|
+
covered in the usage guidelines for those classes.
|
|
240
|
+
|
|
241
|
+
== Order Doesn't Matter
|
|
242
|
+
|
|
243
|
+
You can (it is hoped) define any of the XML objects in any order desired.
|