CREATE LOGGER
Quite simple
use Log::Handler; my $log = Log::Handler->new(); $log->add( screen => \%options );
Create a application wide logger
my $log = Log::Handler->create_logger("myapp"); $log->add( screen => \%options );
Once created you can use the application logger in all modules of your project:
package MyApp; use Log::Handler; my $log = Log::Handler->create_logger("myapp"); $log->add( screen => \%options ); package MyApp::Admin; use Log::Handler; my $log = Log::Handler->get_logger("myapp"); $log->info("message");
ADD OUTPUTS
use Log::Handler; my $log = Log::Handler->new(); $log->add( dbi => \%options ); $log->add( email => \%options ); $log->add( file => \%options ); $log->add( forward => \%options ); $log->add( screen => \%options ); $log->add( socket => \%options );
This is the same like
$log->add( "Log::Handler::Output::DBI" => \%options ); $log->add( "Log::Handler::Output::Email" => \%options ); $log->add( "Log::Handler::Output::File" => \%options ); $log->add( "Log::Handler::Output::Forward" => \%options ); $log->add( "Log::Handler::Output::Screen" => \%options ); $log->add( "Log::Handler::Output::Socket" => \%options );
RELOAD THE LOGGER
Quite simple
use Log::Handler; my $log = Log::Handler->new(); $log->config(config => "logger.conf"); $log->reload(config => "logger.conf");
Reload on HUP
use Log::Handler; my $log = Log::Handler->new(); $log->config(config => "logger.conf"); $SIG{HUP} = sub { unless ($log->reload(config => "logger.conf")) { warn "unable to reload configuration"; warn $log->errstr; } };
Validate first
It's possible to make a configuration check before you reload:
$log->validate(config => "logger.conf") or warn $log->errstr;
LOG VIA DBI
use Log::Handler; my $log = Log::Handler->new(); $log->add( dbi => { database => "database", driver => "mysql", host => "127.0.0.1", port => 3306, user => "user", password => "password", table => "messages", columns => [ qw/level ctime cdate pid hostname caller progname mtime message/ ], values => [ qw/%level %time %date %pid %hostname %caller %progname %mtime %message/ ], maxlevel => "error", minlevel => "emergency" newline => 0, message_pattern => "%L %T %D %P %H %C %S %t %m", } ); $log->error("log an error");
Or with "dbname"
$log->add( dbi => { dbname => "database", driver => "Pg", host => "127.0.0.1", port => 5432, user => "user", password => "password", table => "messages", columns => [ qw/level ctime cdate pid hostname caller progname mtime message/ ], values => [ qw/%level %time %date %pid %hostname %caller %progname %mtime %message/ ], maxlevel => "error", minlevel => "emergency" newline => 0, message_pattern => "%L %T %D %P %H %C %S %t %m", } );
Or with "data_source"
$log->add( dbi => { data_source => "dbi:SQLite:dbname=database.sqlite", table => "messages", columns => [ qw/level ctime cdate pid hostname caller progname mtime message/ ], values => [ qw/%level %time %date %pid %hostname %caller %progname %mtime %message/ ], maxlevel => "error", minlevel => "emergency" newline => 0, message_pattern => "%L %T %D %P %H %C %S %t %m", } );
LOG VIA EMAIL
use Log::Handler; my $log = Log::Handler->new(); $log->add( email => { host => "mx.bar.example", hello => "EHLO my.domain.example", timeout => 30, from => "[email protected]", to => "[email protected]", subject => "your subject", buffer => 0, maxlevel => "emergency", minlevel => "emergency", message_pattern => '%L', } ); $log->emergency("log an emergency issue");
LOG VIA SENDMAIL
use Log::Handler; my $log = Log::Handler->new(); $log->add( sendmail => { from => "[email protected]", to => "[email protected]", subject => "your subject", maxlevel => "error", minlevel => "error", message_pattern => '%L', } ); $log->emergency("message");
LOG VIA FILE
use Log::Handler; my $log = Log::Handler->new(); $log->add( file => { filename => "file1.log", maxlevel => 7, minlevel => 0 } ); $log->error("log an error");
LOG VIA FORWARD
use Log::Handler; my $log = Log::Handler->new(); $log->add( forward => { forward_to => \&my_func, message_pattern => [ qw/%L %T %P %H %C %S %t/ ], message_layout => "%m", maxlevel => "info", } ); $log->info("log a information"); sub my_func { my $params = shift; print Dumper($params); }
LOG VIA SCREEN
use Log::Handler; my $log = Log::Handler->new(); $log->add( screen => { log_to => "STDERR", maxlevel => "info", } ); $log->info("log to the screen");
LOG VIA SOCKET
use Log::Handler; my $log = Log::Handler->new(); $log->add( socket => { peeraddr => "127.0.0.1", peerport => 44444, maxlevel => "info", die_on_errors => 0, } ); while ( 1 ) { $log->info("test") or warn "unable to send message: ", $log->errstr; sleep 1; }
SIMPLE SOCKET SERVER (TCP)
use strict; use warnings; use IO::Socket::INET; use Log::Handler::Output::File; my $sock = IO::Socket::INET->new( LocalAddr => "127.0.0.1", LocalPort => 44444, Listen => 2, ) or die $!; my $file = Log::Handler::Output::File->new( filename => "file.log", fileopen => 1, reopen => 1, ); while ( 1 ) { $file->log(message => "waiting for next connection\n"); while (my $request = $sock->accept) { my $ipaddr = sprintf("%-15s", $request->peerhost); while (my $message = <$request>) { $file->log(message => "$ipaddr - $message"); } } }
DIFFERENT OUTPUTS
use Log::Handler; my $log = Log::Handler->new(); $log->add( file => { filename => "common.log", maxlevel => 6, minlevel => 5, } ); $log->add( file => { filename => "error.log", maxlevel => 4, minlevel => 0, } ); $log->add( email => { host => "mx.bar.example", hello => "EHLO my.domain.example", timeout => 120, from => "[email protected]", to => "[email protected]", subject => "your subject", buffer => 0, maxlevel => 0, } ); # log to common.log $log->info("this is a info message"); # log to error.log $log->warning("this is a warning"); # log to error.log and to [email protected] $log->emergency("this is a emergency message");
FILTER MESSAGES
my $log = Log::Handler->new(); $log->add( screen => { maxlevel => 6, filter_message => { match1 => "foo", match2 => "bar", match3 => "baz", condition => "(match1 && match2) && !match3" } } ); $log->info("foo"); $log->info("foo bar"); $log->info("foo baz");
FILTER CALLER
This example shows you how it's possilbe to debug messages only from a special namespace.
my $log = Log::Handler->new(); $log->add( file => { filename => "file1.log", maxlevel => "warning", } ); $log->add( screen => { maxlevel => "debug", message_layout => "message from %p - %m", filter_caller => qr/^Foo::Bar\z/, } ); $log->warning("a warning here"); package Foo::Bar; $log->info("an info here"); 1;
ANOTHER FILTER
filter_message => "as string" filter_message => qr/as regexp/ filter_message => sub { shift->{message} =~ /as code ref/ } # or with conditions filter_message => { match1 => "as string", match2 => qr/as regexp/, condition => "match1 || match2", } filter_caller => "as string" filter_caller => qr/as regexp/
CONFIG
Examples:
my $log = Log::Handler->new( config => "logger.conf" ); # or $log->add( config => "logger.conf" ); # or $log->config( config => "logger.conf" );
Example with Config::General.
Script:
use Log::Handler; my $log = Log::Handler->new(); $log->config( config => "logger.conf" );
Config (logger.conf):
<file> alias = common filename = example.log maxlevel = info minlevel = warn </file> <file> alias = error filename = example-error.log maxlevel = warn minlevel = emergency </file> <file> alias = debug filename = example-debug.log maxlevel = debug minlevel = debug </file> <screen> log_to = STDERR dump = 1 maxlevel = debug minlevel = debug </screen>
CHECK FOR ACTIVE LEVELS
It can be very useful if you want to check if a level is active.
use Log::Handler; use Data::Dumper; my $log = Log::Handler->new(); $log->add( file => { filename => "file1.log", maxlevel => 4, } ); my %hash = (foo => 1, bar => 2);
Now you want to dump the hash, but not in any case.
if ( $log->is_debug ) { my $dump = Dumper(\%hash); $log->debug($dump); }
This would dump the hash only if the level debug is active.
AUTHOR
Jonny Schulz <jschulz.cpan(at)bloonix.de>.