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