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,40 @@
1
+ This document introduces interested developers to log4r development.
2
+
3
+
4
+ HTML manual and site
5
+ --------------------
6
+
7
+ This is pieced together with a homebrewed content-template system.
8
+ doc/content has the actual contents, which are just three lines of metadata
9
+ and a bunch of <tr>s that are incorporated into a template. The only template
10
+ is doc/templates/main.html which is universal. To test the changes, run
11
+ bin/makedoc.rb directly and check the results in doc/index.html.
12
+
13
+
14
+ Testing RDoc
15
+ ------------
16
+ Either run bin/makerdoc.rb directly or,
17
+
18
+ cd src/
19
+ rdoc --op /tmp/rdoc --template kilmer --main log4r.rb
20
+
21
+
22
+ Automated Builds
23
+ ----------------
24
+
25
+ The build system is automated and relies on CVS and ruby. There are three main
26
+ things that go on during build:
27
+
28
+ 1) bin/makedist.rb checks out a build to prepare for distribution and calls
29
+ other build scripts, then assembles the distribution into tgz and zip balls
30
+
31
+ 2) HTML manual is constructed by bin/makehtml.rb, called from makedist.rb
32
+
33
+ 3) RDoc is constructed by bin/makerdoc.rb, called from makedist.rb
34
+
35
+ All system variables and configurable options are in bin/devconfig.rb.
36
+
37
+ Essentially, the only thing that needs to be done to build packages for
38
+ distribution is,
39
+
40
+ ruby makedist.rb <version-number>
@@ -0,0 +1,14 @@
1
+ Distribution checklist:
2
+
3
+ * DON'T FORGET: change install.rb when new src/ files are added
4
+ * DON'T FORGET: change the log4r.gemspec file for same
5
+ * Update the changelog
6
+ * Update the README
7
+ * Change any INSTALL instructions
8
+ * Update the manuals and HTML
9
+ * Modify what should not appear in the release (bin/prune.rb)
10
+ * Run makedist.rb and check the integrity of the resulting tarballs
11
+ - Test installs
12
+ - Run the unit tests (cd tests; ruby runtest.rb)
13
+ - Run all the examples
14
+ - Browse the docs
@@ -0,0 +1,2 @@
1
+ * Rewrite the RDoc in third person (no "you"s)
2
+ * Trap any remaining parameters in the Configurators
Binary file
Binary file
@@ -0,0 +1,111 @@
1
+ body {
2
+ background-color: #FFFFFF;
3
+ font-family:sans-serif;
4
+ }
5
+
6
+ a:link { color:#014DA3 }
7
+ a:active { color:#AA0000 }
8
+ a:visited { color:#014DA3 }
9
+ a:hoover { color:#AA0000 }
10
+
11
+ .example {
12
+ font-family: monospace;
13
+ border:1px solid #007;
14
+ background:#FFFFFF;
15
+ margin:1em;
16
+ }
17
+
18
+ pre.box {
19
+ margin:0px 1em 1em 1em;
20
+ color:#AA0000;
21
+ }
22
+
23
+ .menu {
24
+ font-family:sans-serif;
25
+ font-size:10px;
26
+ border-left: 1px solid #AA0000;
27
+ border-right: 1px solid #AA0000;
28
+ border-bottom: 1px solid #AA0000;
29
+ background:#EEEEEE;
30
+ color:#AA0000;
31
+ }
32
+
33
+ .menutitle {
34
+ font-family:sans-serif;
35
+ font-size:medium;
36
+ color:#FFFFFF;
37
+ font-weight:bold;
38
+ background:#AA0000;
39
+ border-right: 1px solid #AA0000;
40
+ border-left: 1px solid #AA0000;
41
+ border-top: 1px solid #AA0000;
42
+ border-bottom: 1px solid #AA0000;
43
+ }
44
+
45
+ .menubuff {
46
+ font-family:sans-serif;
47
+ font-size:1px;
48
+ color:#000000;
49
+ border-left: 1px solid #AA0000;
50
+ border-right: 1px solid #AA0000;
51
+ font-weight:bold;
52
+ background-color: #99CCFF;
53
+ height:5;
54
+ padding-bottom: 0;
55
+ }
56
+
57
+ .contentbuff {
58
+ font-family:sans-serif;
59
+ font-size:10px;
60
+ border-left: 1px solid #AA0000;
61
+ border-right: 1px solid #AA0000;
62
+ font-weight:bold;
63
+ background-color: #99CCFF;
64
+ height:5;
65
+ padding-bottom: 0;
66
+ }
67
+
68
+ .header {
69
+ font-family:sans-serif;
70
+ color:#AA0000;
71
+ }
72
+
73
+ .content {
74
+ font-family:sans-serif;
75
+ font-size:medium;
76
+ color:#000000;
77
+ background:#EEEEEE;
78
+ border-right: 2px solid #AA0000;
79
+ border-left: 2px solid #AA0000;
80
+ border-bottom: 2px solid #AA0000;
81
+ padding-bottom: 5;
82
+ padding-right: 5;
83
+ padding-left: 5;
84
+ padding-top: 0;
85
+ }
86
+ .contenttitle {
87
+ font-family:sans-serif;
88
+ font-size:medium;
89
+ color:#FFFFFF;
90
+ font-weight:bold;
91
+ background-color:#AA0000;
92
+ border-left: 2px solid #AA0000;
93
+ border-top: 1px solid #AA0000;
94
+ border-right: 2px solid #AA0000;
95
+ padding: 2;
96
+ }
97
+
98
+ .contentbuff {
99
+ font-family:sans-serif;
100
+ font-size:10px;
101
+ color:#014DA3;
102
+ border-left: 2px solid #AA0000;
103
+ border-right: 2px solid #AA0000;
104
+ font-weight:bold;
105
+ background-color:#99CCFF;
106
+ height:13;
107
+ padding-bottom: 0;
108
+ }
109
+
110
+ br { padding-bottom: 200 }
111
+
@@ -0,0 +1,348 @@
1
+ <html>
2
+ <head><title>Log4r - A Powerful Logger for Ruby</title></head>
3
+ <body bgcolor="#FFFFFF">
4
+ <h1><font color="#AA0000">Log4r - A Powerful Logger for Ruby</font></h1>
5
+ Inspired by the
6
+ <a href="http://jakarta.apache.org/log4j/docs/index.html">Apache Log4j</a>
7
+ project
8
+ <hr/>
9
+
10
+ <h4>At a Glance</h4>
11
+
12
+ <blockquote>
13
+ Log4r features an extremely flexible logging library for Ruby.
14
+ Killer features include a heiarchial logging system of any number of
15
+ levels, logger inheritance, multiple output destinations, tracing, custom
16
+ formatting and more.
17
+ <p>
18
+ Log4r was inspired by the very excellent
19
+ <a href="http://jakarta.apache.org/log4j/docs/index.html">
20
+ Apache Log4j Project</a>
21
+ . Log4r provides the defining features of Log4j and some of its own
22
+ features that just might make Log4j users envious. <code>;-)</code>
23
+ <p/>
24
+ The project is hosted on SourceForge:
25
+ <a href="http://sourceforge.net/projects/log4r/">
26
+ http://sourceforge.net/projects/log4r/</a>
27
+ </blockquote>
28
+
29
+ <h4>Download</h4>
30
+
31
+ <blockquote>
32
+ Latest version is
33
+ <a href="http://sourceforge.net/project/showfiles.php?group_id=43396">
34
+ Log4r 0.9.8</a>. All versions are stable. Newer ones have more features.
35
+ <p/>
36
+ The
37
+ <a href="rdoc/index.html">API is available</a>
38
+ in a Javadoc-like format (thanks go to the
39
+ <a href="http://rdoc.sourceforge.net/">RDoc project</a>).
40
+ </blockquote>
41
+
42
+
43
+ <h4>But why?</h4>
44
+
45
+ <blockquote>
46
+ Please read the
47
+ <a href="http://jakarta.apache.org/log4j/docs/index.html">Introduction</a>
48
+ to Apache Log4j for answers. Personally, I find
49
+ that a logging system such as Log4r is essential when writing distributed
50
+ applications, like for a game that has a client/server design. Also, the
51
+ ability to leave logging statements in the code without commenting them out
52
+ is quite handy.
53
+ </blockquote>
54
+
55
+ <h4>Features</h4>
56
+ <blockquote>
57
+ <dl>
58
+ <dt><b><font color="#AA0000">Easy to use</font></b></dt>
59
+ <dd><p/>
60
+ Thanks to Ruby, Log4r is an extremely simple tool to use. It should become
61
+ evident as you read further. <code>;)</code>
62
+ <p/></dd>
63
+ <dt><b><font color="#AA0000">Multiple loggers</font></b></dt>
64
+ <dd>
65
+ <p/>
66
+ You can have as many loggers as desired. Upon creation, they get stored
67
+ in a Singleton repository from which they can be retrieved at any point.
68
+ <pre>
69
+ Log4r::Logger.new('mylogger') # create a logger 'mylogger'
70
+ Log4r::Logger['mylogger'] # get 'mylogger' back
71
+ </pre>
72
+ <p/>
73
+ </dd>
74
+ <dt><b><font color="#AA0000">Heiarchial logging</font></b></dt>
75
+ <dd>
76
+ <p/>
77
+ Log4r provides five levels of logging:
78
+ <code>DEBUG, INFO, WARN, ERROR, FATAL</code>.
79
+ A logger with a certain level will not perform logging for all levels
80
+ below it (less important, if you will). Hence, if a logger is set to
81
+ <code>WARN</code>, it won't log <code>DEBUG</code>, and
82
+ <code>INFO</code> log events.
83
+ <code>ALL</code> and <code>OFF</code> are special
84
+ boundary levels. Setting a logger to <code>ALL</code> will let it see evey log event
85
+ while setting it to <code>OFF</code> will disable all log events. It's not possible
86
+ to log at <code>ALL</code> and <code>OFF</code>.
87
+ <pre>
88
+ include Log4r # include for brevity
89
+
90
+ log = Logger['mylogger']
91
+ log.level = WARN # set log level to Log4r::WARN
92
+
93
+ log.debug "DEBUG log event" # won't show up
94
+ log.info "INFO log event" # ditto
95
+ log.warn "WARN log event" # will show up, and all that follow
96
+ log.error "ERROR log event"
97
+ log.fatal "FATAL log event"
98
+ </pre>
99
+ <br/>
100
+ You can dynamically reassign a logger's level if you want.
101
+ <p/>
102
+ </dd>
103
+ <dt><b><font color="#AA0000">Custom levels</font></b></dt>
104
+ <dd>
105
+ <p/>
106
+ And now, something that will really make Log4j users envious: You can
107
+ change the number and names of the heiarchial logging levels easily.
108
+ Suppose we don't like having 5 levels named <code>DEBUG</code>, <code>INFO</code>, etc.
109
+ Instead, we want <code>Foo</code>, <code>Bar</code>, and <code>Baz</code>.
110
+ Here's how we do it:
111
+ <pre>
112
+ Log4r::Logger.custom_levels 'Foo', 'Bar', 'Baz'
113
+ </pre>
114
+ <br/>
115
+ Thereafter, the logging methods will be named after your custom levels:
116
+ <p/>
117
+ <pre>
118
+ log.level = Log4r::Bar
119
+ log.foo? => false
120
+ log.bar? => true
121
+ log.bar "this is bar" => &lt;Bar&gt; this is bar
122
+ log.baz "this is baz" => &lt;Baz&gt; this is baz
123
+ </pre>
124
+ <p/>
125
+ </dd>
126
+ <dt><b><font color="#AA0000">Multiple output destinations</font></b></dt>
127
+ <dd>
128
+ <p/>
129
+ The second block of code won't do anything because <code>mylogger</code> does
130
+ not have anything to write to. In order to log somewhere, we have to
131
+ create an <b>Outputter</b> and assign it to our logger. We can give our
132
+ logger as many <code>Outputters</code> as we want:
133
+ <pre>
134
+ # continuing from second block
135
+
136
+ f = FileOutputter.new(:filename =&gt; './tmp.log')
137
+ so = StdoutOutputter.new
138
+ se = StderrOutputter.new
139
+ ex = Outputter.new(ExoticIO.new) # outputter with an IO of our own make
140
+ log.add(f, so, se, ex)
141
+ log.error "A test error" # writes to all 4 IOs
142
+ </pre>
143
+ <br/>
144
+ If an <code>IO</code> somehow chokes, the Outputter will set itself to
145
+ <code>OFF</code> and close the <code>IO</code>.
146
+ <p/>
147
+ </dd>
148
+ <dt><b><font color="#AA0000">Root logger, global threshold and Logger inheritance</font></b></dt>
149
+ <dd>
150
+ <p/>
151
+ A logger can inherit another logger. It turns out that every logger
152
+ that you create normally is a child of the <b>root</b> logger.
153
+ The <b>root</b> logger does two things: Provide the global logging level
154
+ and the default level for its immediate children.
155
+ <pre>
156
+ Logger.root.level = ERROR # set global level to ERROR
157
+ Logger.new("alog") # alog inherits ERROR
158
+ </pre>
159
+ <br/>
160
+ From this point on, the only log events (by <b>alog</b> and <b>mylogger</b>)
161
+ that can show up are <code>ERROR</code> and <code>FATAL</code>.
162
+ <p/>
163
+ To have one logger inherit another, specify the name of the parent
164
+ in the argument to <code>Logger.new</code> as follows:
165
+ <code>"parent::child"</code>. Specifying 'root' is optional. Because
166
+ of namespace collision concerns, you need to specify the full path
167
+ to the logger as in <code>foo::bar::baz</code>. The same thing must be done for
168
+ retrieving loggers from the repository:
169
+ <pre>
170
+ Logger.new('mylogger::mychild') # mychild is a child of mylogger
171
+ Logger['mylogger::mychild'] # get mychild back
172
+ </pre>
173
+ <br/>
174
+ A child logger that does not define its level during creation will inherit
175
+ the level of its parent.
176
+ <p/>
177
+ </dd>
178
+ <dt><b><font color="#AA0000">Outputter inheritance</font></b></dt>
179
+ <dd>
180
+ <p/>
181
+ In addition to level, a logger inherits the <code>Outputter</code>s of its
182
+ parent. That is, when <code>mychild</code> performs a logging event, it also
183
+ calls the appropriate logging event for <code>mylogger</code>. This behavior
184
+ is entirely optional and can be turned off by setting a logger's
185
+ <code>additive</code> to false:
186
+ <pre>
187
+ Logger['mylogger::mychild'].additive = false
188
+ </pre>
189
+ <br/>
190
+ Hencenforth, any logging events to mychild will not be sent to mylogger.
191
+ The buck stops here.
192
+ <p/>
193
+ </dd>
194
+ <dt><b><font color="#AA0000">Custom formatting</font></b></dt>
195
+ <dd>
196
+ <p/>
197
+ By default, Log4r is capable of formatting any object passed to it
198
+ by calling its <code>inspect</code> method. It also pre-formats
199
+ <code>Exceptions</code>.
200
+ Changing the way the data is formatted is just a matter of rolling up
201
+ your own <code>Formatter</code> class that defines the method <code>format</code>:
202
+ <pre>
203
+ class MyFormatter < Formatter
204
+ def format(level, logger, tracer, data)
205
+ # level is the integer level of the log event
206
+ # logger is the logger that called it
207
+ # tracer is the execution stack returned by caller at the log event
208
+ # data is what was passed into a logging method
209
+ end
210
+ end
211
+
212
+ afile = FileOutputter.new(:file=>'./prettyformat')
213
+ afile.formatter = MyFormatter.new
214
+ # add it to 'mychild' dynamically
215
+ Logger['mylogger::mychild'].add afile
216
+ </pre>
217
+ <br/>
218
+ Formatters are not inherited, they are assigned to specific outputters.
219
+ <p/>
220
+ </dd>
221
+ <dt><b><font color="#AA0000">Tracing</font></b></dt>
222
+ <dd>
223
+ <p/>
224
+ By default, loggers don't record the execution stack. You can turn on
225
+ tracing by setting a logger's <code>trace</code> to <code>true</code>. It's up to the
226
+ <code>Formatter</code> to handle this information. <code>BasicFormatter</code> displays
227
+ the line number and file of the log event.
228
+ <p/>
229
+ </dd>
230
+ <dt><b><font color="#AA0000">Ways around parameter evaluation</font></b></dt>
231
+ <dd>
232
+ <p/>
233
+ Avoiding parameter evaluation at the log method invocation can be
234
+ critical at times. One way to do this is to pass the object in
235
+ and let the formatter inspect it. The formatter won't be called for
236
+ non-loggable levels. If parameter evaluation is unavoidable, you can
237
+ querry the logger to see if it's logging at a
238
+ particular level. The following querry methods are provided:
239
+ <pre>
240
+ Logger.root.level =&gt; ERROR
241
+ log = Logger['mylogger']
242
+ log.level =&gt; WARN
243
+ log.debug? =&gt; false
244
+ log.warn? =&gt; false
245
+ log.info? =&gt; false
246
+ log.error? =&gt; true
247
+ log.fatal? =&gt; true
248
+ log.off? =&gt; false # true only if OFF is set
249
+ log.all? =&gt; false # true only if ALL is set
250
+ </pre>
251
+ <p/>
252
+ </dd>
253
+ <dt><b><font color="#AA0000">Even more flexibility: Outputter thresholds</font></b></dt>
254
+ <dd>
255
+ <p/>
256
+ Sometimes it's prudent to fix a certain outputter's level in stone, or
257
+ keep it at some independent level with respect to any loggers. (Yes, you
258
+ can share an outputter among loggers.) This can be done fairly easily by
259
+ setting the level of the outputter:
260
+ <pre>
261
+ # console log for mychild that filters out anything less important than ERROR
262
+
263
+ screen = StdoutOutputter.new(:level=>ERROR)
264
+ Logger['mychild'].add(screen)
265
+ </pre>
266
+ <br/>
267
+ And that's not all, we can also tell an Outputter to log only specific
268
+ levels. Here's how:
269
+ <p/>
270
+ <pre>
271
+ # only DEBUG and FATAL on screen
272
+ screen.only_at DEBUG, FATAL
273
+ </pre>
274
+ <p/>
275
+ </dd>
276
+ <dt><b><font color="#AA0000">Thread safe</font></b></dt>
277
+ <dd>
278
+ <p/>
279
+ Logging is thread safe. The formatting and writing to an output are
280
+ synchronized by a simple mutex in each outputter.
281
+ <p/>
282
+ </dd>
283
+ <dt><b><font color="#AA0000">Fast enough!</font></b></dt>
284
+ <dd>
285
+ <p/>
286
+ Profiling has revealed that log4r is typically an order of magnitude or two
287
+ slower than log4j. However, this is still damn fast! In particular,
288
+ if a logger is set to <code>OFF</code>, the overhead of checking to
289
+ see if
290
+ a log event should be logged nearly vanishes. This was accomplished by
291
+ dynamically redefining the unloggable logging methods to do nothing.
292
+ <p/>
293
+ I'd like to point out that if one needs to use something like log4r
294
+ in a performance-critical application, one should recondsider why Ruby
295
+ is being used at all. As far as anyone should be concerned,
296
+ log4r is Fast Enough (TM) for casual and moderate use <code>:)</code>
297
+ <p/>
298
+ Of course, this doesn't mean that we shouldn't improve the performance
299
+ of
300
+ log4r! When the time comes, it will be written as a C extension to Ruby.
301
+ <p/>
302
+ </dd>
303
+ </dl>
304
+
305
+ </blockquote>
306
+
307
+ <h4>Gotchas</h4>
308
+
309
+ If you are using Log4r, there are a few gotchas that you should be aware of:
310
+ <ul>
311
+ <li>Logger levels, tracing and additivity can be dynamically
312
+ redefined, but the changes won't be noticed by any children. That is, if
313
+ you set <code>root.level=OFF</code> after defining some loggers,
314
+ none of the loggers will change their level to <code>OFF</code>,
315
+ </li>
316
+ <li>However, if a parent changes its Outputters, its children will
317
+ recognize the change.
318
+ </li>
319
+ <li>Dynamically redefining levels, tracing and additivity is a costly
320
+ operation. It's best to set up all your loggers in a config script and
321
+ leave well enough alone. The dynamism is useful for debugging as you can
322
+ toggel tracing and level from within the file you're working on.
323
+ </li>
324
+ <li>When an <code>Outputter</code>'s <code>IO</code> is closed, the
325
+ <code>Outputter</code> changes its level to <code>OFF</code>
326
+ </li>
327
+ </ul>
328
+
329
+ <h4>The Future</h4>
330
+ <blockquote>
331
+ Log4r is mostly done. It was written in about 3 days and does enough to be
332
+ useful for most cases. There is still room for improvement performance-wise
333
+ and maybe the C extension is nigh.
334
+ </blockquote>
335
+
336
+ <h4>Obligatory SourceForge Link</h4>
337
+ <blockquote>
338
+ <A href="http://sourceforge.net"> <IMG
339
+ src="http://sourceforge.net/sflogo.php?group_id=43396" width="88" height="31"
340
+ border="0" alt="SourceForge Logo"></A>
341
+ </blockquote>
342
+ <p/>
343
+ <hr/>
344
+ <i><a href="mailto:leon@to.ugcs.caltech.edu">leon@ugcs.caltech.edu</a></i>
345
+ $Id: manual.html,v 1.1 2002/01/16 12:27:05 cepheus Exp $
346
+
347
+ </body>
348
+ </html>