pp2@europa:~/src/perl/perltesting$ cat -n log4perldrink.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use Log::Log4perl qw(:easy); 4 5 my $level = eval shift @ARGV || $DEBUG; 6 7 Log::Log4perl->easy_init( 8 { 9 level => $level, 10 layout => '%d %p %F{1}-%L-%M: %m%n', 11 } 12 ); 13 14 drink(); 15 drink("Soda"); 16 17 sub drink { 18 my($what) = @_; 19 20 my $logger = get_logger(); 21 22 if(defined $what) { 23 $logger->info("Drinking ", $what); 24 } else { 25 $logger->error("No drink defined"); 26 } 27 }
Sigue un ejemplo de ejecución:
pp2@europa:~/src/perl/perltesting$ perl log4perldrink.pl '$ERROR' 2009/04/13 14:43:09 ERROR log4perldrink.pl-25-main::drink: No drink defined
Véase Log::Log4perl::Layout::PatternLayout para entender el significado de los símbolos en la cadena de formato.
pp2@europa:~/src/perl/perltesting$ cat -n ./eat.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 ######### System initialization section ### 5 use Log::Log4perl qw(get_logger :levels); 6 7 my $food_logger = get_logger("Groceries::Food"); 8 $food_logger->level($INFO); 9 10 # Appenders 11 my $appender = Log::Log4perl::Appender->new( 12 "Log::Dispatch::File", 13 filename => "test.log", 14 mode => "append", 15 ); 16 17 $food_logger->add_appender($appender); 18 19 # Layouts 20 my $layout = 21 Log::Log4perl::Layout::PatternLayout->new( 22 "%d %p> %F{1}:%L %M - %m%n"); 23 $appender->layout($layout); 24 25 ######### Run it ########################## 26 my $food = Groceries::Food->new("Sushi"); 27 my $otherfood = Groceries::Food->new(); 28 $food->consume(); 29 30 ######### Application section ############# 31 package Groceries::Food; 32 33 use Log::Log4perl qw(get_logger); 34 35 sub new { 36 my($class, $what) = @_; 37 38 my $logger = get_logger("Groceries::Food"); 39 40 if(defined $what) { 41 $logger->debug("New food: $what"); 42 return bless { what => $what }, $class; 43 } 44 45 $logger->error("No food defined"); 46 return undef; 47 } 48 49 sub consume { 50 my($self) = @_; 51 52 my $logger = get_logger("Groceries::Food"); 53 $logger->info("Eating $self->{what}"); 54 }Cuando se ejecuta produce:
pp2@europa:~/src/perl/perltesting$ rm test.log pp2@europa:~/src/perl/perltesting$ ./eat.pl pp2@europa:~/src/perl/perltesting$ cat test.log 2009/04/01 15:35:30 ERROR> eat.pl:45 Groceries::Food::new - No food defined 2009/04/01 15:35:30 INFO> eat.pl:53 Groceries::Food::consume - Eating Sushi
$logger->trace("..."); # Log a trace message
$logger->debug("..."); # Log a debug message
$logger->info("..."); # Log a info message
$logger->warn("..."); # Log a warn message
$logger->error("..."); # Log a error message
$logger->fatal("..."); # Log a fatal message
%F
,
%F{1}
,
%F{2}
y
%F{3}
?
pp2@europa:~/src/perl/perltesting$ cat eat.conf log4perl.logger.Groceries=DEBUG, A1 log4perl.appender.A1=Log::Dispatch::File log4perl.appender.A1.filename=test.log log4perl.appender.A1.mode=append log4perl.appender.A1.layout=Log::Log4perl::Layout::PatternLayout log4perl.appender.A1.layout.ConversionPattern=%d %p> %F{1}:%L %M - %m%ny reescriba el programa anterior para que la configuración del logger se lea desde el fichero:
Log::Log4perl->init("eat.conf");
El siguiente ejemplo ilustra el uso de jerarquías en Log::Log4perl:
1 #!/usr/bin/perl -w 2 use strict; 3 4 use Log::Log4perl qw(get_logger :levels); 5 6 Log::Log4perl->easy_init( 7 { 8 level => $DEBUG, 9 layout => '%d %p %F{1}-%L-%M: %m%n', 10 } 11 ); 12 13 my $layout = Log::Log4perl::Layout::PatternLayout->new("%H> %p: %m%n"); 14 my $appender = 15 Log::Log4perl::Appender->new( 'Log::Log4perl::Appender::ScreenColoredLevels', 16 ); 17 $appender->layout($layout); 18 19 my $appliances_logger = get_logger("Groceries::Appliances"); 20 $appliances_logger->level($ERROR); 21 22 my $groceries_logger = get_logger("Groceries"); 23 $groceries_logger->level($INFO); 24 $groceries_logger->add_appender($appender); 25 26 my $b = Groceries::Food->new('banana'); 27 my $c = Groceries::Food->new(); 28 $b->consume; 29 30 my $d = Groceries::Appliances->new('TV'); 31 my $e = Groceries::Appliances->new(); 32 $d->consume; 33 34 package Groceries::Food; 35 36 use Log::Log4perl qw(get_logger); 37 38 sub new { 39 my ( $class, $what ) = @_; 40 41 my $logger = get_logger("Groceries::Food"); 42 43 if ( defined $what ) { 44 $logger->debug("New food: $what"); 45 return bless { what => $what }, $class; 46 } 47 48 $logger->error("No food defined"); 49 return undef; 50 } 51 52 sub consume { 53 my ($self) = @_; 54 55 my $logger = get_logger("Groceries::Food"); 56 $logger->info("Eating $self->{what}"); 57 } 58 59 package Groceries::Appliances; 60 61 use Log::Log4perl qw(get_logger); 62 63 sub new { 64 my ( $class, $what ) = @_; 65 66 my $logger = get_logger("Groceries::Appliances"); 67 68 if ( defined $what ) { 69 $logger->debug("New appliance: $what"); 70 return bless { what => $what }, $class; 71 } 72 73 $logger->error("No appliance defined"); 74 return undef; 75 } 76 77 sub consume { 78 my ($self) = @_; 79 80 my $logger = get_logger("Groceries::Appliances"); 81 $logger->info("Using $self->{what}"); 82 }
Cuando se ejecuta produce la salida:
pp2@europa:~/src/perl/perltesting$ ./log4perlgroceries.pl europa> ERROR: No food defined 2009/04/01 15:18:50 ERROR log4perlgroceries.pl-48-Groceries::Food::new: No food defined europa> INFO: Eating banana 2009/04/01 15:18:50 INFO log4perlgroceries.pl-56-Groceries::Food::consume: Eating banana europa> ERROR: No appliance defined 2009/04/01 15:18:50 ERROR log4perlgroceries.pl-73-Groceries::Appliances::new: No appliance definedlos mensajes asociados con la categoría
Groceries::Food
aparecen coloreados según su nivel.
Eating banana
,
No appliance defined
, etc en los dos layouts?
Remember when we said that if a logger decides to fire, then it forwards the message to all of its appenders and also has it bubble up the hierarchy to hit all other appenders it meets on the way up?
threshold
de un appender?
¿que ocurre si ponemos $appender->threshold($FATAL)
en el appender asociado con Groceries
?
"Groceries::Appliances"
si se comenta la línea 20?
20 $appliances_logger->level($ERROR);
"Groceries::Appliances"
a fichero.
my $appender = Log::Log4perl::Appender->new( "Log::Dispatch::File", filename => "test.log", mode => "append", ); $$appliances_logger->add_appender($appender);
my $conf =<<END_LOG4PERLCONF; # Screen output at INFO level log4perl.rootLogger=DEBUG, SCREEN # Info to screen and logfile log4perl.appender.SCREEN.Threshold=$log_level log4perl.appender.SCREEN=Log::Log4perl::Appender::ScreenColoredLevels log4perl.appender.SCREEN.layout=PatternLayout log4perl.appender.SCREEN.layout.ConversionPattern=%d %m%n log4perl.appender.SCREEN.stderr=0 END_LOG4PERLCONF
por esta:
my $conf =<<END_LOG4PERLCONF; log4perl.rootLogger=DEBUG, LOGFILE # Info to screen and logfile log4perl.appender.LOGFILE=Log::Log4perl::Appender::File log4perl.appender.LOGFILE.filename=/home/pp2/src/perl/Net-CascadeCopy/myerrs.log log4perl.appender.LOGFILE.mode=append log4perl.appender.LOGFILE.layout=PatternLayout log4perl.appender.LOGFILE.layout.ConversionPattern=%d %F %L %m%n END_LOG4PERLCONF¿Cómo cambia la conducta? Que pasa si cambiamos la primera línea:
g4perl.rootLogger=DEBUG, LOGFILE, SCREENy añadimos las líneas de configuración del appender SCREEN a la configuración?
log4perl.appender.SCREEN.Threshold=$log_levelen el fichero de configuración?
-d
activada
$ perl -wd ./scripts/ccp -d -s -f META.yml -g bno:beowulf,nereida,orionExplique el funcionamiento de la función
get_logger
y de las funciones is_trace
, is_debug
, etc.
DB<2> n main::(./scripts/ccp:83): my $logger = get_logger( 'default' ); DB<2> x $logger->is_trace 0 0 DB<3> x $logger->is_debug 0 1 DB<4> x $logger->is_info 0 1
logconfess
:
$logger->logconfess( "failed to execute: $!" );¿Que hace
logwarn
y logdie
?
appender
? ¿Cuando se dispara?
¿Que clases de Appenders pueden usarse con Log::Log4perl?
¿Que es una RDDtool?
Casiano Rodríguez León