This is Bavaria, Germany!
use Log::Log4perl qw(:easy);
# Set priority of root logger to ERROR
Log::Log4perl->easy_init($ERROR);
# Application Section
my $logger = get_logger();
# Will not be logged:
$logger->info("I do this and that");
# Will be logged:
$logger->error("Bad");
Logging looks like this:
C:\temp>perl test.pl
2004/10/18 10:48:13 Bad
#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl;
my $log_conf = q/
log4perl.category = INFO, Logfile, Screen
log4perl.appender.Logfile = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename = your_logfilename.log
log4perl.appender.Logfile.mode = write
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::SimpleLayout
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout
/;
Log::Log4perl::init( \$log_conf );
my $logger = Log::Log4perl::get_logger();
$logger->info("Starting $0");
$logger->error("Bad thing happened");
#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl;
use Hob::Inventory;
use Hob::GetWishlist;
use Hob::Harvester;
# Logging (mode=write|append)
my $log_conf = q/
log4perl.category = INFO, Logfile, Screen
log4perl.appender.Logfile = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename = your_logfilename.log
log4perl.appender.Logfile.mode = write
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Logfile.layout.ConversionPattern = %d %p> %m%n
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.stderr = 0
log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Screen.layout.ConversionPattern = %d %p> %m%n
log4perl.logger.main = INFO
log4perl.logger.Hob.Inventory = INFO
log4perl.logger.Hob.GetWishlist = INFO
log4perl.logger.Hob.Harvester = INFO
log4perl.logger.Hob.Harvester.Anna = INFO
log4perl.logger.Hob.Harvester.Petra = DEBUG
log4perl.logger.Hob.Harvester.Ludmilla = INFO
/;
# Create Singleton-Object
Log::Log4perl::init( \$log_conf );
# Logging ready
my $logger = Log::Log4perl::get_logger("main");
$log->info("Starting $0");
my $badthing=1;
if ($badthing) {
$log->error("bad thing happened");
}
my $fatalthing=1
if ($fatalthing) {
$log->logdie("fatal thing happened, I die");
}
In every module you use do this:
package Hob::Inventory;
use strict;
use warnings;
use Log::Log4perl;
sub new {
my($class,%args) = @_;
my %defaults = (
verbose => 1,
find_these => [ qw/jpg gif/ ],
);
my $self = bless {
%defaults,
%args,
# get Logger-Singleton and get environment for "Hob.Inventory"
logger => Log::Log4perl->get_logger('Hob.Inventory'),
}, $class;
$self->check_args;
return $self;
}
sub _logger { shift->{logger}; }
sub check_args {
my $self = shift;
$self->_logger->debug('Checking arguments');
...
}
1;
package Hob::Harvester;
use strict;
use File::Basename;
use Log::Log4perl qw(:levels);
# ...
my $logger = Log::Log4perl->get_logger('Hob.Harvester');
$logger->level($DEBUG);
# Take the fully qualified variable name if you
# don't want to import :levels like this:
# $logger->level($Log::Log4perl::DEBUG);
If you want to switch the runlevel only for a small part in
the program do this:
my $logger = Log::Log4perl->get_logger('Findus.Oldinicatcher');
# determine and remember old level (DEBUG)
my $loglevel_org = $logger->level();
# set loglevel to ERROR not get flooded with DEBUG-messages
$logger->level($Log::Log4perl::ERROR);
# ... do the things with less logging
# ... do
# ... do
# return to old loglevel
$logger->level($loglevel_org);
#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl;
my $log_conf = q/
log4perl.category = INFO, Logfile
log4perl.appender.Logfile = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename = sub { return get_log_fn(); }
log4perl.appender.Logfile.mode = write
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::SimpleLayout
/;
Log::Log4perl::init( \$log_conf );
my $logger = Log::Log4perl::get_logger();
$logger->info("Starting $0");
$logger->error("Bad thing happened");
=head2 get_log_fn
Return Logfilename for this programm. It is the basename of this programm
with a ".log" ending.
=cut
sub get_log_fn {
use File::Basename;
return sprintf "%s.log", basename( $0, '.pl' );
}
# Separate configfile: customer.logconfig
log4perl.category = DEBUG, Screen, Logfile
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.layout = Log::Log4perl::Layout::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 (if Sys::Hostname is available)
# %l Fully qualified name of the calling method followed by the
# callers source the file name and line number between
# parentheses.
# %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 to logging
# event
# %T A stack trace of functions called
# %x The topmost NDC (see below)
# %X{key} The entry 'key' of the MDC (see below)
# %% A literal percent (%) sign
log4perl.appender.Screen.layout.ConversionPattern = %p> %m
log4perl.appender.Logfile = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename = t.log
log4perl.appender.Logfile.mode = append
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Logfile.layout.ConversionPattern = %d %p> %m%n
log4perl.logger.main = INFO
log4perl.logger.customers.get = DEBUG
Now tell the program where to find the config-file for logging:
#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl;
my $conf_file = 't.logconfig';
# read config file only one time!
# Log::Log4perl->init( $conf_file );
# Re-read config file every 5 seconds
Log::Log4perl->init_and_watch( $conf_file, 5 );
my $logger = Log::Log4perl::get_logger('main');
$logger->debug("Starting $0");
# you need the perlmodule Log::Dispatch::FileRotate for that!
...
log4perl.appender.Logfile = Log::Dispatch::FileRotate
log4perl.appender.Logfile.filename = findus.log
log4perl.appender.Logfile.mode = append
log4perl.appender.Logfile.max = 2
log4perl.appender.Logfile.size = 10_000_000
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.Logfile.layout.ConversionPattern = %d %p: %M> %m%n
...
use strict;
use warnings;
use Config::IniFiles;
use File::Basename;
use Log::Log4perl;
my $ini_obj = Config::IniFiles->new( -file => $ini_fn ) || die;
init_logger_by_section_in_inifile( { ini_obj => $ini_obj } );
my $logger = Log::Log4perl::get_logger();
$logger->info("ok!");
=head2 init_logger_by_section_in_inifile
Initialize Log::Log4perl with an ini-File. You must supply a
section for Log4perl like this:
[log4perl]
log4perl.category = INFO, Logfile, Screen
log4perl.appender.Logfile = Log::Log4perl::Appender::File
log4perl.appender.Logfile.filename = your_logfile.log
log4perl.appender.Logfile.mode = write
log4perl.appender.Logfile.layout = Log::Log4perl::Layout::SimpleLayout
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout
[myfiles]
...
[myvalues1]
...
Usage:
init_logger_by_section_in_inifile(
{
ini_obj => $ini_obj, # mandatory
section => "log4perl", # optional, default is "log4perl"
}
);
# and then:
my $logger = Log::Log4perl->get_logger('main');
Returnvalues:
Returns nothing.
Errors:
Dies if ini_obj is not of type Config::IniFiles
=cut
sub init_logger_by_section_in_inifile {
my $args_rh = shift;
my $ini_obj = $args_rh->{ini_obj};
my $section = 'log4perl' if ! exists $args_rh->{section};
if (! $ini_obj || ref($ini_obj) ne 'Config::IniFiles') {
die 'You must supply a valid ini_obj';
}
my $log_conf;
for my $var ( $ini_obj->Parameters($section) ) {
next unless defined $var;
$log_conf .= sprintf "%s=%s\n", $var, $ini_obj->val( 'log4perl', $var );
}
Log::Log4perl::init( \$log_conf );
}
=head2 _get_logger
Get the logger with the name of this package
Usage:
my $logger = $self->_get_logger();
# If this is package A::B::C -> get logger for 'A.B.C'
or
my $logger = $self->_get_logger('XXX');
# If this is package A::B::C -> get logger for 'A.B.C.XXX'
=cut
sub _get_logger {
my $self = shift;
my $cur_package = ref $self;
my $log_focus = @_ ? $cur_package . '::' . shift() : $cur_package;
$log_focus =~ s{::}{.}g;
Log::Log4perl::get_logger($log_focus);
}
The program needs an inifile anyway, so I have an extra section for log4perl in this file too.
#!/usr/bin/perl
use strict;
use warnings;
use Config::IniFiles;
use Log::Log4perl::ConfigByInifile;
my $ini = Config::IniFiles->new( -file => 'fingerprints.ini' )
|| die;
Log::Log4perl::ConfigByInifile->new( { ini_obj => $ini, } );
my $logger = Log::Log4perl::get_logger();
$logger->info("ok!");
And this is the inifile
[log4perl] log4perl.category = INFO, Screen log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout log4perl.logger.main = INFO log4perl.logger.Ju.Hei = INFO