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