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.
Files changed (77) 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 +40 -0
  7. data/doc/dev/checklist +14 -0
  8. data/doc/dev/things-to-do +2 -0
  9. data/doc/images/crush/logo2.png +0 -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/old/manual.html +348 -0
  14. data/doc/templates/main.html +147 -0
  15. data/examples/README +19 -0
  16. data/examples/customlevels.rb +34 -0
  17. data/examples/fileroll.rb +40 -0
  18. data/examples/log4r_yaml.yaml +0 -0
  19. data/examples/logclient.rb +25 -0
  20. data/examples/logserver.rb +18 -0
  21. data/examples/moderate.xml +29 -0
  22. data/examples/moderateconfig.rb +66 -0
  23. data/examples/myformatter.rb +23 -0
  24. data/examples/outofthebox.rb +21 -0
  25. data/examples/rrconfig.xml +63 -0
  26. data/examples/rrsetup.rb +42 -0
  27. data/examples/simpleconfig.rb +39 -0
  28. data/examples/xmlconfig.rb +25 -0
  29. data/examples/yaml.rb +30 -0
  30. data/src/log4r.rb +17 -0
  31. data/src/log4r/base.rb +74 -0
  32. data/src/log4r/config.rb +9 -0
  33. data/src/log4r/configurator.rb +224 -0
  34. data/src/log4r/formatter/formatter.rb +105 -0
  35. data/src/log4r/formatter/patternformatter.rb +108 -0
  36. data/src/log4r/lib/drbloader.rb +52 -0
  37. data/src/log4r/lib/xmlloader.rb +24 -0
  38. data/src/log4r/logevent.rb +28 -0
  39. data/src/log4r/logger.rb +194 -0
  40. data/src/log4r/loggerfactory.rb +89 -0
  41. data/src/log4r/logserver.rb +28 -0
  42. data/src/log4r/outputter/consoleoutputters.rb +18 -0
  43. data/src/log4r/outputter/datefileoutputter.rb +110 -0
  44. data/src/log4r/outputter/emailoutputter.rb +115 -0
  45. data/src/log4r/outputter/fileoutputter.rb +49 -0
  46. data/src/log4r/outputter/iooutputter.rb +55 -0
  47. data/src/log4r/outputter/outputter.rb +132 -0
  48. data/src/log4r/outputter/outputterfactory.rb +59 -0
  49. data/src/log4r/outputter/remoteoutputter.rb +40 -0
  50. data/src/log4r/outputter/rollingfileoutputter.rb +126 -0
  51. data/src/log4r/outputter/staticoutputter.rb +30 -0
  52. data/src/log4r/outputter/syslogoutputter.rb +75 -0
  53. data/src/log4r/rdoc/configurator +243 -0
  54. data/src/log4r/rdoc/emailoutputter +103 -0
  55. data/src/log4r/rdoc/formatter +39 -0
  56. data/src/log4r/rdoc/log4r +89 -0
  57. data/src/log4r/rdoc/logger +175 -0
  58. data/src/log4r/rdoc/logserver +85 -0
  59. data/src/log4r/rdoc/outputter +108 -0
  60. data/src/log4r/rdoc/patternformatter +128 -0
  61. data/src/log4r/rdoc/syslogoutputter +29 -0
  62. data/src/log4r/rdoc/yamlconfigurator +20 -0
  63. data/src/log4r/repository.rb +65 -0
  64. data/src/log4r/staticlogger.rb +49 -0
  65. data/src/log4r/yamlconfigurator.rb +0 -0
  66. data/tests/include.rb +7 -0
  67. data/tests/runtest.rb +6 -0
  68. data/tests/testbase.rb +45 -0
  69. data/tests/testcustom.rb +33 -0
  70. data/tests/testdefault.rb +25 -0
  71. data/tests/testformatter.rb +29 -0
  72. data/tests/testlogger.rb +198 -0
  73. data/tests/testoutputter.rb +112 -0
  74. data/tests/testpatternformatter.rb +26 -0
  75. data/tests/testxmlconf.rb +51 -0
  76. data/tests/xml/testconf.xml +37 -0
  77. metadata +140 -0
