smart logging with log4perl l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Smart Logging With Log4perl PowerPoint Presentation
Download Presentation
Smart Logging With Log4perl

Loading in 2 Seconds...

play fullscreen
1 / 88

Smart Logging With Log4perl - PowerPoint PPT Presentation


  • 99 Views
  • Uploaded on

Smart Logging With Log4perl. Mike Schilli, Yahoo! YAPC, 06/27/2007. Grab A T-Shirt!. Smart Logging With Log4perl. Mike Schilli, Yahoo! YAPC, 06/27/2007. Logging – why?. Go back in time and figure out what happened. Measure performance Trace activity on live systems

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Smart Logging With Log4perl' - duer


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
smart logging with log4perl

Smart Logging With Log4perl

Mike Schilli, Yahoo!

YAPC, 06/27/2007

Grab A T-Shirt!

smart logging with log4perl2

Smart Logging With Log4perl

Mike Schilli, Yahoo!

YAPC, 06/27/2007

logging why
Logging – why?
  • Go back in time and figure out what happened.
  • Measure performance
  • Trace activity on live systems
  • Debug during development
log4perl and log4j
Log4perl and Log4j
  • Log::Log4perl ports Log4j to Perl
  • Log4j: de facto Java loggingstandard, by Ceki Gülcü
    • Latest development: ‘logback’
  • http://logging.apache.org/log4j
  • Log::Log4perl adds perlisms demanded by users
log4perl history
Log4perl History
  • 0.01 release 2002
  • Current release 1.11 (06/2007)
  • Authors: Mike Schilli, Kevin Goess
  • Used by major banks, target.com, fedex.com, Yahoo!, Google, …
  • Several CPAN modules support it (e.g. Catalyst, Net::Amazon, …)
design goals
Design Goals
  • Easy to use in small scripts
  • Scales easily with growing architecture
  • Log4perl-enabled CPAN modules can be used with and without Log4perl initialization
  • Optimized for Speed
  • Open Architecture, extensible
why log4perl and not one of the 20 logging modules on cpan
Why Log4perl and not one of the 20 Logging modules on CPAN?
  • Write once, and L4p-enabled scripts/modules can be used
    • with any logging configuration you desire
    • by changing loggers, appenders and layouts independently
  • Target specific areas of your application only
  • No need to change your source code to change the logging behaviour
  • Log4perl is aimed to be the last logging module you’ll ever install
log log4perl for simple scripts
Log::Log4perl for Simple Scripts

#!/usr/bin/perl –w

use strict;

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init($INFO);

DEBUG "Won't make it";

INFO "Will go through";

ERROR "Will also go through";

$ easy.pl

2004/10/19 10:56:56 Will go through

2004/10/19 10:56:56 Will also go through

log log4perl for cpan modules
Log::Log4perl for CPAN Modules

use strict;

use YourCPANModule;

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init( $INFO);

YourCPANModule::somefunc();

package YourCPANModule;

use strict;

use Log::Log4perl qw(:easy);

sub somefunc {

DEBUG "Won't make it";

INFO "Will go through";

}

log log4perl for cpan modules11
Log::Log4perl for CPAN Modules

use strict;

use YourCPANModule;

YourCPANModule::somefunc();

package YourCPANModule;

use strict;

use Log::Log4perl qw(:easy);

sub somefunc {

DEBUG "Won't make it";

INFO "Won’t make it";

}

log log4perl building blocks
Log::Log4perl Building Blocks

Loggers

Layouts

Appenders

log log4perl building blocks13
Log::Log4perl Building Blocks

Loggers

Log it or suppress it

Layouts

Format it

Appenders

Write it out

log log4perl building blocks14
Log::Log4perl Building Blocks

DEBUG “Starting up”);

or

my $log = get_logger();

$log->debug(“Starting up”);

Loggers

Layouts

“Starting up” =>

2007-06-21 07:30:33 Foo.pm-123 Starting up

Appenders

Log File

Database

easy vs standard mode
Easy vs. Standard Mode

use Log::Log4perl qw(:easy);

sub somefunc {

DEBUG “Debug Message”;

INFO “Info Message”;

}

use Log::Log4perl qw(get_logger);

sub somefunc {

my $logger = get_logger();

$logger->debug(“Debug message”);

$logger->info(“Info message”);

}

log4perl operation
Log4perl Operation
  • Initialize once, at startup:
    • Define which loggers should fire base on
      • message priority (DEBUG, INFO, …)
      • location (Foo::Bar, …)
    • Define where messages should end up at
  • Loggers planted in program code get activated
