11;
2
3__END__
4
5=head1 NAME
6
7Log::Log4perl::FAQ - Frequently Asked Questions on Log::Log4perl
8
9=head1 DESCRIPTION
10
11This FAQ shows a wide variety of
12commonly encountered logging tasks and how to solve them
13in the most elegant way with Log::Log4perl. Most of the time, this will
14be just a matter of smartly configuring your Log::Log4perl configuration files.
15
16=head2 Why use Log::Log4perl instead of any other logging module on CPAN?
17
18That's a good question. There's dozens of logging modules on CPAN.
19When it comes to logging, people typically think: "Aha. Writing out
20debug and error messages. Debug is lower than error. Easy. I'm gonna
21write my own." Writing a logging module is like a rite of passage for
22every Perl programmer, just like writing your own templating system.
23
24Of course, after getting the basics right, features need to
25be added. You'd like to write a timestamp with every message. Then
26timestamps with microseconds. Then messages need to be written to both
27the screen and a log file.
28
29And, as your application grows in size you might wonder: Why doesn't
30my logging system scale along with it? You would like to switch on
31logging in selected parts of the application, and not all across the
32board, because this kills performance. This is when people turn to
33Log::Log4perl, because it handles all of that.
34
35Avoid this costly switch.
36
37Use C<Log::Log4perl> right from the start. C<Log::Log4perl>'s C<:easy>
38mode supports easy logging in simple scripts:
39
40    use Log::Log4perl qw(:easy);
41    Log::Log4perl->easy_init($DEBUG);
42
43    DEBUG "A low-level message";
44    ERROR "Won't make it until level gets increased to ERROR";
45
46And when your application inevitably grows, your logging system grows
47with it without you having to change any code.
48
49Please, don't re-invent logging. C<Log::Log4perl> is here, it's easy
50to use, it scales, and covers many areas you haven't thought of yet,
51but will enter soon.
52
53=head2 What's the easiest way to use Log4perl?
54
55If you just want to get all the comfort of logging, without much
56overhead, use I<Stealth Loggers>. If you use Log::Log4perl in
57C<:easy> mode like
58
59    use Log::Log4perl qw(:easy);
60
61you'll have the following functions available in the current package:
62
63    DEBUG("message");
64    INFO("message");
65    WARN("message");
66    ERROR("message");
67    FATAL("message");
68
69Just make sure that every package of your code where you're using them in
70pulls in C<use Log::Log4perl qw(:easy)> first, then you're set.
71Every stealth logger's category will be equivalent to the name of the
72package it's located in.
73
74These stealth loggers
75will be absolutely silent until you initialize Log::Log4perl in
76your main program with either
77
78        # Define any Log4perl behavior
79    Log::Log4perl->init("foo.conf");
80
81(using a full-blown Log4perl config file) or the super-easy method
82
83        # Just log to STDERR
84    Log::Log4perl->easy_init($DEBUG);
85
86or the parameter-style method with a complexity somewhat in between:
87
88        # Append to a log file
89    Log::Log4perl->easy_init( { level   => $DEBUG,
90                                file    => ">>test.log" } );
91
92For more info, please check out L<Log::Log4perl/"Stealth Loggers">.
93
94=head2 How can I simply log all my ERROR messages to a file?
95
96After pulling in the C<Log::Log4perl> module, just initialize its
97behavior by passing in a configuration to its C<init> method as a string
98reference. Then, obtain a logger instance and write out a message
99with its C<error()> method:
100
101    use Log::Log4perl qw(get_logger);
102
103        # Define configuration
104    my $conf = q(
105        log4perl.logger                    = ERROR, FileApp
106        log4perl.appender.FileApp          = Log::Log4perl::Appender::File
107        log4perl.appender.FileApp.filename = test.log
108        log4perl.appender.FileApp.layout   = PatternLayout
109        log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n
110    );
111
112        # Initialize logging behavior
113    Log::Log4perl->init( \$conf );
114
115        # Obtain a logger instance
116    my $logger = get_logger("Bar::Twix");
117    $logger->error("Oh my, a dreadful error!");
118    $logger->warn("Oh my, a dreadful warning!");
119
120This will append something like
121
122    2002/10/29 20:11:55> Oh my, a dreadful error!
123
124to the log file C<test.log>. How does this all work?
125
126While the Log::Log4perl C<init()> method typically
127takes the name of a configuration file as its input parameter like
128in
129
130    Log::Log4perl->init( "/path/mylog.conf" );
131
132the example above shows how to pass in a configuration as text in a
133scalar reference.
134
135The configuration as shown
136defines a logger of the root category, which has an appender of type
137C<Log::Log4perl::Appender::File> attached. The line
138
139    log4perl.logger = ERROR, FileApp
140
141doesn't list a category, defining a root logger. Compare that with
142
143    log4perl.logger.Bar.Twix = ERROR, FileApp
144
145which would define a logger for the category C<Bar::Twix>,
146showing probably different behavior. C<FileApp> on
147the right side of the assignment is
148an arbitrarily defined variable name, which is only used to somehow
149reference an appender defined later on.
150
151Appender settings in the configuration are defined as follows:
152
153    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
154    log4perl.appender.FileApp.filename = test.log
155
156It selects the file appender of the C<Log::Log4perl::Appender>
157hierarchy, which will append to the file C<test.log> if it already
158exists. If we wanted to overwrite a potentially existing file, we would
159have to explicitly set the appropriate C<Log::Log4perl::Appender::File>
160parameter C<mode>:
161
162    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
163    log4perl.appender.FileApp.filename = test.log
164    log4perl.appender.FileApp.mode     = write
165
166Also, the configuration defines a PatternLayout format, adding
167the nicely formatted current date and time, an arrow (E<gt>) and
168a space before the messages, which is then followed by a newline:
169
170    log4perl.appender.FileApp.layout   = PatternLayout
171    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n
172
173Obtaining a logger instance and actually logging something is typically
174done in a different system part as the Log::Log4perl initialisation section,
175but in this example, it's just done right after init for the
176sake of compactness:
177
178        # Obtain a logger instance
179    my $logger = get_logger("Bar::Twix");
180    $logger->error("Oh my, a dreadful error!");
181
182This retrieves an instance of the logger of the category C<Bar::Twix>,
183which, as all other categories, inherits behavior from the root logger if no
184other loggers are defined in the initialization section.
185
186The C<error()>
187method fires up a message, which the root logger catches. Its
188priority is equal to
189or higher than the root logger's priority (ERROR), which causes the root logger
190to forward it to its attached appender. By contrast, the following
191
192    $logger->warn("Oh my, a dreadful warning!");
193
194doesn't make it through, because the root logger sports a higher setting
195(ERROR and up) than the WARN priority of the message.
196
197=head2 How can I install Log::Log4perl on Microsoft Windows?
198
199Log::Log4perl is fully supported on the Win32 platform. It has been tested
200with Activestate perl 5.6.1 under Windows 98 and rumor has it that it
201also runs smoothly on all other major flavors (Windows NT, 2000, XP, etc.).
202
203It also runs nicely with ActiveState 5.8.0, and, believe me,
204we had to jump through some major hoops for that.
205
206Typically, Win32 systems don't have the C<make> utility installed,
207so the standard C<perl Makefile.PL; make install> on the downloadable
208distribution won't work. But don't despair, there's a very easy solution!
209
210The C<Log::Log4perl> homepage provides a so-called PPD file for ActiveState's
211C<ppm> installer, which comes with ActiveState perl by default.
212
213=over 4
214
215=item Install on ActiveState 5.6.*
216
217The DOS command line
218
219    ppm install "http://log4perl.sourceforge.net/ppm/Log-Log4perl.ppd"
220
221will contact the Log4perl homepage, download the latest
222C<Log::Log4perl>
223distribution and install it. If your ActiveState installation
224lacks any of the modules C<Log::Log4perl> depends upon, C<ppm> will
225automatically contact ActivateState and download them from their CPAN-like
226repository.
227
228=item Install on ActiveState 5.8.*
229
230ActiveState's "Programmer's Package Manager" can be called from
231Window's Start Menu:
232Start-E<gt>Programs->E<gt>ActiveState ActivePerl 5.8E<gt>Perl Package Manager
233will invoke ppm. Since Log::Log4perl hasn't made it yet into the standard
234ActiveState repository (and you probably don't want their outdated packages
235anyway), just tell ppm the first time you call it to add the Log4perl
236repository
237
238    ppm> repository add http://log4perl.sourceforge.net/ppm
239
240Then, just tell it to install Log::Log4perl and it will resolve all
241dependencies automatically and fetch them from log4perl.sourceforge.net
242if it can't find them in the main archives:
243
244    ppm> install Log-Log4perl
245
246=back
247
248That's it! Afterwards, just create a Perl script like
249
250    use Log::Log4perl qw(:easy);
251    Log::Log4perl->easy_init($DEBUG);
252
253    my $logger = get_logger("Twix::Bar");
254    $logger->debug("Watch me!");
255
256and run it. It should print something like
257
258    2002/11/06 01:22:05 Watch me!
259
260If you find that something doesn't work, please let us know at
261log4perl-devel@lists.sourceforge.net -- we'll apprechiate it. Have fun!
262
263=head2 How can I include global (thread-specific) data in my log messages?
264
265Say, you're writing a web application and want all your
266log messages to include the current client's IP address. Most certainly,
267you don't want to include it in each and every log message like in
268
269    $logger->debug( $r->connection->remote_ip,
270                    " Retrieving user data from DB" );
271
272do you? Instead, you want to set it in a global data structure and
273have Log::Log4perl include it automatically via a PatternLayout setting
274in the configuration file:
275
276    log4perl.appender.FileApp.layout.ConversionPattern = %X{ip} %m%n
277
278The conversion specifier C<%X{ip}> references an entry under the key
279C<ip> in the global C<MDC> (mapped diagnostic context) table, which
280you've set once via
281
282    Log::Log4perl::MDC->put("ip", $r->connection->remote_ip);
283
284at the start of the request handler. Note that this is a
285I<static> (class) method, there's no logger object involved.
286You can use this method with as many key/value pairs as you like as long
287as you reference them under different names.
288
289The mappings are stored in a global hash table within Log::Log4perl.
290Luckily, because the thread
291model in 5.8.0 doesn't share global variables between threads unless
292they're explicitly marked as such, there's no problem with multi-threaded
293environments.
294
295For more details on the MDC, please refer to
296L<Log::Log4perl/"Mapped Diagnostic Context (MDC)"> and
297L<Log::Log4perl::MDC>.
298
299=head2 My application is already logging to a file. How can I duplicate all messages to also go to the screen?
300
301Assuming that you already have a Log4perl configuration file like
302
303    log4perl.logger                    = DEBUG, FileApp
304
305    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
306    log4perl.appender.FileApp.filename = test.log
307    log4perl.appender.FileApp.layout   = PatternLayout
308    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n
309
310and log statements all over your code,
311it's very easy with Log4perl to have the same messages both printed to
312the logfile and the screen. No reason to change your code, of course,
313just add another appender to the configuration file and you're done:
314
315    log4perl.logger                    = DEBUG, FileApp, ScreenApp
316
317    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
318    log4perl.appender.FileApp.filename = test.log
319    log4perl.appender.FileApp.layout   = PatternLayout
320    log4perl.appender.FileApp.layout.ConversionPattern = %d> %m%n
321
322    log4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen
323    log4perl.appender.ScreenApp.stderr   = 0
324    log4perl.appender.ScreenApp.layout   = PatternLayout
325    log4perl.appender.ScreenApp.layout.ConversionPattern = %d> %m%n
326
327The configuration file above is assuming that both appenders are
328active in the same logger hierarchy, in this case the C<root> category.
329But even if you've got file loggers defined in several parts of your system,
330belonging to different logger categories,
331each logging to different files, you can gobble up all logged messages
332by defining a root logger with a screen appender, which would duplicate
333messages from all your file loggers to the screen due to Log4perl's
334appender inheritance. Check
335
336    http://www.perl.com/pub/a/2002/09/11/log4perl.html
337
338for details. Have fun!
339
340=head2 How can I make sure my application logs a message when it dies unexpectedly?
341
342Whenever you encounter a fatal error in your application, instead of saying
343something like
344
345    open FILE, "<blah" or die "Can't open blah -- bailing out!";
346
347just use Log::Log4perl's fatal functions instead:
348
349    my $log = get_logger("Some::Package");
350    open FILE, "<blah" or $log->logdie("Can't open blah -- bailing out!");
351
352This will both log the message with priority FATAL according to your current
353Log::Log4perl configuration and then call Perl's C<die()>
354afterwards to terminate the program. It works the same with
355stealth loggers (see L<Log::Log4perl/"Stealth Loggers">),
356all you need to do is call
357
358    use Log::Log4perl qw(:easy);
359    open FILE, "<blah" or LOGDIE "Can't open blah -- bailing out!";
360
361What can you do if you're using some library which doesn't use Log::Log4perl
362and calls C<die()> internally if something goes wrong? Use a
363C<$SIG{__DIE__}> pseudo signal handler
364
365    use Log::Log4perl qw(get_logger);
366
367    $SIG{__DIE__} = sub {
368        if($^S) {
369            # We're in an eval {} and don't want log
370            # this message but catch it later
371            return;
372        }
373        local $Log::Log4perl::caller_depth =
374              $Log::Log4perl::caller_depth + 1;
375        my $logger = get_logger("");
376        $logger->fatal(@_);
377        die @_; # Now terminate really
378    };
379
380This will catch every C<die()>-Exception of your
381application or the modules it uses. In case you want to
382It
383will fetch a root logger and pass on the C<die()>-Message to it.
384If you make sure you've configured with a root logger like this:
385
386    Log::Log4perl->init(\q{
387        log4perl.category         = FATAL, Logfile
388        log4perl.appender.Logfile = Log::Log4perl::Appender::File
389        log4perl.appender.Logfile.filename = fatal_errors.log
390        log4perl.appender.Logfile.layout = \
391                   Log::Log4perl::Layout::PatternLayout
392        log4perl.appender.Logfile.layout.ConversionPattern = %F{1}-%L (%M)> %m%n
393    });
394
395then all C<die()> messages will be routed to a file properly. The line
396
397     local $Log::Log4perl::caller_depth =
398           $Log::Log4perl::caller_depth + 1;
399
400in the pseudo signal handler above merits a more detailed explanation. With
401the setup above, if a module calls C<die()> in one of its functions,
402the fatal message will be logged in the signal handler and not in the
403original function -- which will cause the %F, %L and %M placeholders
404in the pattern layout to be replaced by the filename, the line number
405and the function/method name of the signal handler, not the error-throwing
406module. To adjust this, Log::Log4perl has the C<$caller_depth> variable,
407which defaults to 0, but can be set to positive integer values
408to offset the caller level. Increasing
409it by one will cause it to log the calling function's parameters, not
410the ones of the signal handler.
411See L<Log::Log4perl/"Using Log::Log4perl from wrapper classes"> for more
412details.
413
414=head2 How can I hook up the LWP library with Log::Log4perl?
415
416Or, to put it more generally: How can you utilize a third-party
417library's embedded logging and debug statements in Log::Log4perl?
418How can you make them print
419to configurable appenders, turn them on and off, just as if they
420were regular Log::Log4perl logging statements?
421
422The easiest solution is to map the third-party library logging statements
423to Log::Log4perl's stealth loggers via a typeglob assignment.
424
425As an example, let's take LWP, one of the most popular Perl modules,
426which makes handling WWW requests and responses a breeze.
427Internally, LWP uses its own logging and debugging system,
428utilizing the following calls
429inside the LWP code (from the LWP::Debug man page):
430
431        # Function tracing
432    LWP::Debug::trace('send()');
433
434        # High-granular state in functions
435    LWP::Debug::debug('url ok');
436
437        # Data going over the wire
438    LWP::Debug::conns("read $n bytes: $data");
439
440First, let's assign Log::Log4perl priorities
441to these functions: I'd suggest that
442C<debug()> messages have priority C<INFO>,
443C<trace()> uses C<DEBUG> and C<conns()> also logs with C<DEBUG> --
444although your mileage may certainly vary.
445
446Now, in order to transpartently hook up LWP::Debug with Log::Log4perl,
447all we have to do is say
448
449    package LWP::Debug;
450    use Log::Log4perl qw(:easy);
451
452    *trace = *INFO;
453    *conns = *DEBUG;
454    *debug = *DEBUG;
455
456    package main;
457    # ... go on with your regular program ...
458
459at the beginning of our program. In this way, every time the, say,
460C<LWP::UserAgent> module calls C<LWP::Debug::trace()>, it will implicitely
461call INFO(), which is the C<info()> method of a stealth logger defined for
462the Log::Log4perl category C<LWP::Debug>. Is this cool or what?
463
464Here's a complete program:
465
466    use LWP::UserAgent;
467    use HTTP::Request::Common;
468    use Log::Log4perl qw(:easy);
469
470    Log::Log4perl->easy_init(
471        { category => "LWP::Debug",
472          level    => $DEBUG,
473          layout   => "%r %p %M-%L %m%n",
474        });
475
476    package LWP::Debug;
477    use Log::Log4perl qw(:easy);
478    *trace = *INFO;
479    *conns = *DEBUG;
480    *debug = *DEBUG;
481
482    package main;
483    my $ua = LWP::UserAgent->new();
484    my $resp = $ua->request(GET "http://amazon.com");
485
486    if($resp->is_success()) {
487        print "Success: Received ",
488              length($resp->content()), "\n";
489    } else {
490        print "Error: ", $resp->code(), "\n";
491    }
492
493This will generate the following output on STDERR:
494
495    174 INFO LWP::UserAgent::new-164 ()
496    208 INFO LWP::UserAgent::request-436 ()
497    211 INFO LWP::UserAgent::send_request-294 GET http://amazon.com
498    212 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
499    405 INFO LWP::Protocol::http::request-122 ()
500    859 DEBUG LWP::Protocol::collect-206 read 233 bytes
501    863 DEBUG LWP::UserAgent::request-443 Simple response: Found
502    869 INFO LWP::UserAgent::request-436 ()
503    871 INFO LWP::UserAgent::send_request-294
504     GET http://www.amazon.com:80/exec/obidos/gateway_redirect
505    872 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
506    873 INFO LWP::Protocol::http::request-122 ()
507    1016 DEBUG LWP::UserAgent::request-443 Simple response: Found
508    1020 INFO LWP::UserAgent::request-436 ()
509    1022 INFO LWP::UserAgent::send_request-294
510     GET http://www.amazon.com/exec/obidos/subst/home/home.html/
511    1023 DEBUG LWP::UserAgent::_need_proxy-1123 Not proxied
512    1024 INFO LWP::Protocol::http::request-122 ()
513    1382 DEBUG LWP::Protocol::collect-206 read 632 bytes
514    ...
515    2605 DEBUG LWP::Protocol::collect-206 read 77 bytes
516    2607 DEBUG LWP::UserAgent::request-443 Simple response: OK
517    Success: Received 42584
518
519Of course, in this way, the embedded logging and debug statements within
520LWP can be utilized in any Log::Log4perl way you can think of. You can
521have them sent to different appenders, block them based on the
522category and everything else Log::Log4perl has to offer.
523
524Only drawback of this method: Steering logging behavior via category
525is always based on the C<LWP::Debug> package. Although the logging
526statements reflect the package name of the issuing module properly,
527the stealth loggers in C<LWP::Debug> are all of the category C<LWP::Debug>.
528This implies that you can't control the logging behavior based on the
529package that's I<initiating> a log request (e.g. LWP::UserAgent) but only
530based on the package that's actually I<executing> the logging statement,
531C<LWP::Debug> in this case.
532
533To work around this conundrum, we need to write a wrapper function and
534plant it into the C<LWP::Debug> package. It will determine the caller and
535create a logger bound to a category with the same name as the caller's
536package:
537
538    package LWP::Debug;
539
540    use Log::Log4perl qw(:levels get_logger);
541
542    sub l4p_wrapper {
543        my($prio, @message) = @_;
544        $Log::Log4perl::caller_depth += 2;
545        get_logger(scalar caller(1))->log($prio, @message);
546        $Log::Log4perl::caller_depth -= 2;
547    }
548
549    no warnings 'redefine';
550    *trace = sub { l4p_wrapper($INFO, @_); };
551    *debug = *conns = sub { l4p_wrapper($DEBUG, @_); };
552
553    package main;
554    # ... go on with your main program ...
555
556This is less performant than the previous approach, because every
557log request will request a reference to a logger first, then call
558the wrapper, which will in turn call the appropriate log function.
559
560This hierarchy shift has to be compensated for by increasing
561C<$Log::Log4perl::caller_depth> by 2 before calling the log function
562and decreasing it by 2 right afterwards. Also, the C<l4p_wrapper>
563function shown above calls C<caller(1)> which determines the name
564of the package I<two> levels down the calling hierarchy (and
565therefore compensates for both the wrapper function and the
566anonymous subroutine calling it).
567
568C<no warnings 'redefine'> suppresses a warning Perl would generate
569otherwise
570upon redefining C<LWP::Debug>'s C<trace()>, C<debug()> and C<conns()>
571functions. In case you use a perl prior to 5.6.x, you need
572to manipulate C<$^W> instead.
573
574To make things easy for you when dealing with LWP, Log::Log4perl 0.47
575introduces C<Log::Log4perl-E<gt>infiltrate_lwp()> which does exactly the
576above.
577
578=head2 What if I need dynamic values in a static Log4perl configuration file?
579
580Say, your application uses Log::Log4perl for logging and
581therefore comes with a Log4perl configuration file, specifying the logging
582behavior.
583But, you also want it to take command line parameters to set values
584like the name of the log file.
585How can you have
586both a static Log4perl configuration file and a dynamic command line
587interface?
588
589As of Log::Log4perl 0.28, every value in the configuration file
590can be specified as a I<Perl hook>. So, instead of saying
591
592    log4perl.appender.Logfile.filename = test.log
593
594you could just as well have a Perl subroutine deliver the value
595dynamically:
596
597    log4perl.appender.Logfile.filename = sub { logfile(); };
598
599given that C<logfile()> is a valid function in your C<main> package
600returning a string containing the path to the log file.
601
602Or, think about using the value of an environment variable:
603
604    log4perl.appender.DBI.user = sub { $ENV{USERNAME} };
605
606When C<Log::Log4perl-E<gt>init()> parses the configuration
607file, it will notice the assignment above because of its
608C<sub {...}> pattern and treat it in a special way:
609It will evaluate the subroutine (which can contain
610arbitrary Perl code) and take its return value as the right side
611of the assignment.
612
613A typical application would be called like this on the command line:
614
615    app                # log file is "test.log"
616    app -l mylog.txt   # log file is "mylog.txt"
617
618Here's some sample code implementing the command line interface above:
619
620    use Log::Log4perl qw(get_logger);
621    use Getopt::Std;
622
623    getopt('l:', \our %OPTS);
624
625    my $conf = q(
626    log4perl.category.Bar.Twix         = WARN, Logfile
627    log4perl.appender.Logfile          = Log::Log4perl::Appender::File
628    log4perl.appender.Logfile.filename = sub { logfile(); };
629    log4perl.appender.Logfile.layout   = SimpleLayout
630    );
631
632    Log::Log4perl::init(\$conf);
633
634    my $logger = get_logger("Bar::Twix");
635    $logger->error("Blah");
636
637    ###########################################
638    sub logfile {
639    ###########################################
640        if(exists $OPTS{l}) {
641            return $OPTS{l};
642        } else {
643            return "test.log";
644        }
645    }
646
647Every Perl hook may contain arbitrary perl code,
648just make sure to fully qualify eventual variable names
649(e.g. C<%main::OPTS> instead of C<%OPTS>).
650
651B<SECURITY NOTE>: this feature means arbitrary perl code
652can be embedded in the config file.  In the rare case
653where the people who have access to your config file
654are different from the people who write your code and
655shouldn't have execute rights, you might want to call
656
657    $Log::Log4perl::Config->allow_code(0);
658
659before you call init(). This will prevent Log::Log4perl from
660executing I<any> Perl code in the config file (including
661code for custom conversion specifiers
662(see L<Log::Log4perl::Layout::PatternLayout/"Custom cspecs">).
663
664=head2 How can I roll over my logfiles automatically at midnight?
665
666Long-running applications tend to produce ever-increasing logfiles.
667For backup and cleanup purposes, however, it is often desirable to move
668the current logfile to a different location from time to time and
669start writing a new one.
670
671This is a non-trivial task, because it has to happen in sync with
672the logging system in order not to lose any messages in the process.
673
674Luckily, I<Mark Pfeiffer>'s C<Log::Dispatch::FileRotate> appender
675works well with Log::Log4perl to rotate your logfiles in a variety of ways.
676
677Note, however, that having the application deal with rotating a log
678file is not cheap. Among other things, it requires locking the log file
679with every write to avoid race conditions.
680There are good reasons to use external rotators like C<newsyslog>
681instead.
682See the entry C<How can I rotate a logfile with newsyslog?> in the
683FAQ for more information on how to configure it.
684
685When using C<Log::Dispatch::FileRotate>,
686all you have to do is specify it in your Log::Log4perl configuration file
687and your logfiles will be rotated automatically.
688
689You can choose between rolling based on a maximum size ("roll if greater
690than 10 MB") or based on a date pattern ("roll everyday at midnight").
691In both cases, C<Log::Dispatch::FileRotate> allows you to define a
692number C<max> of saved files to keep around until it starts overwriting
693the oldest ones. If you set the C<max> parameter to 2 and the name of
694your logfile is C<test.log>, C<Log::Dispatch::FileRotate> will
695move C<test.log> to C<test.log.1> on the first rollover. On the second
696rollover, it will move C<test.log.1> to C<test.log.2> and then C<test.log>
697to C<test.log.1>. On the third rollover, it will move C<test.log.1> to
698C<test.log.2> (therefore discarding the old C<test.log.2>) and
699C<test.log> to C<test.log.1>. And so forth. This way, there's always
700going to be a maximum of 2 saved log files around.
701
702Here's an example of a Log::Log4perl configuration file, defining a
703daily rollover at midnight (date pattern C<yyyy-MM-dd>), keeping
704a maximum of 5 saved logfiles around:
705
706    log4perl.category         = WARN, Logfile
707    log4perl.appender.Logfile = Log::Dispatch::FileRotate
708    log4perl.appender.Logfile.filename    = test.log
709    log4perl.appender.Logfile.max         = 5
710    log4perl.appender.Logfile.DatePattern = yyyy-MM-dd
711    log4perl.appender.Logfile.TZ          = PST
712    log4perl.appender.Logfile.layout = \
713        Log::Log4perl::Layout::PatternLayout
714    log4perl.appender.Logfile.layout.ConversionPattern = %d %m %n
715
716Please see the C<Log::Dispatch::FileRotate> documentation for details.
717C<Log::Dispatch::FileRotate> is available on CPAN.
718
719=head2 What's the easiest way to turn off all logging, even with a lengthy Log4perl configuration file?
720
721In addition to category-based levels and appender thresholds,
722Log::Log4perl supports system-wide logging thresholds. This is the
723minimum level the system will require of any logging events in order for them
724to make it through to any configured appenders.
725
726For example, putting the line
727
728    log4perl.threshold = ERROR
729
730anywhere in your configuration file will limit any output to any appender
731to events with priority of ERROR or higher (ERROR or FATAL that is).
732
733However, in order to suppress all logging entirely, you need to use a
734priority that's higher than FATAL: It is simply called C<OFF>, and it is never
735used by any logger. By definition, it is higher than the highest
736defined logger level.
737
738Therefore, if you keep the line
739
740    log4perl.threshold = OFF
741
742somewhere in your Log::Log4perl configuration, the system will be quiet
743as a graveyard. If you deactivate the line (e.g. by commenting it out),
744the system will, upon config reload, snap back to normal operation, providing
745logging messages according to the rest of the configuration file again.
746
747=head2 I keep getting duplicate log messages! What's wrong?
748
749Having several settings for related categories in the Log4perl
750configuration file sometimes leads to a phenomenon called
751"message duplication". It can be very confusing at first,
752but if thought through properly, it turns out that Log4perl behaves
753as advertised. But, don't despair, of course there's a number of
754ways to avoid message duplication in your logs.
755
756Here's a sample Log4perl configuration file that produces the
757phenomenon:
758
759    log4perl.logger.Cat        = ERROR, Screen
760    log4perl.logger.Cat.Subcat = WARN, Screen
761
762    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
763    log4perl.appender.Screen.layout = SimpleLayout
764
765It defines two loggers, one for category C<Cat> and one for
766C<Cat::Subcat>, which is obviously a subcategory of C<Cat>.
767The parent logger has a priority setting of ERROR, the child
768is set to the lower C<WARN> level.
769
770Now imagine the following code in your program:
771
772    my $logger = get_logger("Cat.Subcat");
773    $logger->warn("Warning!");
774
775What do you think will happen? An unexperienced Log4perl user
776might think: "Well, the message is being sent with level WARN, so the
777C<Cat::Subcat> logger will accept it and forward it to the
778attached C<Screen> appender. Then, the message will percolate up
779the logger hierarchy, find
780the C<Cat> logger, which will suppress the message because of its
781ERROR setting."
782But, perhaps surprisingly, what you'll get with the
783code snippet above is not one but two log messages written
784to the screen:
785
786    WARN - Warning!
787    WARN - Warning!
788
789What happened? The culprit is that once the logger C<Cat::Subcat>
790decides to fire, it will forward the message I<unconditionally>
791to all directly or indirectly attached appenders. The C<Cat> logger
792will never be asked if it wants the message or not -- the message
793will just be pushed through to the appender attached to C<Cat>.
794
795One way to prevent the message from bubbling up the logger
796hierarchy is to set the C<additivity> flag of the subordinate logger to
797C<0>:
798
799    log4perl.logger.Cat            = ERROR, Screen
800    log4perl.logger.Cat.Subcat     = WARN, Screen
801    log4perl.additivity.Cat.Subcat = 0
802
803    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
804    log4perl.appender.Screen.layout = SimpleLayout
805
806The message will now be accepted by the C<Cat::Subcat> logger,
807forwarded to its appender, but then C<Cat::Subcat> will suppress
808any further action. While this setting avoids duplicate messages
809as seen before, it is often not the desired behavior. Messages
810percolating up the hierarchy are a useful Log4perl feature.
811
812If you're defining I<different> appenders for the two loggers,
813one other option is to define an appender threshold for the
814higher-level appender. Typically it is set to be
815equal to the logger's level setting:
816
817    log4perl.logger.Cat           = ERROR, Screen1
818    log4perl.logger.Cat.Subcat    = WARN, Screen2
819
820    log4perl.appender.Screen1   = Log::Log4perl::Appender::Screen
821    log4perl.appender.Screen1.layout = SimpleLayout
822    log4perl.appender.Screen1.Threshold = ERROR
823
824    log4perl.appender.Screen2   = Log::Log4perl::Appender::Screen
825    log4perl.appender.Screen2.layout = SimpleLayout
826
827Since the C<Screen1> appender now blocks every message with
828a priority less than ERROR, even if the logger in charge
829lets it through, the message percolating up the hierarchy is
830being blocked at the last minute and I<not> appended to C<Screen1>.
831
832So far, we've been operating well within the boundaries of the
833Log4j standard, which Log4perl adheres to. However, if
834you would really, really like to use a single appender
835and keep the message percolation intact without having to deal
836with message duplication, there's a non-standard solution for you:
837
838    log4perl.logger.Cat        = ERROR, Screen
839    log4perl.logger.Cat.Subcat = WARN, Screen
840
841    log4perl.appender.Screen   = Log::Log4perl::Appender::Screen
842    log4perl.appender.Screen.layout = SimpleLayout
843
844    log4perl.oneMessagePerAppender = 1
845
846The C<oneMessagePerAppender> flag will suppress duplicate messages
847to the same appender. Again, that's non-standard. But way cool :).
848
849=head2 How can I configure Log::Log4perl to send me email if something happens?
850
851Some incidents require immediate action. You can't wait until someone
852checks the log files, you need to get notified on your pager right away.
853
854The easiest way to do that is by using the C<Log::Dispatch::Email::MailSend>
855module as an appender. It comes with the C<Log::Dispatch> bundle and
856allows you to specify recipient and subject of outgoing emails in the Log4perl
857configuration file:
858
859    log4perl.category = FATAL, Mailer
860    log4perl.appender.Mailer         = Log::Dispatch::Email::MailSend
861    log4perl.appender.Mailer.to      = drone@pageme.net
862    log4perl.appender.Mailer.subject = Something's broken!
863    log4perl.appender.Mailer.layout  = SimpleLayout
864
865The message of every log incident this appender gets
866will then be forwarded to the given
867email address. Check the C<Log::Dispatch::Email::MailSend> documentation
868for details. And please make sure there's not a flood of email messages
869sent out by your application, filling up the receipient's inbox.
870
871There's one caveat you need to know about: The C<Log::Dispatch::Email>
872hierarchy of appenders turns on I<buffering> by default. This means that
873the appender will not send out messages right away but wait until a
874certain threshold has been reached. If you'd rather have your alerts
875sent out immeditately, use
876
877    log4perl.appender.Mailer.buffered = 0
878
879to turn buffering off.
880
881=head2 How can I write my own appender?
882
883First off, Log::Log4perl comes with a set of standard appenders. Then,
884there's a lot of Log4perl-compatible appenders already
885available on CPAN: Just run a search for C<Log::Dispatch> on
886http://search.cpan.org and chances are that what you're looking for
887has already been developed, debugged and been used successfully
888in production -- no need for you to reinvent the wheel.
889
890Also, Log::Log4perl ships with a nifty database appender named
891Log::Log4perl::Appender::DBI -- check it out if talking to databases is your
892desire.
893
894But if you're up for a truly exotic task, you might have to write
895an appender yourself. That's very easy -- it takes no longer
896than a couple of minutes.
897
898Say, we wanted to create an appender of the class
899C<ColorScreenAppender>, which logs messages
900to the screen in a configurable color. Just create a new class
901in C<ColorScreenAppender.pm>:
902
903    package ColorScreenAppender;
904
905Now let's assume that your Log::Log4perl
906configuration file C<test.conf> looks like this:
907
908    log4perl.logger = INFO, ColorApp
909
910    log4perl.appender.ColorApp=ColorScreenAppender
911    log4perl.appender.ColorApp.color=blue
912
913    log4perl.appender.ColorApp.layout = PatternLayout
914    log4perl.appender.ColorApp.layout.ConversionPattern=%d %m %n
915
916This will cause Log::Log4perl on C<init()> to look for a class
917ColorScreenAppender and call its constructor new(). Let's add
918new() to ColorScreenAppender.pm:
919
920    sub new {
921        my($class, %options) = @_;
922
923        my $self = { %options };
924        bless $self, $class;
925
926        return $self;
927    }
928
929To initialize this appender, Log::Log4perl will call
930and pass all attributes of the appender as defined in the configuration
931file to the constructor as name/value pairs (in this case just one):
932
933    ColorScreenAppender->new(color => "blue");
934
935The new() method listed above stores the contents of the
936%options hash in the object's
937instance data hash (referred to by $self).
938That's all for initializing a new appender with Log::Log4perl.
939
940Second, ColorScreenAppender needs to expose a
941C<log()> method, which will be called by Log::Log4perl
942every time it thinks the appender should fire. Along with the
943object reference (as usual in Perl's object world), log()
944will receive a list of name/value pairs, of which only the one
945under the key C<message> shall be of interest for now since it is the
946message string to be logged. At this point, Log::Log4perl has already taken
947care of joining the message to be a single string.
948
949For our special appender ColorScreenAppender, we're using the
950Term::ANSIColor module to colorize the output:
951
952    use Term::ANSIColor;
953
954    sub log {
955        my($self, %params) = @_;
956
957        print colored($params{message},
958                      $self->{color});
959    }
960
961The color (as configured in the Log::Log4perl configuration file)
962is available as $self-E<gt>{color} in the appender object. Don't
963forget to return
964
965    1;
966
967at the end of ColorScreenAppender.pm and you're done. Install the new appender
968somewhere where perl can find it and try it with a test script like
969
970    use Log::Log4perl qw(:easy);
971    Log::Log4perl->init("test.conf");
972    ERROR("blah");
973
974to see the new colored output. Is this cool or what?
975
976And it gets even better: You can write dynamically generated appender
977classes using the C<Class::Prototyped> module. Here's an example of
978an appender prepending every outgoing message with a configurable
979number of bullets:
980
981    use Class::Prototyped;
982
983    my $class = Class::Prototyped->newPackage(
984      "MyAppenders::Bulletizer",
985      bullets => 1,
986      log     => sub {
987        my($self, %params) = @_;
988        print "*" x $self->bullets(),
989              $params{message};
990      },
991    );
992
993    use Log::Log4perl qw(:easy);
994
995    Log::Log4perl->init(\ q{
996      log4perl.logger = INFO, Bully
997
998      log4perl.appender.Bully=MyAppenders::Bulletizer
999      log4perl.appender.Bully.bullets=3
1000
1001      log4perl.appender.Bully.layout = PatternLayout
1002      log4perl.appender.Bully.layout.ConversionPattern=%m %n
1003    });
1004
1005        # ... prints: "***Boo!\n";
1006    INFO "Boo!";
1007
1008=head2 How can I drill down on references before logging them?
1009
1010If you've got a reference to a nested structure or object, then
1011you probably don't want to log it as C<HASH(0x81141d4)> but rather
1012dump it as something like
1013
1014    $VAR1 = {
1015              'a' => 'b',
1016              'd' => 'e'
1017            };
1018
1019via a module like Data::Dumper. While it's syntactically correct to say
1020
1021    $logger->debug(Data::Dumper::Dumper($ref));
1022
1023this call imposes a huge performance penalty on your application
1024if the message is suppressed by Log::Log4perl, because Data::Dumper
1025will perform its expensive operations in any case, because it doesn't
1026know that its output will be thrown away immediately.
1027
1028As of Log::Log4perl 0.28, there's a better way: Use the
1029message output filter format as in
1030
1031    $logger->debug( {filter => \&Data::Dumper::Dumper,
1032                     value  => $ref} );
1033
1034and Log::Log4perl won't call the filter function unless the message really
1035gets written out to an appender. Just make sure to pass the whole slew as a
1036reference to a hash specifying a filter function (as a sub reference)
1037under the key C<filter> and the value to be passed to the filter function in
1038C<value>).
1039When it comes to logging, Log::Log4perl will call the filter function,
1040pass the C<value> as an argument and log the return value.
1041Saves you serious cycles.
1042
1043=head2 How can I collect all FATAL messages in an extra log file?
1044
1045Suppose you have employed Log4perl all over your system and you've already
1046activated logging in various subsystems. On top of that, without disrupting
1047any other settings, how can you collect all FATAL messages all over the system
1048and send them to a separate log file?
1049
1050If you define a root logger like this:
1051
1052    log4perl.logger                  = FATAL, File
1053    log4perl.appender.File           = Log::Log4perl::Appender::File
1054    log4perl.appender.File.filename  = /tmp/fatal.txt
1055    log4perl.appender.File.layout    = PatternLayout
1056    log4perl.appender.File.layout.ConversionPattern= %d %m %n
1057        # !!! Something's missing ...
1058
1059you'll be surprised to not only receive all FATAL messages
1060issued anywhere in the system,
1061but also everything else -- gazillions of
1062ERROR, WARN, INFO and even DEBUG messages will end up in
1063your fatal.txt logfile!
1064Reason for this is Log4perl's (or better: Log4j's) appender additivity.
1065Once a
1066lower-level logger decides to fire, the message is going to be forwarded
1067to all appenders upstream -- without further priority checks with their
1068attached loggers.
1069
1070There's a way to prevent this, however: If your appender defines a
1071minimum threshold, only messages of this priority or higher are going
1072to be logged. So, just add
1073
1074    log4perl.appender.File.Threshold = FATAL
1075
1076to the configuration above, and you'll get what you wanted in the
1077first place: An overall system FATAL message collector.
1078
1079=head2 How can I bundle several log messages into one?
1080
1081Would you like to tally the messages arriving at your appender and
1082dump out a summary once they're exceeding a certain threshold?
1083So that something like
1084
1085    $logger->error("Blah");
1086    $logger->error("Blah");
1087    $logger->error("Blah");
1088
1089won't be logged as
1090
1091    Blah
1092    Blah
1093    Blah
1094
1095but as
1096
1097    [3] Blah
1098
1099instead? If you'd like to hold off on logging a message until it has been
1100sent a couple of times, you can roll that out by creating a buffered
1101appender.
1102
1103Let's define a new appender like
1104
1105    package TallyAppender;
1106
1107    sub new {
1108        my($class, %options) = @_;
1109
1110        my $self = { maxcount => 5,
1111                     %options
1112                   };
1113
1114        bless $self, $class;
1115
1116        $self->{last_message}        = "";
1117        $self->{last_message_count}  = 0;
1118
1119        return $self;
1120    }
1121
1122with two additional instance variables C<last_message> and
1123C<last_message_count>, storing the content of the last message sent
1124and a counter of how many times this has happened. Also, it features
1125a configuration parameter C<maxcount> which defaults to 5 in the
1126snippet above but can be set in the Log4perl configuration file like this:
1127
1128    log4perl.logger = INFO, A
1129    log4perl.appender.A=TallyAppender
1130    log4perl.appender.A.maxcount = 3
1131
1132The main tallying logic lies in the appender's C<log> method,
1133which is called every time Log4perl thinks a message needs to get logged
1134by our appender:
1135
1136    sub log {
1137        my($self, %params) = @_;
1138
1139            # Message changed? Print buffer.
1140        if($self->{last_message} and
1141           $params{message} ne $self->{last_message}) {
1142            print "[$self->{last_message_count}]: " .
1143                  "$self->{last_message}";
1144            $self->{last_message_count} = 1;
1145            $self->{last_message} = $params{message};
1146            return;
1147        }
1148
1149        $self->{last_message_count}++;
1150        $self->{last_message} = $params{message};
1151
1152            # Threshold exceeded? Print, reset counter
1153        if($self->{last_message_count} >=
1154           $self->{maxcount}) {
1155            print "[$self->{last_message_count}]: " .
1156                  "$params{message}";
1157            $self->{last_message_count} = 0;
1158            $self->{last_message}       = "";
1159            return;
1160        }
1161    }
1162
1163We basically just check if the oncoming message in C<$param{message}>
1164is equal to what we've saved before in the C<last_message> instance
1165variable. If so, we're increasing C<last_message_count>.
1166We print the message in two cases: If the new message is different
1167than the buffered one, because then we need to dump the old stuff
1168and store the new. Or, if the counter exceeds the threshold, as
1169defined by the C<maxcount> configuration parameter.
1170
1171Please note that the appender always gets the fully rendered message and
1172just compares it as a whole -- so if there's a date/timestamp in there,
1173that might confuse your logic. You can work around this by specifying
1174%m %n as a layout and add the date later on in the appender. Or, make
1175the comparison smart enough to omit the date.
1176
1177At last, don't forget what happens if the program is being shut down.
1178If there's still messages in the buffer, they should be printed out
1179at that point. That's easy to do in the appender's DESTROY method,
1180which gets called at object destruction time:
1181
1182    sub DESTROY {
1183        my($self) = @_;
1184
1185        if($self->{last_message_count}) {
1186            print "[$self->{last_message_count}]: " .
1187                  "$self->{last_message}";
1188            return;
1189        }
1190    }
1191
1192This will ensure that none of the buffered messages are lost.
1193Happy buffering!
1194
1195=head2 I want to log ERROR and WARN messages to different files! How can I do that?
1196
1197Let's assume you wanted to have each logging statement written to a
1198different file, based on the statement's priority. Messages with priority
1199C<WARN> are supposed to go to C</tmp/app.warn>, events prioritized
1200as C<ERROR> should end up in C</tmp/app.error>.
1201
1202Now, if you define two appenders C<AppWarn> and C<AppError>
1203and assign them both to the root logger,
1204messages bubbling up from any loggers below will be logged by both
1205appenders because of Log4perl's message propagation feature. If you limit
1206their exposure via the appender threshold mechanism and set
1207C<AppWarn>'s threshold to C<WARN> and C<AppError>'s to C<ERROR>, you'll
1208still get C<ERROR> messages in C<AppWarn>, because C<AppWarn>'s C<WARN>
1209setting will just filter out messages with a I<lower> priority than
1210C<WARN> -- C<ERROR> is higher and will be allowed to pass through.
1211
1212What we need for this is a Log4perl I<Custom Filter>, available with
1213Log::Log4perl 0.30.
1214
1215Both appenders need to verify that
1216the priority of the oncoming messages exactly I<matches> the priority
1217the appender is supposed to log messages of. To accomplish this task,
1218let's define two custom filters, C<MatchError> and C<MatchWarn>, which,
1219when attached to their appenders, will limit messages passed on to them
1220to those matching a given priority:
1221
1222    log4perl.logger = WARN, AppWarn, AppError
1223
1224        # Filter to match level ERROR
1225    log4perl.filter.MatchError = Log::Log4perl::Filter::LevelMatch
1226    log4perl.filter.MatchError.LevelToMatch  = ERROR
1227    log4perl.filter.MatchError.AcceptOnMatch = true
1228
1229        # Filter to match level WARN
1230    log4perl.filter.MatchWarn  = Log::Log4perl::Filter::LevelMatch
1231    log4perl.filter.MatchWarn.LevelToMatch  = WARN
1232    log4perl.filter.MatchWarn.AcceptOnMatch = true
1233
1234        # Error appender
1235    log4perl.appender.AppError = Log::Log4perl::Appender::File
1236    log4perl.appender.AppError.filename = /tmp/app.err
1237    log4perl.appender.AppError.layout   = SimpleLayout
1238    log4perl.appender.AppError.Filter   = MatchError
1239
1240        # Warning appender
1241    log4perl.appender.AppWarn = Log::Log4perl::Appender::File
1242    log4perl.appender.AppWarn.filename = /tmp/app.warn
1243    log4perl.appender.AppWarn.layout   = SimpleLayout
1244    log4perl.appender.AppWarn.Filter   = MatchWarn
1245
1246The appenders C<AppWarn> and C<AppError> defined above are logging to C</tmp/app.warn> and
1247C</tmp/app.err> respectively and have the custom filters C<MatchWarn> and C<MatchError>
1248attached.
1249This setup will direct all WARN messages, issued anywhere in the system, to /tmp/app.warn (and
1250ERROR messages to /tmp/app.error) -- without any overlaps.
1251
1252=head2 On our server farm, Log::Log4perl configuration files differ slightly from host to host. Can I roll them all into one?
1253
1254You sure can, because Log::Log4perl allows you to specify attribute values
1255dynamically. Let's say that one of your appenders expects the host's IP address
1256as one of its attributes. Now, you could certainly roll out different
1257configuration files for every host and specify the value like
1258
1259    log4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender
1260    log4perl.appender.MyAppender.ip = 10.0.0.127
1261
1262but that's a maintenance nightmare. Instead, you can have Log::Log4perl
1263figure out the IP address at configuration time and set the appender's
1264value correctly:
1265
1266        # Set the IP address dynamically
1267    log4perl.appender.MyAppender    = Log::Log4perl::Appender::SomeAppender
1268    log4perl.appender.MyAppender.ip = sub { \
1269       use Sys::Hostname; \
1270       use Socket; \
1271       return inet_ntoa(scalar gethostbyname hostname); \
1272    }
1273
1274If Log::Log4perl detects that an attribute value starts with something like
1275C<"sub {...">, it will interpret it as a perl subroutine which is to be executed
1276once at configuration time (not runtime!) and its return value is
1277to be used as the attribute value. This comes in handy
1278for rolling out applications whichs Log::Log4perl configuration files
1279show small host-specific differences, because you can deploy the unmodified
1280application distribution on all instances of the server farm.
1281
1282=head2 Log4perl doesn't interpret my backslashes correctly!
1283
1284If you're using Log4perl's feature to specify the configuration as a
1285string in your program (as opposed to a separate configuration file),
1286chances are that you've written it like this:
1287
1288    # *** WRONG! ***
1289
1290    Log::Log4perl->init( \ <<END_HERE);
1291        log4perl.logger = WARN, A1
1292        log4perl.appender.A1 = Log::Log4perl::Appender::Screen
1293        log4perl.appender.A1.layout = \
1294            Log::Log4perl::Layout::PatternLayout
1295        log4perl.appender.A1.layout.ConversionPattern = %m%n
1296    END_HERE
1297
1298    # *** WRONG! ***
1299
1300and you're getting the following error message:
1301
1302    Layout not specified for appender A1 at .../Config.pm line 342.
1303
1304What's wrong? The problem is that you're using a here-document with
1305substitution enabled (C<E<lt>E<lt>END_HERE>) and that Perl won't
1306interpret backslashes at line-ends as continuation characters but
1307will essentially throw them out. So, in the code above, the layout line
1308will look like
1309
1310    log4perl.appender.A1.layout =
1311
1312to Log::Log4perl which causes it to report an error. To interpret the backslash
1313at the end of the line correctly as a line-continuation character, use
1314the non-interpreting mode of the here-document like in
1315
1316    # *** RIGHT! ***
1317
1318    Log::Log4perl->init( \ <<'END_HERE');
1319        log4perl.logger = WARN, A1
1320        log4perl.appender.A1 = Log::Log4perl::Appender::Screen
1321        log4perl.appender.A1.layout = \
1322            Log::Log4perl::Layout::PatternLayout
1323        log4perl.appender.A1.layout.ConversionPattern = %m%n
1324    END_HERE
1325
1326    # *** RIGHT! ***
1327
1328(note the single quotes around C<'END_HERE'>) or use C<q{...}>
1329instead of a here-document and Perl will treat the backslashes at
1330line-end as intended.
1331
1332=head2 I want to suppress certain messages based on their content!
1333
1334Let's assume you've plastered all your functions with Log4perl
1335statements like
1336
1337    sub some_func {
1338
1339        INFO("Begin of function");
1340
1341        # ... Stuff happens here ...
1342
1343        INFO("End of function");
1344    }
1345
1346to issue two log messages, one at the beginning and one at the end of
1347each function. Now you want to suppress the message at the beginning
1348and only keep the one at the end, what can you do? You can't use the category
1349mechanism, because both messages are issued from the same package.
1350
1351Log::Log4perl's custom filters (0.30 or better) provide an interface for the
1352Log4perl user to step in right before a message gets logged and decide if
1353it should be written out or suppressed, based on the message content or other
1354parameters:
1355
1356    use Log::Log4perl qw(:easy);
1357
1358    Log::Log4perl::init( \ <<'EOT' );
1359        log4perl.logger             = INFO, A1
1360        log4perl.appender.A1        = Log::Log4perl::Appender::Screen
1361        log4perl.appender.A1.layout = \
1362            Log::Log4perl::Layout::PatternLayout
1363        log4perl.appender.A1.layout.ConversionPattern = %m%n
1364
1365        log4perl.filter.M1 = Log::Log4perl::Filter::StringMatch
1366        log4perl.filter.M1.StringToMatch = Begin
1367        log4perl.filter.M1.AcceptOnMatch = false
1368
1369        log4perl.appender.A1.Filter = M1
1370EOT
1371
1372The last four statements in the configuration above are defining a custom
1373filter C<M1> of type C<Log::Log4perl::Filter::StringMatch>, which comes with
1374Log4perl right out of the box and allows you to define a text pattern to match
1375(as a perl regular expression) and a flag C<AcceptOnMatch> indicating
1376if a match is supposed to suppress the message or let it pass through.
1377
1378The last line then assigns this filter to the C<A1> appender, which will
1379call it every time it receives a message to be logged and throw all
1380messages out I<not> matching the regular expression C<Begin>.
1381
1382Instead of using the standard C<Log::Log4perl::Filter::StringMatch> filter,
1383you can define your own, simply using a perl subroutine:
1384
1385    log4perl.filter.ExcludeBegin  = sub { !/Begin/ }
1386    log4perl.appender.A1.Filter   = ExcludeBegin
1387
1388For details on custom filters, check L<Log::Log4perl::Filter>.
1389
1390=head2 My new module uses Log4perl -- but what happens if the calling program didn't configure it?
1391
1392If a Perl module uses Log::Log4perl, it will typically rely on the
1393calling program to initialize it. If it is using Log::Log4perl in C<:easy>
1394mode, like in
1395
1396    package MyMod;
1397    use Log::Log4perl qw(:easy);
1398
1399    sub foo {
1400        DEBUG("In foo");
1401    }
1402
1403    1;
1404
1405and the calling program doesn't initialize Log::Log4perl at all (e.g. because
1406it has no clue that it's available), Log::Log4perl will silently
1407ignore all logging messages. However, if the module is using Log::Log4perl
1408in regular mode like in
1409
1410    package MyMod;
1411    use Log::Log4perl qw(get_logger);
1412
1413    sub foo {
1414        my $logger = get_logger("");
1415        $logger->debug("blah");
1416    }
1417
1418    1;
1419
1420and the main program is just using the module like in
1421
1422    use MyMode;
1423    MyMode::foo();
1424
1425then Log::Log4perl will also ignore all logging messages but
1426issue a warning like
1427
1428    Log4perl: Seems like no initialization happened.
1429    Forgot to call init()?
1430
1431(only once!) to remind novice users to not forget to initialize
1432the logging system before using it.
1433However, if you want to suppress this message, just
1434add the C<:nowarn> target to the module's C<use Log::Log4perl> call:
1435
1436    use Log::Log4perl qw(get_logger :nowarn);
1437
1438This will have Log::Log4perl silently ignore all logging statements if
1439no initialization has taken place. If, instead of using init(), you're
1440using Log4perl's API to define loggers and appenders, the same
1441notification happens if no call to add_appenders() is made, i.e. no
1442appenders are defined.
1443
1444If the module wants to figure out if some other program part has
1445already initialized Log::Log4perl, it can do so by calling
1446
1447    Log::Log4perl::initialized()
1448
1449which will return a true value in case Log::Log4perl has been initialized
1450and a false value if not.
1451
1452=head2 How can I synchronize access to an appender?
1453
1454If you're using the same instance of an appender in multiple processes,
1455and each process is passing on messages to the appender in parallel,
1456you might end up with overlapping log entries.
1457
1458Typical scenarios include a file appender that you create in the main
1459program, and which will then be shared between the parent and a
1460forked child process. Or two separate processes, each initializing a
1461Log4perl file appender on the same logfile.
1462
1463Log::Log4perl won't synchronize access to the shared logfile by
1464default. Depending on your operating system's flush mechanism,
1465buffer size and the size of your messages, there's a small chance of
1466an overlap.
1467
1468The easiest way to prevent overlapping messages in logfiles written to
1469by multiple processes is setting the
1470file appender's C<syswrite> flag along with a file write mode of C<"append">.
1471This makes sure that
1472C<Log::Log4perl::Appender::File> uses C<syswrite()> (which is guaranteed
1473to run uninterrupted) instead of C<print()> which might buffer
1474the message or get interrupted by the OS while it is writing. And in
1475C<"append"> mode, the OS kernel ensures that multiple processes share
1476one end-of-file marker, ensuring that each process writes to the I<real>
1477end of the file. (The value of C<"append">
1478for the C<mode> parameter is the default setting in Log4perl's file
1479appender so you don't have to set it explicitely.)
1480
1481      # Guarantees atomic writes
1482
1483    log4perl.category.Bar.Twix          = WARN, Logfile
1484
1485    log4perl.appender.Logfile           = Log::Log4perl::Appender::File
1486    log4perl.appender.Logfile.mode      = append
1487    log4perl.appender.Logfile.syswrite  = 1
1488    log4perl.appender.Logfile.filename  = test.log
1489    log4perl.appender.Logfile.layout    = SimpleLayout
1490
1491Another guaranteed way of having messages separated with any kind of
1492appender is putting a Log::Log4perl::Appender::Synchronized composite
1493appender in between Log::Log4perl and the real appender. It will make
1494sure to let messages pass through this virtual gate one by one only.
1495
1496Here's a sample configuration to synchronize access to a file appender:
1497
1498    log4perl.category.Bar.Twix          = WARN, Syncer
1499
1500    log4perl.appender.Logfile           = Log::Log4perl::Appender::File
1501    log4perl.appender.Logfile.autoflush = 1
1502    log4perl.appender.Logfile.filename  = test.log
1503    log4perl.appender.Logfile.layout    = SimpleLayout
1504
1505    log4perl.appender.Syncer            = Log::Log4perl::Appender::Synchronized
1506    log4perl.appender.Syncer.appender   = Logfile
1507
1508C<Log::Log4perl::Appender::Synchronized> uses
1509the C<IPC::Shareable> module and its semaphores, which will slow down writing
1510the log messages, but ensures sequential access featuring atomic checks.
1511Check L<Log::Log4perl::Appender::Synchronized> for details.
1512
1513=head2 Can I use Log::Log4perl with log4j's Chainsaw?
1514
1515Yes, Log::Log4perl can be configured to send its events to log4j's
1516graphical log UI I<Chainsaw>.
1517
1518=for html
1519<p>
1520<TABLE><TR><TD>
1521<A HREF="http://log4perl.sourceforge.net/images/chainsaw2.jpg"><IMG SRC="http://log4perl.sourceforge.net/images/chainsaw2s.jpg"></A>
1522<TR><TD>
1523<I>Figure 1: Chainsaw receives Log::Log4perl events</I>
1524</TABLE>
1525<p>
1526
1527=for text
1528Figure1: Chainsaw receives Log::Log4perl events
1529
1530Here's how it works:
1531
1532=over 4
1533
1534=item *
1535
1536Get Guido Carls' E<lt>gcarls@cpan.orgE<gt> Log::Log4perl extension
1537C<Log::Log4perl::Layout::XMLLayout> from CPAN and install it:
1538
1539    perl -MCPAN -eshell
1540    cpan> install Log::Log4perl::Layout::XMLLayout
1541
1542=item *
1543
1544Install and start Chainsaw, which is part of the C<log4j> distribution now
1545(see http://jakarta.apache.org/log4j ). Create a configuration file like
1546
1547  <log4j:configuration debug="true">
1548    <plugin name="XMLSocketReceiver"
1549            class="org.apache.log4j.net.XMLSocketReceiver">
1550      <param name="decoder" value="org.apache.log4j.xml.XMLDecoder"/>
1551      <param name="Port" value="4445"/>
1552    </plugin>
1553    <root> <level value="debug"/> </root>
1554  </log4j:configuration>
1555
1556and name it e.g. C<config.xml>. Then start Chainsaw like
1557
1558  java -Dlog4j.debug=true -Dlog4j.configuration=config.xml \
1559    -classpath ".:log4j-1.3alpha.jar:log4j-chainsaw-1.3alpha.jar" \
1560    org.apache.log4j.chainsaw.LogUI
1561
1562and watch the GUI coming up.
1563
1564=item *
1565
1566Configure Log::Log4perl to use a socket appender with an XMLLayout, pointing
1567to the host/port where Chainsaw (as configured above) is waiting with its
1568XMLSocketReceiver:
1569
1570  use Log::Log4perl qw(get_logger);
1571  use Log::Log4perl::Layout::XMLLayout;
1572
1573  my $conf = q(
1574    log4perl.category.Bar.Twix          = WARN, Appender
1575    log4perl.appender.Appender          = Log::Log4perl::Appender::Socket
1576    log4perl.appender.Appender.PeerAddr = localhost
1577    log4perl.appender.Appender.PeerPort = 4445
1578    log4perl.appender.Appender.layout   = Log::Log4perl::Layout::XMLLayout
1579  );
1580
1581  Log::Log4perl::init(\$conf);
1582
1583    # Nasty hack to suppress encoding header
1584  my $app = Log::Log4perl::appenders->{"Appender"};
1585  $app->layout()->{enc_set} = 1;
1586
1587  my $logger = get_logger("Bar.Twix");
1588  $logger->error("One");
1589
1590The nasty hack shown in the code snippet above is currently (October 2003)
1591necessary, because Chainsaw expects XML messages to arrive in a format like
1592
1593  <log4j:event logger="Bar.Twix"
1594               timestamp="1066794904310"
1595               level="ERROR"
1596               thread="10567">
1597    <log4j:message><![CDATA[Two]]></log4j:message>
1598    <log4j:NDC><![CDATA[undef]]></log4j:NDC>
1599    <log4j:locationInfo class="main"
1600      method="main"
1601      file="./t"
1602      line="32">
1603    </log4j:locationInfo>
1604  </log4j:event>
1605
1606without a preceding
1607
1608  <?xml version = "1.0" encoding = "iso8859-1"?>
1609
1610which Log::Log4perl::Layout::XMLLayout applies to the first event sent
1611over the socket.
1612
1613=back
1614
1615See figure 1 for a screenshot of Chainsaw in action, receiving events from
1616the Perl script shown above.
1617
1618Many thanks to Chainsaw's
1619Scott Deboy <sdeboy@comotivsystems.com> for his support!
1620
1621=head2 How can I run Log::Log4perl under mod_perl?
1622
1623In persistent environments it's important to play by the rules outlined
1624in section L<Log::Log4perl/"Initialize once and only once">.
1625If you haven't read this yet, please go ahead and read it right now. It's
1626very important.
1627
1628And no matter if you use a startup handler to init() Log::Log4perl or use the
1629init_once() strategy (added in 0.42), either way you're very likely to have
1630unsynchronized writes to logfiles.
1631
1632If Log::Log4perl is configured with a log file appender, and it is
1633initialized via
1634the Apache startup handler, the file handle created initially will be
1635shared among all Apache processes. Similarly, with the init_once()
1636approach: although every process has a separate L4p configuration,
1637processes are gonna share the appender file I<names> instead, effectively
1638opening several different file handles on the same file.
1639
1640Now, having several appenders using the same file handle or having
1641several appenders logging to the same file unsynchronized, this might
1642result in overlapping messages. Sometimes, this is acceptable. If it's
1643not, here's two strategies:
1644
1645=over 4
1646
1647=item *
1648
1649Use the L<Log::Log4perl::Appender::Synchronized> appender to connect to
1650your file appenders. Here's the writeup:
1651http://log4perl.sourceforge.net/releases/Log-Log4perl/docs/html/Log/Log4perl/FAQ.html#23804
1652
1653=item *
1654
1655Use a different logfile for every process like in
1656
1657     #log4perl.conf
1658     ...
1659     log4perl.appender.A1.filename = sub { "mylog.$$.log" }
1660
1661=back
1662
1663=head2 My program already uses warn() and die(). How can I switch to Log4perl?
1664
1665If your program already uses Perl's C<warn()> function to spew out
1666error messages and you'd like to channel those into the Log4perl world,
1667just define a C<__WARN__> handler where your program or module resides:
1668
1669    use Log::Log4perl qw(:easy);
1670
1671    $SIG{__WARN__} = sub {
1672        local $Log::Log4perl::caller_depth =
1673            $Log::Log4perl::caller_depth + 1;
1674        WARN @_;
1675    };
1676
1677Why the C<local> setting of C<$Log::Log4perl::caller_depth>?
1678If you leave that out,
1679C<PatternLayout> conversion specifiers like C<%M> or C<%F> (printing
1680the current function/method and source filename) will refer
1681to where the __WARN__ handler resides, not the environment
1682Perl's C<warn()> function was issued from. Increasing C<caller_depth>
1683adjusts for this offset. Having it C<local>, makes sure the level
1684gets set back after the handler exits.
1685
1686Once done, if your program does something like
1687
1688    sub some_func {
1689        warn "Here's a warning";
1690    }
1691
1692you'll get (depending on your Log::Log4perl configuration) something like
1693
1694    2004/02/19 20:41:02-main::some_func: Here's a warning at ./t line 25.
1695
1696in the appropriate appender instead of having a screen full of STDERR
1697messages. It also works with the C<Carp> module and its C<carp()>
1698and C<cluck()> functions.
1699
1700If, on the other hand, catching C<die()> and friends is
1701required, a C<__DIE__> handler is appropriate:
1702
1703    $SIG{__DIE__} = sub {
1704        if($^S) {
1705            # We're in an eval {} and don't want log
1706            # this message but catch it later
1707            return;
1708        }
1709        local $Log::Log4perl::caller_depth =
1710            $Log::Log4perl::caller_depth + 1;
1711        LOGDIE @_;
1712    };
1713
1714This will call Log4perl's C<LOGDIE()> function, which will log a fatal
1715error and then call die() internally, causing the program to exit. Works
1716equally well with C<Carp>'s C<croak()> and C<confess()> functions.
1717
1718=head2 Some module prints messages to STDERR. How can I funnel them to Log::Log4perl?
1719
1720If a module you're using doesn't use Log::Log4perl but prints logging
1721messages to STDERR instead, like
1722
1723    ########################################
1724    package IgnorantModule;
1725    ########################################
1726
1727    sub some_method {
1728        print STDERR "Parbleu! An error!\n";
1729    }
1730
1731    1;
1732
1733there's still a way to capture these messages and funnel them
1734into Log::Log4perl, even without touching the module. What you need is
1735a trapper module like
1736
1737    ########################################
1738    package Trapper;
1739    ########################################
1740
1741    use Log::Log4perl qw(:easy);
1742
1743    sub TIEHANDLE {
1744        my $class = shift;
1745        bless [], $class;
1746    }
1747
1748    sub PRINT {
1749        my $self = shift;
1750        $Log::Log4perl::caller_depth++;
1751        DEBUG @_;
1752        $Log::Log4perl::caller_depth--;
1753    }
1754
1755    1;
1756
1757and a C<tie> command in the main program to tie STDERR to the trapper
1758module along with regular Log::Log4perl initialization:
1759
1760    ########################################
1761    package main;
1762    ########################################
1763
1764    use Log::Log4perl qw(:easy);
1765
1766    Log::Log4perl->easy_init(
1767        {level  => $DEBUG,
1768         file   => 'stdout',   # make sure not to use stderr here!
1769         layout => "%d %M: %m%n",
1770        });
1771
1772    tie *STDERR, "Trapper";
1773
1774Make sure not to use STDERR as Log::Log4perl's file appender
1775here (which would be the default in C<:easy> mode), because it would
1776end up in an endless recursion.
1777
1778Now, calling
1779
1780    IgnorantModule::some_method();
1781
1782will result in the desired output
1783
1784    2004/05/06 11:13:04 IgnorantModule::some_method: Parbleu! An error!
1785
1786=head2 How come PAR (Perl Archive Toolkit) creates executables which then can't find their Log::Log4perl appenders?
1787
1788If not instructed otherwise, C<Log::Log4perl> dynamically pulls in
1789appender classes found in its configuration. If you specify
1790
1791    #!/usr/bin/perl
1792    # mytest.pl
1793
1794    use Log::Log4perl qw(get_logger);
1795
1796    my $conf = q(
1797      log4perl.category.Bar.Twix = WARN, Logfile
1798      log4perl.appender.Logfile  = Log::Log4perl::Appender::Screen
1799      log4perl.appender.Logfile.layout = SimpleLayout
1800    );
1801
1802    Log::Log4perl::init(\$conf);
1803    my $logger = get_logger("Bar::Twix");
1804    $logger->error("Blah");
1805
1806then C<Log::Log4perl::Appender::Screen> will be pulled in while the program
1807runs, not at compile time. If you have PAR compile the script above to an
1808executable binary via
1809
1810    pp -o mytest mytest.pl
1811
1812and then run C<mytest> on a machine without having Log::Log4perl installed,
1813you'll get an error message like
1814
1815    ERROR: can't load appenderclass 'Log::Log4perl::Appender::Screen'
1816    Can't locate Log/Log4perl/Appender/Screen.pm in @INC ...
1817
1818Why? At compile time, C<pp> didn't realize that
1819C<Log::Log4perl::Appender::Screen> would be needed later on and didn't
1820wrap it into the executable created. To avoid this, either say
1821C<use Log::Log4perl::Appender::Screen> in the script explicitely or
1822compile it with
1823
1824    pp -o mytest -M Log::Log4perl::Appender::Screen mytest.pl
1825
1826to make sure the appender class gets included.
1827
1828=head2 How can I access a custom appender defined in the configuration?
1829
1830Any appender defined in the configuration file or somewhere in the code
1831can be accessed later via
1832C<Log::Log4perl-E<gt>appender_by_name("appender_name")>,
1833which returns a reference the the appender object.
1834
1835Once you've got a hold of the object, it can be queried or modified to
1836your liking. For example, see the custom C<IndentAppender> defined below:
1837After calling C<init()> to define the Log4perl settings, the
1838appender object is retrieved to call its C<indent_more()> and C<indent_less()>
1839methods to control indentation of messages:
1840
1841    package IndentAppender;
1842
1843    sub new {
1844        bless { indent => 0 }, $_[0];
1845    }
1846
1847    sub indent_more  { $_[0]->{indent}++ }
1848    sub indent_less  { $_[0]->{indent}-- }
1849
1850    sub log {
1851        my($self, %params) = @_;
1852        print " " x $self->{indent}, $params{message};
1853    }
1854
1855    package main;
1856
1857    use Log::Log4perl qw(:easy);
1858
1859    my $conf = q(
1860    log4perl.category          = DEBUG, Indented
1861    log4perl.appender.Indented = IndentAppender
1862    log4perl.appender.Indented.layout = Log::Log4perl::Layout::SimpleLayout
1863    );
1864
1865    Log::Log4perl::init(\$conf);
1866
1867    my $appender = Log::Log4perl->appender_by_name("Indented");
1868
1869    DEBUG "No identation";
1870    $appender->indent_more();
1871    DEBUG "One more";
1872    $appender->indent_more();
1873    DEBUG "Two more";
1874    $appender->indent_less();
1875    DEBUG "One less";
1876
1877As you would expect, this will print
1878
1879    DEBUG - No identation
1880     DEBUG - One more
1881      DEBUG - Two more
1882     DEBUG - One less
1883
1884because the very appender used by Log4perl is modified dynamically at
1885runtime.
1886
1887=head2 I don't know if Log::Log4perl is installed. How can I prepare my script?
1888
1889In case your script needs to be prepared for environments that may or may
1890not have Log::Log4perl installed, there's a trick.
1891
1892If you put the following BEGIN blocks at the top of the program,
1893you'll be able to use the DEBUG(), INFO(), etc. macros in
1894Log::Log4perl's C<:easy> mode.
1895If Log::Log4perl
1896is installed in the target environment, the regular Log::Log4perl rules
1897apply. If not, all of DEBUG(), INFO(), etc. are "stubbed" out, i.e. they
1898turn into no-ops:
1899
1900    use warnings;
1901    use strict;
1902
1903    BEGIN {
1904        eval { require Log::Log4perl; };
1905
1906        if($@) {
1907            print "Log::Log4perl not installed - stubbing.\n";
1908            no strict qw(refs);
1909            *{"main::$_"} = sub { } for qw(DEBUG INFO WARN ERROR FATAL);
1910        } else {
1911            no warnings;
1912            print "Log::Log4perl installed - life is good.\n";
1913            require Log::Log4perl::Level;
1914            Log::Log4perl::Level->import(__PACKAGE__);
1915            Log::Log4perl->import(qw(:easy));
1916            Log::Log4perl->easy_init($main::DEBUG);
1917        }
1918    }
1919
1920        # The regular script begins ...
1921    DEBUG "Hey now!";
1922
1923This snippet will first probe for Log::Log4perl, and if it can't be found,
1924it will alias DEBUG(), INFO(), with empty subroutines via typeglobs.
1925If Log::Log4perl is available, its level constants are first imported
1926(C<$DEBUG>, C<$INFO>, etc.) and then C<easy_init()> gets called to initialize
1927the logging system.
1928
1929=head2 Can file appenders create files with different permissions?
1930
1931Typically, when C<Log::Log4perl::Appender::File> creates a new file,
1932its permissions are set to C<rw-r--r-->. Why? Because your
1933environment's I<umask> most likely defaults to
1934C<0022>, that's the standard setting.
1935
1936What's a I<umask>, you're asking? It's a template that's applied to
1937the permissions of all newly created files. While calls like
1938C<open(FILE, "E<gt>foo")> will always try to create files in C<rw-rw-rw-
1939> mode, the system will apply the current I<umask> template to
1940determine the final permission setting. I<umask> is a bit mask that's
1941inverted and then applied to the requested permission setting, using a
1942bitwise AND:
1943
1944    $request_permission &~ $umask
1945
1946So, a I<umask> setting of 0000 (the leading 0 simply indicates an
1947octal value) will create files in C<rw-rw-rw-> mode, a setting of 0277
1948will use C<r-------->, and the standard 0022 will use C<rw-r--r-->.
1949
1950As an example, if you want your log files to be created with
1951C<rw-r--rw-> permissions, use a I<umask> of C<0020> before
1952calling Log::Log4perl->init():
1953
1954    use Log::Log4perl;
1955
1956    umask 0020;
1957        # Creates log.out in rw-r--rw mode
1958    Log::Log4perl->init(\ q{
1959        log4perl.logger = WARN, File
1960        log4perl.appender.File = Log::Log4perl::Appender::File
1961        log4perl.appender.File.filename = log.out
1962        log4perl.appender.File.layout = SimpleLayout
1963    });
1964
1965=head2 Using Log4perl in an END block causes a problem!
1966
1967It's not easy to get to this error, but if you write something like
1968
1969    END { Log::Log4perl::get_logger()->debug("Hey there."); }
1970
1971    use Log::Log4perl qw(:easy);
1972    Log::Log4perl->easy_init($DEBUG);
1973
1974it won't work. The reason is that C<Log::Log4perl> defines an
1975END block that cleans up all loggers. And perl will run END blocks
1976in the reverse order as they're encountered in the compile phase,
1977so in the scenario above, the END block will run I<after> Log4perl
1978has cleaned up its loggers.
1979
1980Placing END blocks using Log4perl I<after>
1981a C<use Log::Log4perl> statement fixes the problem:
1982
1983    use Log::Log4perl qw(:easy);
1984    Log::Log4perl->easy_init($DEBUG);
1985
1986    END { Log::Log4perl::get_logger()->debug("Hey there."); }
1987
1988In this scenario, the shown END block is executed I<before> Log4perl
1989cleans up and the debug message will be processed properly.
1990
1991=head2 Help! My appender is throwing a "Wide character in print" warning!
1992
1993This warning shows up when Unicode strings are printed without
1994precautions. The warning goes away if the complaining appender is
1995set to utf-8 mode:
1996
1997      # Either in the log4perl configuration file:
1998  log4perl.appender.Logfile.filename = test.log
1999  log4perl.appender.Logfile.utf8     = 1
2000
2001      # Or, in easy mode:
2002  Log::Log4perl->easy_init( {
2003    level => $DEBUG,
2004    file  => ":utf8> test.log"
2005  } );
2006
2007If the complaining appender is a screen appender, set its C<utf8> option:
2008
2009      log4perl.appender.Screen.stderr = 1
2010      log4perl.appender.Screen.utf8   = 1
2011
2012Alternatively, C<binmode> does the trick:
2013
2014      # Either STDOUT ...
2015    binmode(STDOUT, ":utf8);
2016
2017      # ... or STDERR.
2018    binmode(STDERR, ":utf8);
2019
2020Some background on this: Perl's strings are either byte strings or
2021Unicode strings. C<"Mike"> is a byte string.
2022C<"\x{30DE}\x{30A4}\x{30AF}"> is a Unicode string. Unicode strings are
2023marked specially and are UTF-8 encoded internally.
2024
2025If you print a byte string to STDOUT,
2026all is well, because STDOUT is by default set to byte mode. However,
2027if you print a Unicode string to STDOUT without precautions, C<perl>
2028will try to transform the Unicode string back to a byte string before
2029printing it out. This is troublesome if the Unicode string contains
2030'wide' characters which can't be represented in Latin-1.
2031
2032For example, if you create a Unicode string with three japanese Katakana
2033characters as in
2034
2035    perl -le 'print "\x{30DE}\x{30A4}\x{30AF}"'
2036
2037(coincidentally pronounced Ma-i-ku, the japanese pronounciation of
2038"Mike"), STDOUT is in byte mode and the warning
2039
2040    Wide character in print at ./script.pl line 14.
2041
2042appears. Setting STDOUT to UTF-8 mode as in
2043
2044    perl -le 'binmode(STDOUT, ":utf8"); print "\x{30DE}\x{30A4}\x{30AF}"'
2045
2046will silently print the Unicode string to STDOUT in UTF-8. To see the
2047characters printed, you'll need a UTF-8 terminal with a font including
2048japanese Katakana characters.
2049
2050=head2 How can I send errors to the screen, and debug messages to a file?
2051
2052Let's assume you want to maintain a detailed DEBUG output in a file
2053and only messages of level ERROR and higher should be printed on the
2054screen. Often times, developers come up with something like this:
2055
2056     # Wrong!!!
2057    log4perl.logger = DEBUG, FileApp
2058    log4perl.logger = ERROR, ScreenApp
2059     # Wrong!!!
2060
2061This won't work, however. Logger definitions aren't additive, and the
2062second statement will overwrite the first one. Log4perl versions
2063below 1.04 were silently accepting this, leaving people confused why
2064it wouldn't work as expected.
2065As of 1.04, this will throw a I<fatal error> to notify the user of
2066the problem.
2067
2068What you want to do instead, is this:
2069
2070    log4perl.logger                    = DEBUG, FileApp, ScreenApp
2071
2072    log4perl.appender.FileApp          = Log::Log4perl::Appender::File
2073    log4perl.appender.FileApp.filename = test.log
2074    log4perl.appender.FileApp.layout   = SimpleLayout
2075
2076    log4perl.appender.ScreenApp          = Log::Log4perl::Appender::Screen
2077    log4perl.appender.ScreenApp.stderr   = 0
2078    log4perl.appender.ScreenApp.layout   = SimpleLayout
2079       ### limiting output to ERROR messages
2080    log4perl.appender.ScreenApp.Threshold = ERROR
2081       ###
2082
2083Note that without the second appender's C<Threshold> setting, both appenders
2084would receive all messages prioritized DEBUG and higher. With the
2085threshold set to ERROR, the second appender will filter the messages
2086as required.
2087
2088=head2 Where should I put my logfiles?
2089
2090Your log files may go anywhere you want them, but the effective
2091user id of the calling process must have write access.
2092
2093If the log file doesn't exist at program start, Log4perl's file appender
2094will create it. For this, it needs write access to the directory where
2095the new file will be located in. If the log file already exists at startup,
2096the process simply needs write access to the file. Note that it will
2097need write access to the file's directory if you're encountering situations
2098where the logfile gets recreated, e.g. during log rotation.
2099
2100If Log::Log4perl is used by a web server application (e.g. in a CGI script
2101or mod_perl), then the webserver's user (usually C<nobody> or C<www>)
2102must have the permissions mentioned above.
2103
2104To prepare your web server to use log4perl, we'd recommend:
2105
2106    webserver:~$ su -
2107    webserver:~# mkdir /var/log/cgiapps
2108    webserver:~# chown nobody:root /var/log/cgiapps/
2109    webserver:~# chown nobody:root -R /var/log/cgiapps/
2110    webserver:~# chmod 02755 -R /var/log/cgiapps/
2111
2112Then set your /etc/log4perl.conf file to include:
2113
2114    log4perl.appender.FileAppndr1.filename =
2115        /var/log/cgiapps/<app-name>.log
2116
2117=head2 How can my file appender deal with disappearing log files?
2118
2119The file appender that comes with Log4perl, L<Log::Log4perl::Appender::File>,
2120will open a specified log file at initialization time and will
2121keep writing to it via a file handle.
2122
2123In case the associated file goes way, messages written by a
2124long-running process will still be written
2125to the file handle. In case the file has been moved to a different
2126location on the same file system, the writer will keep writing to
2127it under the new filename. In case the file has been removed from
2128the file system, the log messages will end up in nowhere land. This
2129is not a bug in Log4perl, this is how Unix works. There is
2130no error message in this case, because the writer has no idea that
2131the file handle is not associated with a visible file.
2132
2133To prevent the loss of log messages when log files disappear, the
2134file appender's C<recreate> option needs to be set to a true value:
2135
2136    log4perl.appender.Logfile.recreate = 1
2137
2138This will instruct the file appender to check in regular intervals
2139(default: 30 seconds) if the log file is still there. If it finds
2140out that the file is missing, it will recreate it.
2141
2142Continuously checking if the log file still exists is fairly
2143expensive. For this reason it is only performed every 30 seconds. To
2144change this interval, the option C<recreate_check_interval> can be set
2145to the number of seconds between checks. In the extreme case where the
2146check should be performed before every write, it can even be set to 0:
2147
2148    log4perl.appender.Logfile.recreate = 1
2149    log4perl.appender.Logfile.recreate_check_interval = 0
2150
2151To avoid having to check the file system so frequently, a signal
2152handler can be set up:
2153
2154    log4perl.appender.Logfile.recreate = 1
2155    log4perl.appender.Logfile.recreate_check_signal = USR1
2156
2157This will install a signal handler which will recreate a missing log file
2158immediatly when it receives the defined signal.
2159
2160Note that the init_and_watch() method for Log4perl's initialization
2161can also be instructed to install a signal handler, usually using the
2162HUP signal. Make sure to use a different signal if you're using both
2163of them at the same time.
2164
2165=head2 How can I rotate a logfile with newsyslog?
2166
2167Here's a few things that need to be taken care of when using the popular
2168log file rotating utilty C<newsyslog>
2169(http://www.courtesan.com/newsyslog) with Log4perl's file appender
2170in long-running processes.
2171
2172For example, with a newsyslog configuration like
2173
2174    # newsyslog.conf
2175    /tmp/test.log 666  12  5  *  B
2176
2177and a call to
2178
2179    # newsyslog -f /path/to/newsyslog.conf
2180
2181C<newsyslog> will take action if C</tmp/test.log> is larger than the
2182specified 5K in size. It will move the current log file C</tmp/test.log> to
2183C</tmp/test.log.0> and create a new and empty C</tmp/test.log> with
2184the specified permissions (this is why C<newsyslog> needs to run as root).
2185An already existing C</tmp/test.log.0> would be moved to
2186C</tmp/test.log.1>, C</tmp/test.log.1> to C</tmp/test.log.2>, and so
2187forth, for every one of a max number of 12 archived logfiles that have
2188been configured in C<newsyslog.conf>.
2189
2190Although a new file has been created, from Log4perl's appender's point
2191of view, this situation is identical to the one described in the
2192previous FAQ entry, labeled C<How can my file appender deal with
2193disappearing log files>.
2194
2195To make sure that log messages are written to the new log file and not
2196to an archived one or end up in nowhere land,
2197the appender's C<recreate> and C<recreate_check_interval> have to be
2198configured to deal with the 'disappearing' log file.
2199
2200The situation gets interesting when C<newsyslog>'s option
2201to compress archived log files is enabled. This causes the
2202original log file not to be moved, but to disappear. If the
2203file appender isn't configured to recreate the logfile in this situation,
2204log messages will actually be lost without warning. This also
2205applies for the short time frame of C<recreate_check_interval> seconds
2206in between the recreator's file checks.
2207
2208To make sure that no messages get lost, one option is to set the
2209interval to
2210
2211    log4perl.appender.Logfile.recreate_check_interval = 0
2212
2213However, this is fairly expensive. A better approach is to define
2214a signal handler:
2215
2216    log4perl.appender.Logfile.recreate = 1
2217    log4perl.appender.Logfile.recreate_check_signal  = USR1
2218    log4perl.appender.Logfile.recreate_pid_write = /tmp/myappid
2219
2220As a service for C<newsyslog> users, Log4perl's file appender writes
2221the current process ID to a PID file specified by the C<recreate_pid_write>
2222option.  C<newsyslog> then needs to be configured as in
2223
2224    # newsyslog.conf configuration for compressing archive files and
2225    # sending a signal to the Log4perl-enabled application
2226    /tmp/test.log 666  12  5  *  B /tmp/myappid 30
2227
2228to send the defined signal (30, which is USR1 on FreeBSD) to the
2229application process at rotation time. Note that the signal number
2230is different on Linux, where USR1 denotes as 10. Check C<man signal>
2231for details.
2232
2233=head2 How can a process under user id A log to a file under user id B?
2234
2235This scenario often occurs in configurations where processes run under
2236various user IDs but need to write to a log file under a fixed, but
2237different user id.
2238
2239With a traditional file appender, the log file will probably be created
2240under one user's id and appended to under a different user's id. With
2241a typical umask of 0002, the file will be created with -rw-rw-r--
2242permissions. If a user who's not in the first user's group
2243subsequently appends to the log file, it will fail because of a
2244permission problem.
2245
2246Two potential solutions come to mind:
2247
2248=over 4
2249
2250=item *
2251
2252Creating the file with a umask of 0000 will allow all users to append
2253to the log file. Log4perl's file appender C<Log::Log4perl::Appender::File>
2254has an C<umask> option that can be set to support this:
2255
2256    log4perl.appender.File = Log::Log4perl::Appender::File
2257    log4perl.appender.File.umask = sub { 0000 };
2258
2259This way, the log file will be created with -rw-rw-rw- permissions and
2260therefore has world write permissions. This might open up the logfile
2261for unwanted manipulations by arbitrary users, though.
2262
2263=item *
2264
2265Running the process under an effective user id of C<root> will allow
2266it to write to the log file, no matter who started the process.
2267However, this is not a good idea, because of security concerns.
2268
2269=back
2270
2271Luckily, under Unix, there's the syslog daemon which runs as root and
2272takes log requests from user processes over a socket and writes them
2273to log files as configured in C</etc/syslog.conf>.
2274
2275By modifying C</etc/syslog.conf> and HUPing the syslog daemon, you can
2276configure new log files:
2277
2278    # /etc/syslog.conf
2279    ...
2280    user.* /some/path/file.log
2281
2282Using the C<Log::Dispatch::Syslog> appender, which comes with the
2283C<Log::Log4perl> distribution, you can then send messages via syslog:
2284
2285    use Log::Log4perl qw(:easy);
2286
2287    Log::Log4perl->init(\<<EOT);
2288        log4perl.logger = DEBUG, app
2289        log4perl.appender.app=Log::Dispatch::Syslog
2290        log4perl.appender.app.Facility=user
2291        log4perl.appender.app.layout=SimpleLayout
2292    EOT
2293
2294        # Writes to /some/path/file.log
2295    ERROR "Message!";
2296
2297This way, the syslog daemon will solve the permission problem.
2298
2299Note that while it is possible to use syslog() without Log4perl (syslog
2300supports log levels, too), traditional syslog setups have a
2301significant drawback.
2302
2303Without Log4perl's ability to activate logging in only specific
2304parts of a system, complex systems will trigger log events all over
2305the place and slow down execution to a crawl at high debug levels.
2306
2307Remote-controlling logging in the hierarchical parts of an application
2308via Log4perl's categories is one of its most distinguished features.
2309It allows for enabling high debug levels in specified areas without
2310noticable performance impact.
2311
2312=head2 I want to use UTC instead of the local time!
2313
2314If a layout defines a date, Log::Log4perl uses local time to populate it.
2315If you want UTC instead, set
2316
2317    $Log::Log4perl::DateFormat::GMTIME = 1;
2318
2319in your program before the first log statement.
2320
2321=head2 Can Log4perl intercept messages written to a filehandle?
2322
2323You have a function that prints to a filehandle. You want to tie
2324into that filehandle and forward all arriving messages to a
2325Log4perl logger.
2326
2327First, let's write a package that ties a file handle and forwards it
2328to a Log4perl logger:
2329
2330    package FileHandleLogger;
2331    use Log::Log4perl qw(:levels get_logger);
2332
2333    sub TIEHANDLE {
2334       my($class, %options) = @_;
2335
2336       my $self = {
2337           level    => $DEBUG,
2338           category => '',
2339           %options
2340       };
2341
2342       $self->{logger} = get_logger($self->{category}),
2343       bless $self, $class;
2344    }
2345
2346    sub PRINT {
2347        my($self, @rest) = @_;
2348        $Log::Log4perl::caller_depth++;
2349        $self->{logger}->log($self->{level}, @rest);
2350        $Log::Log4perl::caller_depth--;
2351    }
2352
2353    sub PRINTF {
2354        my($self, $fmt, @rest) = @_;
2355        $Log::Log4perl::caller_depth++;
2356        $self->PRINT(sprintf($fmt, @rest));
2357        $Log::Log4perl::caller_depth--;
2358    }
2359
2360    1;
2361
2362Now, if you have a function like
2363
2364    sub function_printing_to_fh {
2365        my($fh) = @_;
2366        printf $fh "Hi there!\n";
2367    }
2368
2369which takes a filehandle and prints something to it, it can be used
2370with Log4perl:
2371
2372    use Log::Log4perl qw(:easy);
2373    usa FileHandleLogger;
2374
2375    Log::Log4perl->easy_init($DEBUG);
2376
2377    tie *SOMEHANDLE, 'FileHandleLogger' or
2378        die "tie failed ($!)";
2379
2380    function_printing_to_fh(*SOMEHANDLE);
2381        # prints "2007/03/22 21:43:30 Hi there!"
2382
2383If you want, you can even specify a different log level or category:
2384
2385    tie *SOMEHANDLE, 'FileHandleLogger',
2386        level => $INFO, category => "Foo::Bar" or die "tie failed ($!)";
2387
2388=head2 I want multiline messages rendered line-by-line!
2389
2390With the standard C<PatternLayout>, if you send a multiline message to
2391an appender as in
2392
2393    use Log::Log4perl qw(:easy);
2394    Log
2395
2396it gets rendered this way:
2397
2398    2007/04/04 23:23:39 multi
2399    line
2400    message
2401
2402If you want each line to be rendered separately according to
2403the layout use C<Log::Log4perl::Layout::PatternLayout::Multiline>:
2404
2405    use Log::Log4perl qw(:easy);
2406
2407    Log::Log4perl->init(\<<EOT);
2408      log4perl.category         = DEBUG, Screen
2409      log4perl.appender.Screen = Log::Log4perl::Appender::Screen
2410      log4perl.appender.Screen.layout = \\
2411        Log::Log4perl::Layout::PatternLayout::Multiline
2412      log4perl.appender.Screen.layout.ConversionPattern = %d %m %n
2413    EOT
2414
2415    DEBUG "some\nmultiline\nmessage";
2416
2417and you'll get
2418
2419    2007/04/04 23:23:39 some
2420    2007/04/04 23:23:39 multiline
2421    2007/04/04 23:23:39 message
2422
2423instead.
2424
2425=head2 I'm on Windows and I'm getting all these 'redefined' messages!
2426
2427If you're on Windows and are getting warning messages like
2428
2429  Constant subroutine Log::Log4perl::_INTERNAL_DEBUG redefined at
2430    C:/Programme/Perl/lib/constant.pm line 103.
2431  Subroutine import redefined at
2432    C:/Programme/Perl/site/lib/Log/Log4Perl.pm line 69.
2433  Subroutine initialized redefined at
2434    C:/Programme/Perl/site/lib/Log/Log4Perl.pm line 207.
2435
2436then chances are that you're using 'Log::Log4Perl' (wrong uppercase P)
2437instead of the correct 'Log::Log4perl'. Perl on Windows doesn't
2438handle this error well and spits out a slew of confusing warning
2439messages. But now you know, just use the correct module name and
2440you'll be fine.
2441
2442=head2 Log4perl complains that no initialization happened during shutdown!
2443
2444If you're using Log4perl log commands in DESTROY methods of your objects,
2445you might see confusing messages like
2446
2447    Log4perl: Seems like no initialization happened. Forgot to call init()?
2448    Use of uninitialized value in subroutine entry at
2449    /home/y/lib/perl5/site_perl/5.6.1/Log/Log4perl.pm line 134 during global
2450    destruction. (in cleanup) Undefined subroutine &main:: called at
2451    /home/y/lib/perl5/site_perl/5.6.1/Log/Log4perl.pm line 134 during global
2452    destruction.
2453
2454when the program shuts down. What's going on?
2455
2456This phenomenon happens if you have circular references in your objects,
2457which perl can't clean up when an object goes out of scope but waits
2458until global destruction instead. At this time, however, Log4perl has
2459already shut down, so you can't use it anymore.
2460
2461For example, here's a simple class which uses a logger in its DESTROY
2462method:
2463
2464    package A;
2465    use Log::Log4perl qw(:easy);
2466    sub new { bless {}, shift }
2467    sub DESTROY { DEBUG "Waaah!"; }
2468
2469Now, if the main program creates a self-referencing object, like in
2470
2471    package main;
2472    use Log::Log4perl qw(:easy);
2473    Log::Log4perl->easy_init($DEBUG);
2474
2475    my $a = A->new();
2476    $a->{selfref} = $a;
2477
2478then you'll see the error message shown above during global destruction.
2479How to tackle this problem?
2480
2481First, you should clean up your circular references before global
2482destruction. They will not only cause objects to be destroyed in an order
2483that's hard to predict, but also eat up memory until the program shuts
2484down.
2485
2486So, the program above could easily be fixed by putting
2487
2488    $a->{selfref} = undef;
2489
2490at the end or in an END handler. If that's hard to do, use weak references:
2491
2492    package main;
2493    use Scalar::Util qw(weaken);
2494    use Log::Log4perl qw(:easy);
2495    Log::Log4perl->easy_init($DEBUG);
2496
2497    my $a = A->new();
2498    $a->{selfref} = weaken $a;
2499
2500This allows perl to clean up the circular reference when the object
2501goes out of scope, and doesn't wait until global destruction.
2502
2503=head2 How can I access POE heap values from Log4perl's layout?
2504
2505POE is a framework for creating multitasked applications running in a
2506single process and a single thread. POE's threads equivalents are
2507'sessions' and since they run quasi-simultaneously, you can't use
2508Log4perl's global NDC/MDC to hold session-specific data.
2509
2510However, POE already maintains a data store for every session. It is called
2511'heap' and is just a hash storing session-specific data in key-value pairs.
2512To access this per-session heap data from a Log4perl layout, define a
2513custom cspec and reference it with the newly defined pattern in the layout:
2514
2515    use strict;
2516    use POE;
2517    use Log::Log4perl qw(:easy);
2518
2519    Log::Log4perl->init( \ q{
2520        log4perl.logger = DEBUG, Screen
2521        log4perl.appender.Screen = Log::Log4perl::Appender::Screen
2522        log4perl.appender.Screen.layout = PatternLayout
2523        log4perl.appender.Screen.layout.ConversionPattern = %U %m%n
2524        log4perl.PatternLayout.cspec.U = \
2525            sub { POE::Kernel->get_active_session->get_heap()->{ user } }
2526    } );
2527
2528    for (qw( Huey Lewey Dewey )) {
2529        POE::Session->create(
2530            inline_states => {
2531                _start    => sub {
2532                    $_[HEAP]->{user} = $_;
2533                    POE::Kernel->yield('hello');
2534                },
2535                hello     => sub {
2536                    DEBUG "I'm here now";
2537                }
2538            }
2539        );
2540    }
2541
2542    POE::Kernel->run();
2543    exit;
2544
2545The code snippet above defines a new layout placeholder (called
2546'cspec' in Log4perl) %U which calls a subroutine, retrieves the active
2547session, gets its heap and looks up the entry specified ('user').
2548
2549Starting with Log::Log4perl 1.20, cspecs also support parameters in
2550curly braces, so you can say
2551
2552    log4perl.appender.Screen.layout.ConversionPattern = %U{user} %U{id} %m%n
2553    log4perl.PatternLayout.cspec.U = \
2554            sub { POE::Kernel->get_active_session-> \
2555                  get_heap()->{ $_[0]->{curlies} } }
2556
2557and print the POE session heap entries 'user' and 'id' with every logged
2558message. For more details on cpecs, read the PatternLayout manual.
2559
2560=head2 I want to print something unconditionally!
2561
2562Sometimes it's a script that's supposed to log messages regardless if
2563Log4perl has been initialized or not. Or there's a logging statement that's
2564not going to be suppressed under any circumstances -- many people want to
2565have the final word, make the executive decision, because it seems like
2566the only logical choice.
2567
2568But think about it:
2569First off, if a messages is supposed to be printed, where is it supposed
2570to end up at? STDOUT? STDERR? And are you sure you want to set in stone
2571that this message needs to be printed, while someone else might
2572find it annoying and wants to get rid of it?
2573
2574The truth is, there's always going to be someone who wants to log a
2575messages at all cost, but also another person who wants to suppress it
2576with equal vigilance. There's no good way to serve these two conflicting
2577desires, someone will always want to win at the cost of leaving
2578the other party dissappointed.
2579
2580So, the best Log4perl offers is the ALWAYS level for a message that even
2581fires if the system log level is set to $OFF:
2582
2583    use Log::Log4perl qw(:easy);
2584
2585    Log::Log4perl->easy_init( $OFF );
2586    ALWAYS "This gets logged always. Well, almost always";
2587
2588The logger won't fire, though, if Log4perl hasn't been initialized or
2589if someone defines a custom log hurdle that's higher than $OFF.
2590
2591Bottom line: Leave the setting of the logging level to the initial Perl
2592script -- let their owners decided what they want, no matter how tempting
2593it may be to decide it for them.
2594
2595=cut 
2596
2597=head1 SEE ALSO
2598
2599Log::Log4perl
2600
2601=head1 LICENSE
2602
2603Copyright 2002-2012 by Mike Schilli E<lt>m@perlmeister.comE<gt>
2604and Kevin Goess E<lt>cpan@goess.orgE<gt>.
2605
2606This library is free software; you can redistribute it and/or modify
2607it under the same terms as Perl itself.
2608
2609=head1 AUTHOR
2610
2611Please contribute patches to the project on Github:
2612
2613    http://github.com/mschilli/log4perl
2614
2615Send bug reports or requests for enhancements to the authors via our
2616
2617MAILING LIST (questions, bug reports, suggestions/patches):
2618log4perl-devel@lists.sourceforge.net
2619
2620Authors (please contact them via the list above, not directly):
2621Mike Schilli <m@perlmeister.com>,
2622Kevin Goess <cpan@goess.org>
2623
2624Contributors (in alphabetical order):
2625Ateeq Altaf, Cory Bennett, Jens Berthold, Jeremy Bopp, Hutton
2626Davidson, Chris R. Donnelly, Matisse Enzer, Hugh Esco, Anthony
2627Foiani, James FitzGibbon, Carl Franks, Dennis Gregorovic, Andy
2628Grundman, Paul Harrington, David Hull, Robert Jacobson, Jason Kohles,
2629Jeff Macdonald, Markus Peter, Brett Rann, Peter Rabbitson, Erik
2630Selberg, Aaron Straup Cope, Lars Thegler, David Viner, Mac Yang.
2631
2632