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.
Files changed (74) hide show
  1. data/doc/content/contact.html +22 -0
  2. data/doc/content/contribute.html +21 -0
  3. data/doc/content/index.html +90 -0
  4. data/doc/content/license.html +56 -0
  5. data/doc/content/manual.html +449 -0
  6. data/doc/dev/README.developers +55 -0
  7. data/doc/dev/checklist +23 -0
  8. data/doc/dev/things-to-do +5 -0
  9. data/doc/images/log4r-logo.png +0 -0
  10. data/doc/images/logo2.png +0 -0
  11. data/doc/log4r.css +111 -0
  12. data/doc/templates/main.html +147 -0
  13. data/examples/README +19 -0
  14. data/examples/customlevels.rb +34 -0
  15. data/examples/fileroll.rb +40 -0
  16. data/examples/log4r_yaml.yaml +0 -0
  17. data/examples/logclient.rb +25 -0
  18. data/examples/logserver.rb +18 -0
  19. data/examples/moderate.xml +29 -0
  20. data/examples/moderateconfig.rb +66 -0
  21. data/examples/myformatter.rb +23 -0
  22. data/examples/outofthebox.rb +21 -0
  23. data/examples/rrconfig.xml +63 -0
  24. data/examples/rrsetup.rb +42 -0
  25. data/examples/simpleconfig.rb +39 -0
  26. data/examples/xmlconfig.rb +25 -0
  27. data/examples/yaml.rb +30 -0
  28. data/src/log4r.rb +17 -0
  29. data/src/log4r/base.rb +74 -0
  30. data/src/log4r/config.rb +9 -0
  31. data/src/log4r/configurator.rb +224 -0
  32. data/src/log4r/formatter/formatter.rb +105 -0
  33. data/src/log4r/formatter/patternformatter.rb +107 -0
  34. data/src/log4r/lib/drbloader.rb +52 -0
  35. data/src/log4r/lib/xmlloader.rb +24 -0
  36. data/src/log4r/logevent.rb +28 -0
  37. data/src/log4r/logger.rb +194 -0
  38. data/src/log4r/loggerfactory.rb +89 -0
  39. data/src/log4r/logserver.rb +28 -0
  40. data/src/log4r/outputter/consoleoutputters.rb +18 -0
  41. data/src/log4r/outputter/datefileoutputter.rb +110 -0
  42. data/src/log4r/outputter/emailoutputter.rb +116 -0
  43. data/src/log4r/outputter/fileoutputter.rb +49 -0
  44. data/src/log4r/outputter/iooutputter.rb +55 -0
  45. data/src/log4r/outputter/outputter.rb +132 -0
  46. data/src/log4r/outputter/outputterfactory.rb +59 -0
  47. data/src/log4r/outputter/remoteoutputter.rb +40 -0
  48. data/src/log4r/outputter/rollingfileoutputter.rb +126 -0
  49. data/src/log4r/outputter/staticoutputter.rb +30 -0
  50. data/src/log4r/outputter/syslogoutputter.rb +75 -0
  51. data/src/log4r/rdoc/configurator +243 -0
  52. data/src/log4r/rdoc/emailoutputter +103 -0
  53. data/src/log4r/rdoc/formatter +39 -0
  54. data/src/log4r/rdoc/log4r +89 -0
  55. data/src/log4r/rdoc/logger +175 -0
  56. data/src/log4r/rdoc/logserver +85 -0
  57. data/src/log4r/rdoc/outputter +108 -0
  58. data/src/log4r/rdoc/patternformatter +128 -0
  59. data/src/log4r/rdoc/syslogoutputter +29 -0
  60. data/src/log4r/rdoc/yamlconfigurator +20 -0
  61. data/src/log4r/repository.rb +65 -0
  62. data/src/log4r/staticlogger.rb +49 -0
  63. data/src/log4r/yamlconfigurator.rb +0 -0
  64. data/tests/README +10 -0
  65. data/tests/testall.rb +6 -0
  66. data/tests/testbase.rb +49 -0
  67. data/tests/testconf.xml +37 -0
  68. data/tests/testcustom.rb +27 -0
  69. data/tests/testformatter.rb +27 -0
  70. data/tests/testlogger.rb +196 -0
  71. data/tests/testoutputter.rb +111 -0
  72. data/tests/testpatternformatter.rb +21 -0
  73. data/tests/testxmlconf.rb +45 -0
  74. metadata +127 -0