easy init vs standard init
Easy Init vs. Standard Init

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init($INFO);

use Log::Log4perl;

Log::Log4perl->init(“l4p.conf”);

#l4p.conf

log4perl.category = INFO, Screen

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

log4perl.appender.Screen.stderr = 1

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::SimpleLayout

mix match standard init with easy functions
Mix&Match: Standard Init with Easy Functions

use Log::Log4perl qw(:easy);

Log::Log4perl->init(“l4p.conf”);

DEBUG “Debug Message”;

INFO “Info Message”;

#l4p.conf

log4perl.category = WARN, Logfile

log4perl.appender.Logfile = \

Log::Log4perl::Appender::File

log4perl.appender.Logfile.filename = test.log

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::SimpleLayout

categories areas of your app
Categories: Areas of your App

package Bar::Twix;

use Log::Log4perl qw(get_logger);

sub eat {

# Gets a Bar::Twix logger

my $logger = get_logger();

$logger->debug(“Debug Message”);

}

#l4p.conf

log4perl.category.Bar.Twix = WARN, Logfile

log4perl.appender.Logfile = \

Log::Log4perl::Appender::File

log4perl.appender.Logfile.filename = test.log

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::SimpleLayout

categories easy mode
Categories (Easy Mode)

package Bar::Twix;

use Log::Log4perl qw(:easy);

sub eat {

# Has a Bar::Twix logger

DEBUG “Debug Message”;

}

#l4p.conf

log4perl.category.Bar.Twix = WARN, Logfile

log4perl.appender.Logfile = \

Log::Log4perl::Appender::File

log4perl.appender.Logfile.filename = test.log

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::SimpleLayout

loggers
Loggers
  • Have a
    • category (e.g. “Net::Amazon” )
    • priority (e.g. $DEBUG )
  • Take a message (e.g. “Starting” )
loggers24
Loggers
  • Pass on their message if
    • logging has been configured for
      • their category ( “Net::Amazon”) or
      • a parent category ( “Net”, “” )
    • and (!) the message priority (e.g. $DEBUG) is greater or equal than the configured log level (e.g. $DEBUG) for the category
limit throughput levels and categories
Limit Throughput: Levels and Categories
  • Categoriesdetermine which parts of the system are addressed.

my $log = get_logger(“Net::Amazon”);

or simply

package Net::Amazon;

DEBUG “…”;

  • Levelsindicate the message priority.