@@ -0,0 +1,29 @@
1
+ = SyslogOutputter
2
+
3
+ A SyslogOutputter transforms a Log4r::LogEvent into a call to syslog().
4
+ Since syslog has its own formatting system, log4r formatters are ignored.
5
+
6
+ == Usage
7
+
8
+ To use,
9
+
10
+ <tt>require 'log4r/outputter/syslogoutputter'</tt>
11
+
12
+ An example,
13
+
14
+ require 'log4r'
15
+ require 'log4r/outputter/syslogoutputter'
16
+
17
+ syslog = Log4r::SyslogOutputter.new("name", 'logopt'=>#, 'facility'=>#)
18
+ syslog.err("this is an ERR message")
19
+
20
+ The output in <tt>/var/logs/syslog</tt> (Debian) is,
21
+
22
+ Sep 3 11:43:06 tiphares sys[1603]: this is an ERR message
23
+
24
+ The hash arguments +logoptions+ and +facility+ are passed to
25
+ <tt>Syslog.open</tt>. The
26
+ defaults are <tt>LOG_PID | LOG_CONS</tt> and <tt>LOG_USER</tt> respectively.
27
+
28
+ This is a first try implementation. It works well. Please report
29
+ any bugs and fixes.
@@ -0,0 +1,20 @@
1
+ = Configuring Log4r with Log4r::YamlConfigurator
2
+
3
+ The YamlConfigurator class allows one to set up Log4r via YAML.
4
+ It is used almost exactly as Log4r::Configurator and has the same features,
5
+
6
+ ycfg = YamlConfigurator # handy shorthand
7
+ ycfg['foo'] = bar # replaces instances of #{foo} in the YAML with bar
8
+ ycfg.load_yaml_file('foo.yaml')
9
+
10
+ Ruby 1.7 and 1.8 comes with a YAML parser. Hence, YAML can be used
11
+ to configure Log4r out of the box.
12
+
13
+ A comprehensive example of a Log4r YAML configuration is provided in the
14
+ examples directory.
15
+
16
+ To use this class:
17
+
18
+ require 'log4r/yamlconfigurator'
19
+
20
+ Thanks to Andreas Hund for making this possible.
@@ -0,0 +1,65 @@
1
+ # :nodoc:
2
+ # Version:: $Id: repository.rb,v 1.10 2002/08/20 07:40:26 cepheus Exp $
3
+
4
+ require "singleton"
5
+
6
+ module Log4r
7
+ class Logger
8
+
9
+ # The repository stores a Hash of loggers keyed to their fullnames and
10
+ # provides a few functions to reduce the code bloat in log4r/logger.rb.
11
+ # This class is supposed to be transparent to end users, hence it is
12
+ # a class within Logger. If anyone knows how to make this private,
13
+ # let me know.
14
+
15
+ class Repository # :nodoc:
16
+ include Singleton
17
+ attr_reader :loggers
18
+
19
+ def initialize
20
+ @loggers = Hash.new
21
+ end
22
+
23
+ def self.[](fullname)
24
+ instance.loggers[fullname]
25
+ end
26
+
27
+ def self.[]=(fullname, logger)
28
+ instance.loggers[fullname] = logger
29
+ end
30
+
31
+ # Retrieves all children of a parent
32
+ def self.all_children(parent)
33
+ # children have the parent name + delimiter in their fullname
34
+ daddy = parent.name + Private::Config::LoggerPathDelimiter
35
+ for fullname, logger in instance.loggers
36
+ yield logger if parent.is_root? || fullname =~ /#{daddy}/
37
+ end
38
+ end
39
+
40
+ # when new loggers are introduced, they may get inserted into
41
+ # an existing inheritance tree. this method
42
+ # updates the children of a logger to link their new parent
43
+ def self.reassign_any_children(parent)
44
+ for fullname, logger in instance.loggers
45
+ next if logger.is_root?
46
+ logger.parent = parent if logger.path =~ /^#{parent.fullname}$/
47
+ end
48
+ end
49
+
50
+ # looks for the first defined logger in a child's path
51
+ # or nil if none found (which will then be rootlogger)
52
+ def self.find_ancestor(path)
53
+ arr = path.split Log4rConfig::LoggerPathDelimiter
54
+ logger = nil
55
+ while arr.size > 0 do
56
+ logger = Repository[arr.join(Log4rConfig::LoggerPathDelimiter)]
57
+ break unless logger.nil?
58
+ arr.pop
59
+ end
60
+ logger
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,49 @@
1
+ # :nodoc:
2
+ module Log4r
3
+ class Logger
4
+ # Returns the root logger. Identical to Logger.global
5
+ def self.root; return RootLogger.instance end
6
+ # Returns the root logger. Identical to Logger.root
7
+ def self.global; return root end
8
+
9
+ # Get a logger with a fullname from the repository or nil if logger
10
+ # wasn't found.
11
+
12
+ def self.[](_fullname)
13
+ # forces creation of RootLogger if it doesn't exist yet.
14
+ return RootLogger.instance if _fullname=='root' or _fullname=='global'
15
+ Repository[_fullname]
16
+ end
17
+
18
+ # Like Logger[] except that it raises NameError if Logger wasn't found.
19
+
20
+ def self.get(_fullname)
21
+ logger = self[_fullname]
22
+ if logger.nil?
23
+ raise NameError, "Logger '#{_fullname}' not found.", caller
24
+ end
25
+ logger
26
+ end
27
+
28
+ # Yields fullname and logger for every logger in the system.
29
+ def self.each
30
+ for fullname, logger in Repository.instance.loggers
31
+ yield fullname, logger
32
+ end
33
+ end
34
+
35
+ def self.each_logger
36
+ Repository.instance.loggers.each_value {|logger| yield logger}
37
+ end
38
+
39
+ # Internal logging for Log4r components. Accepts only blocks.
40
+ # To see such log events, create a logger named 'log4r' and give
41
+ # it an outputter.
42
+
43
+ def self.log_internal(level=1)
44
+ internal = Logger['log4r']
45
+ return if internal.nil?
46
+ internal.send(LNAMES[level].downcase, yield)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,7 @@
1
+ $:.push("../src")
2
+ require 'runit/testcase'
3
+ require "log4r"
4
+ require "log4r/configurator"
5
+
6
+ include Log4r
7
+ include RUNIT
@@ -0,0 +1,6 @@
1
+ system "ruby testcustom.rb"
2
+ system "ruby testbase.rb"
3
+ system "ruby testdefault.rb"
4
+ for i in 1..4
5
+ system "ruby testxmlconf.rb #{i}"
6
+ end
@@ -0,0 +1,45 @@
1
+ require "include"
2
+ require "runit/cui/testrunner"
3
+
4
+ # must be run independently
5
+ class TestBase < TestCase
6
+ def test_default_const
7
+ Logger.root # create the default levels
8
+ assert_equal(ALL,0)
9
+ assert_equal(DEBUG,1)
10
+ assert_equal(INFO,2)
11
+ assert_equal(WARN,3)
12
+ assert_equal(ERROR,4)
13
+ assert_equal(FATAL,5)
14
+ assert_equal(OFF,6)
15
+ assert_equal(LEVELS, 7)
16
+ assert_equal(LNAMES.size, 7)
17
+ end
18
+ def test_validate
19
+ 7.times{|i| assert_no_exception {Log4rTools.validate_level(i)} }
20
+ assert_exception(ArgumentError) {Log4rTools.validate_level(-1)}
21
+ assert_exception(ArgumentError) {Log4rTools.validate_level(LEVELS)}
22
+ assert_exception(ArgumentError) {Log4rTools.validate_level(String)}
23
+ assert_exception(ArgumentError) {Log4rTools.validate_level("bogus")}
24
+ end
25
+ def test_decode_bool
26
+ assert(Log4rTools.decode_bool({:data=>'true'},:data,false) == true)
27
+ assert(Log4rTools.decode_bool({:data=>true},:data,false) == true)
28
+ assert(Log4rTools.decode_bool({:data=>'false'},:data,true) == false)
29
+ assert(Log4rTools.decode_bool({:data=>false},:data,true) == false)
30
+ assert(Log4rTools.decode_bool({:data=>nil},:data,true) == true)
31
+ assert(Log4rTools.decode_bool({:data=>nil},:data,false) == false)
32
+ assert(Log4rTools.decode_bool({:data=>String},:data,true) == true)
33
+ assert(Log4rTools.decode_bool({:data=>String},:data,false) == false)
34
+ assert(Log4rTools.decode_bool({'data'=>'true'},:data,false) == true)
35
+ assert(Log4rTools.decode_bool({'data'=>true},:data,false) == true)
36
+ assert(Log4rTools.decode_bool({'data'=>'false'},:data,true) == false)
37
+ assert(Log4rTools.decode_bool({'data'=>false},:data,true) == false)
38
+ assert(Log4rTools.decode_bool({'data'=>nil},:data,true) == true)
39
+ assert(Log4rTools.decode_bool({'data'=>nil},:data,false) == false)
40
+ assert(Log4rTools.decode_bool({'data'=>String},:data,true) == true)
41
+ assert(Log4rTools.decode_bool({'data'=>String},:data,false) == false)
42
+ end
43
+ end
44
+
45
+ CUI::TestRunner.run(TestBase.suite)
@@ -0,0 +1,33 @@
1
+ require "include"
2
+ require "runit/cui/testrunner"
3
+
4
+ # tests the customization of Log4r levels
5
+ class TestCustom < TestCase
6
+ def test_validation
7
+ assert_exception(TypeError) { Configurator.custom_levels "lowercase" }
8
+ assert_exception(TypeError) { Configurator.custom_levels "With space" }
9
+ end
10
+
11
+ def test_create
12
+ assert_no_exception { Configurator.custom_levels "Foo", "Bar", "Baz" }
13
+ assert_no_exception { Configurator.custom_levels }
14
+ assert_no_exception { Configurator.custom_levels "Bogus", "Levels" }
15
+ end
16
+ def test_methods
17
+ l = Logger.new 'custom1'
18
+ assert_respond_to(:foo, l)
19
+ assert_respond_to(:foo?, l)
20
+ assert_respond_to(:bar, l)
21
+ assert_respond_to(:bar?, l)
22
+ assert_respond_to(:baz, l)
23
+ assert_respond_to(:baz?, l)
24
+ assert_no_exception(NameError) { Bar }
25
+ assert_no_exception(NameError) { Baz }
26
+ assert_no_exception(NameError) { Foo }
27
+ end
28
+
29
+ end
30
+
31
+ CUI::TestRunner.run(TestCustom.new("test_validation"))
32
+ CUI::TestRunner.run(TestCustom.new("test_create"))
33
+ CUI::TestRunner.run(TestCustom.new("test_methods"))
@@ -0,0 +1,25 @@
1
+ # actually, tests only the following:
2
+ require "testlogger"
3
+ require "testoutputter"
4
+ require "testformatter"
5
+ require "testpatternformatter"
6
+
7
+ require "runit/testsuite"
8
+ require "runit/cui/testrunner"
9
+
10
+ class TestDefault
11
+ def TestDefault.suite
12
+ suite = TestSuite.new
13
+ for k in Object.constants.sort
14
+ next if /^Test/ !~ k
15
+ const = Object.const_get(k)
16
+ if const.kind_of?(Class) && const.superclass == RUNIT::TestCase
17
+ suite.add(const.suite)
18
+ end
19
+ end
20
+ suite
21
+ end
22
+ end
23
+
24
+ CUI::TestRunner.run(TestDefault.suite)
25
+
@@ -0,0 +1,29 @@
1
+ require "include"
2
+
3
+ class TestFormatter < TestCase
4
+ def test_creation
5
+ assert_no_exception { Formatter.new.format(3) }
6
+ assert_no_exception { DefaultFormatter.new }
7
+ assert_kind_of(Formatter, DefaultFormatter.new)
8
+ end
9
+ def test_simple_formatter
10
+ sf = SimpleFormatter.new
11
+ f = Logger.new('simple formatter')
12
+ event = LogEvent.new(0, f, nil, "some data")
13
+ assert_match(sf.format(event), /simple formatter/)
14
+ end
15
+ def test_basic_formatter
16
+ b = BasicFormatter.new
17
+ f = Logger.new('fake formatter')
18
+ event = LogEvent.new(0, f, caller, "fake formatter")
19
+ event2 = LogEvent.new(0, f, nil, "fake formatter")
20
+ # this checks for tracing
21
+ assert_match(b.format(event), /in/)
22
+ assert_not_match(b.format(event2), /in/)
23
+ e = ArgumentError.new("argerror")
24
+ e.set_backtrace ['backtrace']
25
+ event3 = LogEvent.new(0, f, nil, e)
26
+ assert_match(b.format(event3), /ArgumentError/)
27
+ assert_match(b.format(LogEvent.new(0,f,nil,[1,2,3])), /Array/)
28
+ end
29
+ end
@@ -0,0 +1,198 @@
1
+ require "include"
2
+
3
+ class MyFormatter1 < Formatter
4
+ def format(event)
5
+ return "MyFormatter1\n"
6
+ end
7
+ end
8
+
9
+ class MyFormatter2 < Formatter
10
+ def format(event)
11
+ return "MyFormatter2\n"
12
+ end
13
+ end
14
+
15
+ class TestLogger < TestCase
16
+ def test_root
17
+ l1 = Logger.root
18
+ l2 = Logger['root']
19
+ l3 = Logger.global
20
+ assert(l1 == l2, "RootLogger wasn't singleton!")
21
+ assert(l1 == l3)
22
+ assert(l1.is_root? == true, "is_root? not working")
23
+ assert(l1.parent == nil, "Root's parent wasn't nil!")
24
+ end
25
+ def test_validation
26
+ assert_exception(ArgumentError) { Logger.new }
27
+ assert_no_exception { Logger.new('validate', nil) }
28
+ end
29
+ def test_all_off
30
+ l = Logger.new("create_method")
31
+ l.level = WARN
32
+ assert(l.debug? == false)
33
+ assert(l.info? == false)
34
+ assert(l.warn? == true)
35
+ assert(l.error? == true)
36
+ assert(l.fatal? == true)
37
+ assert(l.off? == false)
38
+ assert(l.all? == false)
39
+ l.level = OFF
40
+ assert(l.off? == true)
41
+ assert(l.all? == false)
42
+ l.level = ALL
43
+ assert(l.off? == false)
44
+ assert(l.all? == true)
45
+ end
46
+ def test_add_outputters
47
+ StdoutOutputter.new('fake1')
48
+ StdoutOutputter.new('fake2')
49
+ a = Logger.new("add")
50
+ assert_exception(TypeError) { a.add 'bogus' }
51
+ assert_exception(TypeError) { a.add Class }
52
+ assert_exception(TypeError) { a.add 'fake1', Class }
53
+ assert_no_exception { a.add 'fake1', 'fake2' }
54
+ end
55
+ def test_repository
56
+ assert_exception(NameError) { Logger.get('bogusbogus') }
57
+ assert_no_exception { Logger['bogusbogus'] }
58
+ end
59
+ def test_heiarchy
60
+ a = Logger.new("a")
61
+ a.additive = true
62
+ assert(a.name == "a", "name wasn't set properly")
63
+ assert(a.path == "", "path wasn't set properly")
64
+ assert(a.level == Logger.root.level, "didn't inherit root's level")
65
+ assert(a.parent == Logger.root)
66
+ a.level = WARN
67
+ b = Logger.new("a::b")
68
+ assert(b.name == "b", "name wasn't set properly")
69
+ assert(b.path == "a", "path wasn't set properly")
70
+ assert(b.level == a.level, "didn't inherit parent's level")
71
+ assert(b.parent == a, "parent wasn't what is expected")
72
+ c = Logger.new("a::b::c")
73
+ assert(Logger["a::b::c"] == c)
74
+ assert(c.name == "c", "name wasn't set properly")
75
+ assert(c.path == "a::b", "path wasn't set properly")
76
+ assert(c.level == b.level, "didn't inherit parent's level")
77
+ assert(c.parent == b, "parent wasn't what is expected")
78
+ d = Logger.new("a::d")
79
+ assert(Logger["a::d"] == d)
80
+ assert(d.name == "d", "name wasn't set properly")
81
+ assert(d.path == "a", "path wasn't set properly")
82
+ assert(d.level == a.level, "didn't inherit parent's level")
83
+ assert(d.parent == a, "parent wasn't what is expected")
84
+ assert_exception(ArgumentError) { Logger.new("::a") }
85
+ end
86
+ def test_undefined_parents
87
+ a = Logger.new 'has::no::real::parents::me'
88
+ assert(a.parent == Logger.root)
89
+ b = Logger.new 'has::no::real::parents::me::child'
90
+ assert(b.parent == a)
91
+ c = Logger.new 'has::no::real::parents::metoo'
92
+ assert(c.parent == Logger.root)
93
+ p = Logger.new 'has::no::real::parents'
94
+ assert(p.parent == Logger.root)
95
+ assert(a.parent == p)
96
+ assert(b.parent == a)
97
+ assert(c.parent == p)
98
+ Logger.each{|fullname, logger|
99
+ if logger != a and logger != c
100
+ assert(logger.parent != p)
101
+ end
102
+ }
103
+ end
104
+ def test_levels
105
+ l = Logger.new("levels", WARN)
106
+ assert(l.level == WARN, "level wasn't changed")
107
+ assert(l.fatal? == true)
108
+ assert(l.error? == true)
109
+ assert(l.warn? == true)
110
+ assert(l.info? == false)
111
+ assert(l.debug? == false)
112
+ l.debug "debug message should NOT show up"
113
+ l.info "info message should NOT show up"
114
+ l.warn "warn messge should show up. 3 total"
115
+ l.error "error messge should show up. 3 total"
116
+ l.fatal "fatal messge should show up. 3 total"
117
+ l.level = ERROR
118
+ assert(l.level == ERROR, "level wasn't changed")
119
+ assert(l.fatal? == true)
120
+ assert(l.error? == true)
121
+ assert(l.warn? == false)
122
+ assert(l.info? == false)
123
+ assert(l.debug? == false)
124
+ l.debug "debug message should NOT show up"
125
+ l.info "info message should NOT show up"
126
+ l.warn "warn messge should NOT show up."
127
+ l.error "error messge should show up. 2 total"
128
+ l.fatal "fatal messge should show up. 2 total"
129
+ l.level = WARN
130
+ end
131
+ def test_log_blocks
132
+ l = Logger.new 'logblocks'
133
+ l.level = WARN
134
+ l.add(Outputter.stdout)
135
+ assert_no_exception {
136
+ l.debug { puts "should not show up"; "LOGBLOCKS" }
137
+ l.fatal { puts "should show up"; "LOGBLOCKS" }
138
+ l.fatal { nil }
139
+ l.fatal {}
140
+ }
141
+ end
142
+ def test_heiarchial_logging
143
+ a = Logger.new("one")
144
+ a.add(StdoutOutputter.new 'so1')
145
+ b = Logger.new("one::two")
146
+ b.add(StdoutOutputter.new 'so2')
147
+ c = Logger.new("one::two::three")
148
+ c.add(StdoutOutputter.new 'so3')
149
+ d = Logger.new("one::two::three::four")
150
+ d.add(StdoutOutputter.new 'so4')
151
+ d.additive = false
152
+ e = Logger.new("one::two::three::four::five")
153
+ e.add(StdoutOutputter.new 'so5')
154
+
155
+ a.fatal "statement from a should show up once"
156
+ b.fatal "statement from b should show up twice"
157
+ c.fatal "statement from c should show up thrice"
158
+ d.fatal "statement from d should show up once"
159
+ e.fatal "statement from e should show up twice"
160
+ end
161
+ def test_multi_outs
162
+ f1 = FileOutputter.new('f1', :filename => "./junk/tmp1.log", :level=>ALL)
163
+ f2 = FileOutputter.new('f2', :filename => "./junk/tmp2.log", :level=>DEBUG)
164
+ f3 = FileOutputter.new('f3', :filename => "./junk/tmp3.log", :level=>ERROR)
165
+ f4 = FileOutputter.new('f4', :filename => "./junk/tmp4.log", :level=>FATAL)
166
+
167
+ l = Logger.new("multi")
168
+ l.add(f1, f3, f4)
169
+
170
+ a = Logger.new("multi::multi2")
171
+ a.level = ERROR
172
+ a.add(f2, f4)
173
+
174
+ l.debug "debug test_multi_outputters"
175
+ l.info "info test_multi_outputters"
176
+ l.warn "warn test_multi_outputters"
177
+ l.error "error test_multi_outputters"
178
+ l.fatal "fatal test_multi_outputters"
179
+
180
+ a.debug "debug test_multi_outputters"
181
+ a.info "info test_multi_outputters"
182
+ a.warn "warn test_multi_outputters"
183
+ a.error "error test_multi_outputters"
184
+ a.fatal "fatal test_multi_outputters"
185
+
186
+ f1.close; f2.close; f3.close; f4.close
187
+ end
188
+ def test_custom_formatter
189
+ l = Logger.new('custom_formatter')
190
+ o = StdoutOutputter.new('formatter'=>MyFormatter1.new)
191
+ l.add o
192
+ l.error "try myformatter1"
193
+ l.fatal "try myformatter1"
194
+ o.formatter = MyFormatter2.new
195
+ l.error "try formatter2"
196
+ l.fatal "try formatter2"
197
+ end
198
+ end