@@ -0,0 +1,37 @@
1
+ <test>
2
+ <log4r_config>
3
+
4
+ <pre_config>
5
+ <custom_levels>Foo, Bar,Baz, Bing</custom_levels>
6
+ <global level="Foo"/>
7
+ <parameters>
8
+ <mypattern>[%l] %d %t - %m</mypattern>
9
+ </parameters>
10
+ <parameter name="datem" value="usec"/>
11
+ </pre_config>
12
+
13
+ <!-- level and formatter are optional, -->
14
+ <outputter name="SO" type="StdoutOutputter">
15
+ <level>Foo</level>
16
+ <formatter type="Log4r::PatternFormatter">
17
+ <pattern>%d %c %l&gt; %m</pattern>
18
+ <date_method>#{datem}</date_method>
19
+ </formatter>
20
+ </outputter>
21
+ <outputter name="SE" type="StderrOutputter" level="Baz">
22
+ <formatter type="PatternFormatter" pattern="#{mypattern}">
23
+ <date_pattern>%H:%S</date_pattern>
24
+ </formatter>
25
+ </outputter>
26
+ <outputter name="F" type="FileOutputter">
27
+ <filename>#{logpath}/junk/foo.log</filename>
28
+ <trunc>true</trunc>
29
+ <only_at>Foo, Bar, Bing</only_at>
30
+ </outputter>
31
+ <!-- optional level, additive and outputters -->
32
+ <logger name="first::second" level="Bar" additive="false">
33
+ <trace>true</trace>
34
+ <outputters>SO, SE, F, stdout, stderr</outputters>
35
+ </logger>
36
+ </log4r_config>
37
+ </test>
@@ -0,0 +1,27 @@
1
+
2
+ # tests the customization of Log4r levels
3
+ class TestCustom < TestCase
4
+ def test_validation
5
+ assert_exception(TypeError) { Configurator.custom_levels "lowercase" }
6
+ assert_exception(TypeError) { Configurator.custom_levels "With space" }
7
+ end
8
+
9
+ def test_create
10
+ assert_no_exception { Configurator.custom_levels "Foo", "Bar", "Baz" }
11
+ assert_no_exception { Configurator.custom_levels }
12
+ assert_no_exception { Configurator.custom_levels "Bogus", "Levels" }
13
+ end
14
+ def test_methods
15
+ l = Logger.new 'custom1'
16
+ assert_respond_to(:foo, l)
17
+ assert_respond_to(:foo?, l)
18
+ assert_respond_to(:bar, l)
19
+ assert_respond_to(:bar?, l)
20
+ assert_respond_to(:baz, l)
21
+ assert_respond_to(:baz?, l)
22
+ assert_no_exception(NameError) { Bar }
23
+ assert_no_exception(NameError) { Baz }
24
+ assert_no_exception(NameError) { Foo }
25
+ end
26
+
27
+ end
@@ -0,0 +1,27 @@
1
+ class TestFormatter < TestCase
2
+ def test_creation
3
+ assert_no_exception { Formatter.new.format(3) }
4
+ assert_no_exception { DefaultFormatter.new }
5
+ assert_kind_of(Formatter, DefaultFormatter.new)
6
+ end
7
+ def test_simple_formatter
8
+ sf = SimpleFormatter.new
9
+ f = Logger.new('simple formatter')
10
+ event = LogEvent.new(0, f, nil, "some data")
11
+ assert_match(sf.format(event), /simple formatter/)
12
+ end
13
+ def test_basic_formatter
14
+ b = BasicFormatter.new
15
+ f = Logger.new('fake formatter')
16
+ event = LogEvent.new(0, f, caller, "fake formatter")
17
+ event2 = LogEvent.new(0, f, nil, "fake formatter")
18
+ # this checks for tracing
19
+ assert_match(b.format(event), /in/)
20
+ assert_not_match(b.format(event2), /in/)
21
+ e = ArgumentError.new("argerror")
22
+ e.set_backtrace ['backtrace']
23
+ event3 = LogEvent.new(0, f, nil, e)
24
+ assert_match(b.format(event3), /ArgumentError/)
25
+ assert_match(b.format(LogEvent.new(0,f,nil,[1,2,3])), /Array/)
26
+ end
27
+ end
@@ -0,0 +1,196 @@
1
+ class MyFormatter1 < Formatter
2
+ def format(event)
3
+ return "MyFormatter1\n"
4
+ end
5
+ end
6
+
7
+ class MyFormatter2 < Formatter
8
+ def format(event)
9
+ return "MyFormatter2\n"
10
+ end
11
+ end
12
+
13
+ class TestLogger < TestCase
14
+ def test_root
15
+ l1 = Logger.root
16
+ l2 = Logger['root']
17
+ l3 = Logger.global
18
+ assert(l1 == l2, "RootLogger wasn't singleton!")
19
+ assert(l1 == l3)
20
+ assert(l1.is_root? == true, "is_root? not working")
21
+ assert(l1.parent == nil, "Root's parent wasn't nil!")
22
+ end
23
+ def test_validation
24
+ assert_exception(ArgumentError) { Logger.new }
25
+ assert_no_exception { Logger.new('validate', nil) }
26
+ end
27
+ def test_all_off
28
+ l = Logger.new("create_method")
29
+ l.level = WARN
30
+ assert(l.debug? == false)
31
+ assert(l.info? == false)
32
+ assert(l.warn? == true)
33
+ assert(l.error? == true)
34
+ assert(l.fatal? == true)
35
+ assert(l.off? == false)
36
+ assert(l.all? == false)
37
+ l.level = OFF
38
+ assert(l.off? == true)
39
+ assert(l.all? == false)
40
+ l.level = ALL
41
+ assert(l.off? == false)
42
+ assert(l.all? == true)
43
+ end
44
+ def test_add_outputters
45
+ StdoutOutputter.new('fake1')
46
+ StdoutOutputter.new('fake2')
47
+ a = Logger.new("add")
48
+ assert_exception(TypeError) { a.add 'bogus' }
49
+ assert_exception(TypeError) { a.add Class }
50
+ assert_exception(TypeError) { a.add 'fake1', Class }
51
+ assert_no_exception { a.add 'fake1', 'fake2' }
52
+ end
53
+ def test_repository
54
+ assert_exception(NameError) { Logger.get('bogusbogus') }
55
+ assert_no_exception { Logger['bogusbogus'] }
56
+ end
57
+ def test_heiarchy
58
+ a = Logger.new("a")
59
+ a.additive = true
60
+ assert(a.name == "a", "name wasn't set properly")
61
+ assert(a.path == "", "path wasn't set properly")
62
+ assert(a.level == Logger.root.level, "didn't inherit root's level")
63
+ assert(a.parent == Logger.root)
64
+ a.level = WARN
65
+ b = Logger.new("a::b")
66
+ assert(b.name == "b", "name wasn't set properly")
67
+ assert(b.path == "a", "path wasn't set properly")
68
+ assert(b.level == a.level, "didn't inherit parent's level")
69
+ assert(b.parent == a, "parent wasn't what is expected")
70
+ c = Logger.new("a::b::c")
71
+ assert(Logger["a::b::c"] == c)
72
+ assert(c.name == "c", "name wasn't set properly")
73
+ assert(c.path == "a::b", "path wasn't set properly")
74
+ assert(c.level == b.level, "didn't inherit parent's level")
75
+ assert(c.parent == b, "parent wasn't what is expected")
76
+ d = Logger.new("a::d")
77
+ assert(Logger["a::d"] == d)
78
+ assert(d.name == "d", "name wasn't set properly")
79
+ assert(d.path == "a", "path wasn't set properly")
80
+ assert(d.level == a.level, "didn't inherit parent's level")
81
+ assert(d.parent == a, "parent wasn't what is expected")
82
+ assert_exception(ArgumentError) { Logger.new("::a") }
83
+ end
84
+ def test_undefined_parents
85
+ a = Logger.new 'has::no::real::parents::me'
86
+ assert(a.parent == Logger.root)
87
+ b = Logger.new 'has::no::real::parents::me::child'
88
+ assert(b.parent == a)
89
+ c = Logger.new 'has::no::real::parents::metoo'
90
+ assert(c.parent == Logger.root)
91
+ p = Logger.new 'has::no::real::parents'
92
+ assert(p.parent == Logger.root)
93
+ assert(a.parent == p)
94
+ assert(b.parent == a)
95
+ assert(c.parent == p)
96
+ Logger.each{|fullname, logger|
97
+ if logger != a and logger != c
98
+ assert(logger.parent != p)
99
+ end
100
+ }
101
+ end
102
+ def test_levels
103
+ l = Logger.new("levels", WARN)
104
+ assert(l.level == WARN, "level wasn't changed")
105
+ assert(l.fatal? == true)
106
+ assert(l.error? == true)
107
+ assert(l.warn? == true)
108
+ assert(l.info? == false)
109
+ assert(l.debug? == false)
110
+ l.debug "debug message should NOT show up"
111
+ l.info "info message should NOT show up"
112
+ l.warn "warn messge should show up. 3 total"
113
+ l.error "error messge should show up. 3 total"
114
+ l.fatal "fatal messge should show up. 3 total"
115
+ l.level = ERROR
116
+ assert(l.level == ERROR, "level wasn't changed")
117
+ assert(l.fatal? == true)
118
+ assert(l.error? == true)
119
+ assert(l.warn? == false)
120
+ assert(l.info? == false)
121
+ assert(l.debug? == false)
122
+ l.debug "debug message should NOT show up"
123
+ l.info "info message should NOT show up"
124
+ l.warn "warn messge should NOT show up."
125
+ l.error "error messge should show up. 2 total"
126
+ l.fatal "fatal messge should show up. 2 total"
127
+ l.level = WARN
128
+ end
129
+ def test_log_blocks
130
+ l = Logger.new 'logblocks'
131
+ l.level = WARN
132
+ l.add(Outputter.stdout)
133
+ assert_no_exception {
134
+ l.debug { puts "should not show up"; "LOGBLOCKS" }
135
+ l.fatal { puts "should show up"; "LOGBLOCKS" }
136
+ l.fatal { nil }
137
+ l.fatal {}
138
+ }
139
+ end
140
+ def test_heiarchial_logging
141
+ a = Logger.new("one")
142
+ a.add(StdoutOutputter.new 'so1')
143
+ b = Logger.new("one::two")
144
+ b.add(StdoutOutputter.new 'so2')
145
+ c = Logger.new("one::two::three")
146
+ c.add(StdoutOutputter.new 'so3')
147
+ d = Logger.new("one::two::three::four")
148
+ d.add(StdoutOutputter.new 'so4')
149
+ d.additive = false
150
+ e = Logger.new("one::two::three::four::five")
151
+ e.add(StdoutOutputter.new 'so5')
152
+
153
+ a.fatal "statement from a should show up once"
154
+ b.fatal "statement from b should show up twice"
155
+ c.fatal "statement from c should show up thrice"
156
+ d.fatal "statement from d should show up once"
157
+ e.fatal "statement from e should show up twice"
158
+ end
159
+ def test_multi_outs
160
+ f1 = FileOutputter.new('f1', :filename => "./junk/tmp1.log", :level=>ALL)
161
+ f2 = FileOutputter.new('f2', :filename => "./junk/tmp2.log", :level=>DEBUG)
162
+ f3 = FileOutputter.new('f3', :filename => "./junk/tmp3.log", :level=>ERROR)
163
+ f4 = FileOutputter.new('f4', :filename => "./junk/tmp4.log", :level=>FATAL)
164
+
165
+ l = Logger.new("multi")
166
+ l.add(f1, f3, f4)
167
+
168
+ a = Logger.new("multi::multi2")
169
+ a.level = ERROR
170
+ a.add(f2, f4)
171
+
172
+ l.debug "debug test_multi_outputters"
173
+ l.info "info test_multi_outputters"
174
+ l.warn "warn test_multi_outputters"
175
+ l.error "error test_multi_outputters"
176
+ l.fatal "fatal test_multi_outputters"
177
+
178
+ a.debug "debug test_multi_outputters"
179
+ a.info "info test_multi_outputters"
180
+ a.warn "warn test_multi_outputters"
181
+ a.error "error test_multi_outputters"
182
+ a.fatal "fatal test_multi_outputters"
183
+
184
+ f1.close; f2.close; f3.close; f4.close
185
+ end
186
+ def test_custom_formatter
187
+ l = Logger.new('custom_formatter')
188
+ o = StdoutOutputter.new('formatter'=>MyFormatter1.new)
189
+ l.add o
190
+ l.error "try myformatter1"
191
+ l.fatal "try myformatter1"
192
+ o.formatter = MyFormatter2.new
193
+ l.error "try formatter2"
194
+ l.fatal "try formatter2"
195
+ end
196
+ end
@@ -0,0 +1,111 @@
1
+
2
+ class TestOutputter < TestCase
3
+ def test_validation
4
+ assert_exception(ArgumentError) { Outputter.new }
5
+ assert_exception(ArgumentError) { Outputter.new 'fonda', :level=>-10}
6
+ assert_exception(TypeError) { Outputter.new 'fonda', :formatter=>-10}
7
+ end
8
+ def test_io
9
+ assert_no_exception {
10
+ IOOutputter.new('foo3', $stdout)
11
+ IOOutputter.new('foo4', $stderr)
12
+ }
13
+ f = File.new("junk/tmpx.log", "w")
14
+ o = IOOutputter.new('asdf', f)
15
+ o.close
16
+ assert(f.closed? == true)
17
+ assert(o.level == OFF)
18
+ end
19
+ def test_repository
20
+ assert( Outputter['foo3'].type == IOOutputter )
21
+ assert( Outputter['foo4'].type == IOOutputter )
22
+ assert( Outputter['asdf'].type == IOOutputter )
23
+ end
24
+ def test_validation_and_creation
25
+ assert_no_exception {
26
+ StdoutOutputter.new('out', 'level'=>DEBUG)
27
+ FileOutputter.new('file', 'filename'=>'junk/test', :trunc=>true)
28
+ }
29
+ a = StdoutOutputter.new 'out2'
30
+ assert(a.level == Logger.root.level)
31
+ assert(a.formatter.type == DefaultFormatter)
32
+ b = StdoutOutputter.new('ook', :level => DEBUG, :formatter => Formatter)
33
+ assert(b.level == DEBUG)
34
+ assert(b.formatter.type == Formatter)
35
+ c = StdoutOutputter.new('akk', :formatter => Formatter)
36
+ assert(c.level == Logger.root.level)
37
+ assert(c.formatter.type == Formatter)
38
+ c = StderrOutputter.new('iikk', :level => OFF)
39
+ assert(c.level == OFF)
40
+ assert(c.formatter.type == DefaultFormatter)
41
+ o = StderrOutputter.new 'ik'
42
+ assert_no_exception(TypeError) { o.formatter = DefaultFormatter }
43
+ assert_equals(o.formatter.type, DefaultFormatter)
44
+ end
45
+ # test the resource= bounds
46
+ def test_boundaries
47
+ o = StderrOutputter.new('ak', :formatter => Formatter)
48
+ assert_exception(TypeError) { o.formatter = nil }
49
+ assert_exception(TypeError) { o.formatter = String }
50
+ assert_exception(TypeError) { o.formatter = "bogus" }
51
+ assert_exception(TypeError) { o.formatter = -3 }
52
+ # the formatter should be preserved
53
+ assert(o.formatter.type == Formatter)
54
+ end
55
+ def test_file
56
+ assert_exception(TypeError) { FileOutputter.new 'f' }
57
+ assert_exception(TypeError) { FileOutputter.new('fa', :filename => DEBUG) }
58
+ assert_exception(TypeError) { FileOutputter.new('fo', :filename => nil) }
59
+ assert_no_exception {
60
+ FileOutputter.new('fi', :filename => './junk/tmp')
61
+ FileOutputter.new('fum', :filename=>'./junk/tmp', :trunc => "true")
62
+ }
63
+ fo = FileOutputter.new('food', :filename => './junk/tmp', :trunc => false)
64
+ assert(fo.trunc == false)
65
+ assert(fo.filename == './junk/tmp')
66
+ assert(fo.closed? == false)
67
+ fo.close
68
+ assert(fo.closed? == true)
69
+ assert(fo.level == OFF)
70
+ end
71
+ # test the dynamic definition of outputter log messages
72
+ def test_log_methods
73
+ o = StderrOutputter.new('so1', :level => WARN )
74
+ # test to see if all of the methods are defined
75
+ for mname in LNAMES
76
+ next if mname == 'OFF' || mname == 'ALL'
77
+ assert_respond_to(mname.downcase, o, "Test respond to #{mname.to_s}")
78
+ end
79
+ return # cuz the rest is borked
80
+ # we rely on BasicFormatter's inability to reference a nil Logger to test
81
+ # the log methods. Everything from WARN to FATAL should choke.
82
+ event = LogEvent.new(nil, nil, nil, nil)
83
+ assert_no_exception { o.debug event }
84
+ assert_no_exception { o.info event }
85
+ assert_exception(NameError) { o.warn event }
86
+ assert_exception(NameError) { o.error event }
87
+ assert_exception(NameError) { o.fatal event }
88
+ # now let's dynamically change the level and repeat
89
+ o.level = ERROR
90
+ assert_no_exception { o.debug event}
91
+ assert_no_exception { o.info event}
92
+ assert_no_exception { o.warn event}
93
+ assert_exception(NameError) { o.error event}
94
+ assert_exception(NameError) { o.fatal event}
95
+ end
96
+ def test_only_at_validation
97
+ o = StdoutOutputter.new 'so2'
98
+ assert_exception(ArgumentError) { o.only_at }
99
+ assert_exception(ArgumentError) { o.only_at ALL }
100
+ assert_exception(TypeError) { o.only_at OFF }
101
+ assert_no_exception { o.only_at DEBUG, ERROR }
102
+ return # cuz the rest is borked
103
+ # test the methods as before
104
+ event = LogEvent.new(nil,nil,nil,nil)
105
+ assert_exception(NameError) { o.debug event}
106
+ assert_exception(NameError) { o.error event}
107
+ assert_no_exception { o.warn event}
108
+ assert_no_exception { o.info event}
109
+ assert_no_exception { o.fatal event}
110
+ end
111
+ end
@@ -0,0 +1,21 @@
1
+ class TestPatternFormatter < TestCase
2
+ def test_pattern
3
+ l = Logger.new 'test::this::that'
4
+ l.trace = true
5
+ o = StdoutOutputter.new 'test'
6
+ l.add o
7
+ assert_no_exception {
8
+ f = PatternFormatter.new :pattern=> "%d %6l [%C]%c %% %-40.30M"
9
+ #:date_pattern=> "%Y"
10
+ #:date_method => :usec
11
+ Outputter['test'].formatter = f
12
+ l.debug "And this?"
13
+ l.info "How's this?"
14
+ l.error "and a really freaking huge line which we hope will be trimmed?"
15
+ e = ArgumentError.new("something barfed")
16
+ e.set_backtrace Array.new(5, "trace junk at thisfile.rb 154")
17
+ l.fatal e
18
+ l.info [1, 3, 5]
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+
2
+ One=<<-EOX
3
+ <log4r_config><pre_config><custom_levels> Foo </custom_levels>
4
+ </pre_config></log4r_config>
5
+ EOX
6
+ Two=<<-EOX
7
+ <log4r_config><pre_config><global level="DEBUG"/></pre_config></log4r_config>
8
+ EOX
9
+ Three=<<-EOX
10
+ <log4r_config><pre_config><custom_levels>Foo</custom_levels>
11
+ <global level="Foo"/></pre_config>
12
+ </log4r_config>
13
+ EOX
14
+
15
+ # must be run independently
16
+ class TestXmlConf < TestCase
17
+ def test_load1
18
+ Configurator.load_xml_string(One)
19
+ assert_no_exception{
20
+ assert(Foo == 1)
21
+ assert(Logger.global.level == ALL)
22
+ }
23
+ end
24
+ def test_load2
25
+ Configurator.load_xml_string(Two)
26
+ assert_no_exception{
27
+ assert(Logger.global.level == DEBUG)
28
+ }
29
+ end
30
+ def test_load3
31
+ Configurator.load_xml_string(Three)
32
+ assert_no_exception{
33
+ assert(Foo == 1)
34
+ assert(Logger.global.level == Foo)
35
+ }
36
+ end
37
+ def test_load4
38
+ assert_no_exception {
39
+ Configurator['logpath'] = '.'
40
+ Configurator.load_xml_file "xml/testconf.xml"
41
+ a = Logger['first::second']
42
+ a.bing "what the heck"
43
+ }
44
+ end
45
+ end