$log->debug(“Request sent ($bytes bytes)”;

log levels
Log Levels
  • Levels
    • $TRACE
    • $DEBUG
    • $INFO
    • $WARN
    • $ERROR
    • $FATAL
    • $OFF
log levels27
Log Levels
  • Methods
    • $log->trace(“$bytes bytes transferred”);
    • $log->debug(“HTTP get OK”);
    • $log->info(“Starting up”);
    • $log->warn(“HTTP get failed, retrying”);
    • $log->error(“Out of retries!”);
    • $log->fatal(“Panic! Shutting down.”);
log levels28
Log Levels
  • Macros
    • TRACE(“$bytes bytes transferred”);
    • DEBUG(“HTTP get OK”);
    • INFO(“Starting up”);
    • WARN(“HTTP get failed, retrying”);
    • ERROR(“Out of retries!”);
    • FATAL(“Panic! Shutting down.”);
remote control via categories
Remote Control via Categories

l4p.conf

log4perl.category = DEBUG, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Makes it through!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Makes it through”;

remote control via categories30
Remote Control via Categories

l4p.conf

Log4perl.category = ERROR, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Gets blocked!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Gets blocked”;

remote control via categories31
Remote Control via Categories

l4p.conf

Log4perl.category = FATAL, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Gets blocked!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Gets blocked!”;

DEBUG “Gets blocked”;

remote control via categories32
Remote Control via Categories

l4p.conf

Log4perl.category.main = DEBUG, Screen

Log4perl.category.Net.Amazon = ERROR, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Makes it through!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Gets blocked”;

remote control via categories33
Remote Control via Categories

l4p.conf

Log4perl.category.main = ERROR, Screen

Log4perl.category.Net.Amazon = DEBUG, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Gets blocked”;

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Makes it through!”;

category inheritance 1
Category Inheritance (1)

l4p.conf

Log4perl.category.main = DEBUG, Screen

Log4perl.category.Net = ERROR, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Makes it through!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Gets blocked”;

category inheritance 2
Category Inheritance (2)

l4p.conf

Log4perl.category.main = DEBUG, Screen

Log4perl.category = ERROR, Screen

#!/usr/bin/perl

use Net::Amazon;

Log::Log4perl->init(“l4p.conf”);

DEBUG “Makes it through!”

my $amzn = Net::Amazon->new();

package Net::Amazon;

ERROR “Makes it through!”;

DEBUG “Gets blocked”;

log4perl flow

Appender

Appender

Appender

Log4perl Flow

Application sends a log message (Category, Priority)

Log4perl Configuration decides go/no go, based on Category and Priority

?

Layout

l4p conf screen appender
l4p.conf: Screen Appender

log4perl.category.main = DEBUG, ScreenLog4perl.category.Net.Amazon = INFO, Screen

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

l4p conf file appender
l4p.conf: File Appender

log4perl.category.main = DEBUG, Logfile

Log4perl.category.Net.Amazon = INFO, Logfile

log4perl.appender.Logfile = \

Log::Log4perl::Appender::File

log4perl.appender.Logfile.filename = test.log

l4p conf two appenders
l4p.conf: Two appenders

log4perl.category.main = DEBUG, Logfile

Log4perl.category.Net.Amazon = INFO, Screen

log4perl.appender.Logfile = \

Log::Log4perl::Appender::File

log4perl.appender.Logfile.filename = test.log

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

init and watch
Init and Watch
  • Log::Log4perl->init(“l4p.conf”);
  • Log::Log4perl->init(\$conf_string);
  • Log::Log4perl->init_and_watch(“l4p.conf”, 30);
  • Log::Log4perl->init_and_watch(“l4p.conf”, ‘HUP’ );
appenders
Appenders
  • Appenders are output sinks
  • Get called if a message passes category and level hurdles
appenders43
Appenders
  • Log::Log4perl::Appender::Screen Log::Log4perl::Appender::File Log::Log4perl::Appender::Socket Log::Log4perl::Appender::DBI Log::Log4perl::Appender::Synchronized Log::Log4perl::Appender::RRDs
  • Log::Dispatch provides even more:
log dispatch appenders
Log::Dispatch Appenders
  • Log::Dispatch::ApacheLog Log::Dispatch::DBI, Log::Dispatch::Email, Log::Dispatch::Email::MIMELite Log::Dispatch::File Log::Dispatch::FileRotate Log::Dispatch::Screen Log::Dispatch::Syslog, Log::Dispatch::Tk
example rotating log file appender
Example: Rotating Log File Appender
  • Keep 5 days of logfiles, then delete:

log4perl.category = WARN, Logfile

log4perl.appender.Logfile = Log::Dispatch::FileRotate

log4perl.appender.Logfile.filename = test.log

log4perl.appender.Logfile.max = 5

log4perl.appender.Logfile.DatePattern = yyyy-MM-dd

log4perl.appender.Logfile.TZ = PST

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::SimpleLayout

rotating files
Rotating Files
  • Rotating File Appender:
    • Log::Dispatch::FileRotate
    • Single request pays for rotation
    • Rotation runs as particular user
  • External Rotators (e.g. newsyslog):
    • recreate flag makes sure file appender adjusts
    • recreate_check_interval saves on stat() calls
write your own appender 1
Write Your Own Appender (1)

package ColorScreenAppender;

our @ISA = qw(Log::Log4perl::Appender);

use Term::ANSIColor;

sub new {

my($class, %options) = @_;

my $self = {%options, …};

bless $self, $class;

}

sub log {

my($self, %params) = @_;

print colored($params{message},

$self->{color});

}

write your own appender 2
Write Your Own Appender (2)

log4perl.logger = INFO, ColorApp log4perl.appender.ColorApp=ColorScreenAppender log4perl.appender.ColorApp.color = red log4perl.appender.ColorApp.layout = SimpleLayout

layouts
Layouts
  • SimpleLayout

$log->debug(“Sending Mail”);

DEBUG – Sending Mail

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

log4perl.appender.Screen.layout = SimpleLayout

layouts50
Layouts
  • PatternLayout

$log->debug(“Sending Mail”);

2004/10/17 18:47:25 l4ptest.pl:25> Sending Mail

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::PatternLayout

log4perl.appender.Logfile.layout.ConversionPattern = \

%d %F{1}:%L> %m %n

layouts51
Layouts
  • PatternLayout

%c Category of the logging event.

%C Fully qualified package (or class) name of the caller

%d Current date in yyyy/MM/dd hh:mm:ss format

%F File where the logging event occurred

%H Hostname

%l calling method + file + line

%L Line number within the file where the log statement was issued

%m The message to be logged

%M Method or function where the logging request was issued

%n Newline (OS-independent)

%p Priority of the logging event

%P pid of the current process

%r Number of milliseconds elapsed from program start

%x The elements of the NDC stack

%X{key} The entry 'key' of the MDC

%% A literal percent (%) sign

layouts52
Layouts
  • Still not enough? Write your own:

log4perl.PatternLayout.cspec.U = sub { return "UID $<" }

log4perl.appender.Logfile.layout = \

Log::Log4perl::Layout::PatternLayout

log4perl.appender.Logfile.layout.ConversionPattern = \

%d %U> %m %n

filters
Filters
  • Last minute chance for Appenders to block
  • More expensive than Level/Category blocking
  • Text/Level Match comes with L4p
  • Write your own custom filters
filters54
Filters

log4perl.category = INFO, Screen

log4perl.filter.MyFilter = \

Log::Log4perl::Filter::StringMatch

log4perl.filter.M1.StringToMatch = let this through

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

log4perl.appender.Screen.Filter = MyFilter log4perl.appender.Screen.layout = \

Log::Log4perl::Layout::SimpleLayout

filters55
Filters

log4perl.filter.M1 = Log::Log4perl::Filter::StringMatch log4perl.filter.M1.StringToMatch = let this through log4perl.filter.M1.AcceptOnMatch = true

log4perl.filter.M1 = Log::Log4perl::Filter::LevelMatch log4perl.filter.M1.LevelToMatch = INFO log4perl.filter.M1.AcceptOnMatch = true

avoid wasting cycles
Avoid Wasting Cycles

for (@super_long_array) {

$logger->debug("Element: $_\n");

}

if($logger->is_debug()) {

for (@super_long_array) {

$logger->debug("Element: $_\n");

}

}

performance
Performance
  • On a Pentium 4 Linux box at 2.4 GHz, you'll get through
    • 500,000 suppressed log statements per second
    • 30,000 logged messages per second (using an in-memory appender)
    • init_and_watch delay mode: 300,000 suppressed, 30,000 logged.
    • init_and_watch signal mode: 450,000 suppressed, 30,000 logged.
infiltrating lwp
Infiltrating LWP
  • Ever wondered what LWP is doing behind the scenes?

use LWP::UserAgent;

use HTTP::Request::Common;

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init($DEBUG);

Log::Log4perl->infiltrate_lwp();

my $ua = LWP::UserAgent->new();

my $resp = $ua->request(GET "http://www.yahoo.com");

infiltrating lwp61
Infiltrating LWP
  • Getting LWP to use Log4perl for logging:

2004/10/20 18:36:43 ()

2004/10/20 18:36:43 ()

2004/10/20 18:36:43 GET http://www.yahoo.com

2004/10/20 18:36:43 Not proxied

2004/10/20 18:36:43 ()

2004/10/20 18:36:43 read 634 bytes

2004/10/20 18:36:43 read 4096 bytes

2004/10/20 18:36:43 read 2488 bytes

2004/10/20 18:36:43 Simple response: OK

resurrect in a single file
Resurrect in a Single File
  • The :resurrect target uncomments lines starting with ###l4p:

use Log4perl qw(:easy :resurrect);

sub foo {

# …

###l4p DEBUG “foo was here”;

}

resurrect l4p in all modules
Resurrect L4p in all Modules
  • The Log::Log4perl::Resurrector touches all subsequently loaded modules (experimental!):

use Log4perl qw(:easy);

use Log::Log4perl::Resurrector;

use Foo::Bar;

# Deploy a module without requiring L4p at all!

package Foo::Bar;

###l4p use Log4perl qw(:easy);

sub foo {

###l4p DEBUG “This will be resurrected!”;

}

pitfalls
Pitfalls

Beginner’s Pitfalls

beginner s pitfalls
Beginner’s Pitfalls
  • Appender Additivity:
    • Once a lower level logger decides to fire, it will forward the message to its appenders.
    • It will also forward the message unconditionally to all of its parent logger’s appenders.
beginner s pitfalls66
Beginner’s Pitfalls
  • Appender Additivity (with dupes)

log4perl.category = FATAL, Screen

log4perl.category.Net.Amazon = DEBUG, Screen

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

log4perl.appender.Screen.layout = SimpleLayout

package Net::Amazon;

DEBUG(“Debugging!”);

DEBUG - Debugging!

DEBUG - Debugging!

appender additivity
Appender Additivity

File Appender

root

FATAL

Screen Appender

Net

Net::Amazon

DEBUG

beginner s pitfalls68
Beginner’s Pitfalls
  • Appender Additivity (no dupes)

log4perl.category = ERROR, Screen

log4perl.category.Net.Amazon = DEBUG, Screen

log4perl.additivity.Net.Amazon = 0

log4perl.appender.Screen = \

Log::Log4perl::Appender::Screen

log4perl.appender.Screen.layout = SimpleLayout

package Net::Amazon;

DEBUG(“Debugging!”); Q

DEBUG – Debugging!

log log4perl availability
Log::Log4perl Availability
  • Cpan> install Log::Log4perl
    • Only requires core modules
  • Requires Perl 5.00503 or better
  • Included in major Linux distros
  • Windows: ppm package available in ActiveState archives or from log4perl.sf.net
best practices
Best Practices
  • Don’t provide program name, function name in the message. Use Layouts instead.
  • Log plenty. Don’t worry about space, use rotating log files for chatty output.
what you should log
What you should log
  • Program starting up, shutting down
  • Function parameters
  • Milestones in request processing
  • Start/end of lenghty operations (e.g. DB access)
what you shouldn t log
What you shouldn’t log
  • Function/method names (although you want parameters)
  • Date
  • Process ID
  • … everything else provided by the layout
best practices73
Best Practices
  • Rolling out new L4p-enabled Modules

package My::Module;

use Log::Log4perl qw(:easy);

sub new { # … }

sub foo { DEBUG “I’m here”; # … }

sub bar { INFO “Now I’m here”; # … }

# Use w/o Log4perl

use My::Module;

$o = My::Module->new();

$o->foo();

# Log4perl enabled

use My::Module;

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init($DEBUG);

$o = My::Module->new();

$o->foo();

gotchas
Gotchas
  • Avoid ‘append’ on NFS (creating lots of ‘read’ traffic)
  • Don’t put expensive operations into the logger call which are executed before the logger decides
  • Permission issues with rotating file appenders
mod perl
mod_perl
  • Init() in startup handler
  • Current limitation: One init().
  • Use init_once() if you’re not sure who inits first.
combat overlapping messages
Combat overlapping Messages
  • Either live with it or
    • Use the Synchronized appender
    • Use Appender.File.syswrite=1
driving log log4perl further
Driving Log::Log4perl further
  • Bug Fixes:

Submit to log4perl-devel@sourceforge.net

  • New Features:

Propose features or send patches

  • New Appenders:

Release separately as a module in the Log::Log4perl::Appender::xx namespace on CPAN

  • … or contact me: mschilli@yahoo-inc.com
slide78
Q & A

Q & A

thank you
Thank You!

Log::Log4perl Project Page:

http://log4perl.sourceforge.net

Email me:

Mike Schilli

mschilli@yahoo-inc.com

Post to the List:

log4perl-devel@sourceforge.net

error handling
Error Handling

use Log::Log4perl qw(:easy);

do_something or

LOGDIE “Horrible error!”;

  • LOGCARP, LOGCLUCK, LOGCONFESS etc. also available.
displaying logs with chainsaw
Displaying Logs with Chainsaw
  • Log4j features an XML layout and a socket appender
  • XML output is displayed in a nice GUI called Chainsaw
  • Log::Log4perl also features an XML layout and a socket appender
  • … XML output is also displayed in a nice GUI called Chainsaw!
displaying logs with chainsaw83
Displaying Logs with Chainsaw

Log::Log4perl enabled Perl Script

Log::Log4perl::Layout::XML

Log::Log4perl::Appender::Socket

Java / log4j Program

the future
The Future
  • Allow multiple configurations within the same process (e.g. for mod_perl)
easy mode init with files
Easy Mode Init with Files

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init({

level => $DEBUG,

file => “>file.log”,

category => “Bar::Twix”,

});

multiline layout
Multiline Layout

Instead of

2007/04/04 23:59:01 This is

a message with

multiple lines

get this:

2007/04/04 23:59:01 This is

2007/04/04 23:59:01 a message with

2007/04/04 23:59:01 multiple lines

with PatternLayout::Multiline:

log4perl.appender.Logfile. layout = \

Log::Log4perl::Layout::PatternLayout::Multiline

log4perl.appender.Logfile.layout.ConversionPattern = %d %m %n

perl hooks
Perl Hooks
  • Add parameters known at init() time

log4perl.appender.Logfile.filename = sub { \

“mylog.$$.log” }