Call for Participation - Perl Community Conference, Summer 2025: Hybrid / Austin, Texas July 3-4, 2025 Learn more

NAME

Log::Handler::Examples - Examples.

CREATE LOGGER

Quite simple

my $log = Log::Handler->new();
$log->add( screen => \%options );

Create a application logger and accessor LOG

use Log::Handler myapp => 'LOG';
LOG->add( screen => \%options );

Create a application logger without accessor

use Log::Handler 'myapp';
my $log = Log::Handler->get_logger('myapp');
$log->add( screen => \%options );

Create application logger with create_logger()

my $log = Log::Handler->create_logger('myapp');
$log->add( screen => \%options );

Another self-explanatory examples

use Log::Handler l1 => 'LOG1', l2 => 'LOG2', l3 => 'LOG3';
@logger = Log::Handler->create_logger(qw/l1 l2 l3/);
@logger = Log::Handler->get_logger(qw/l1 l2 l3/);

Once created you can import a application logger into all modules of your project:

package MyApp;
use Log::Handler myapp => 'LOG';
LOG->add( screen => \%options );
package MyApp::Foo;
# Import it with an accessor
use Log::Handler myapp => 'LOG';
LOG->info('message');
package MyApp::Bar;
# Import it with get_logger()
my $log = Log::Handler->get_logger('myapp');
$log->info('message');

ADD OUTPUTS

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 );

You can add output objects on this way as well:

my %file_options = (
filename => 'file1.log',
mode => 'append'
);
my %handler_options = (
maxlevel => 'info',
newline => 1
);
my $log = Log::Handler->new();
my $file = Log::Handler::Output::File->new( \%file_options );
$log->add( $file => \%handler_options );

LOG VIA DBI

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'
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'
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'
message_pattern => '%L %T %D %P %H %C %S %t %m',
}
);

LOG VIA EMAIL

my $log = Log::Handler->new();
$log->add(
email => {
host => 'mx.bar.example',
hello => 'EHLO my.domain.example',
timeout => 30,
from => 'bar@foo.example',
to => 'foo@bar.example',
subject => 'your subject',
buffer => 0,
maxlevel => 'emergency',
minlevel => 'emergency',
}
);
$log->emergency('log an emergency issue');

LOG VIA FILE

my $log = Log::Handler->new();
$log->add(
file => {
filename => 'file1.log',
mode => 'append',
newline => 1,
maxlevel => 7,
minlevel => 0
}
);
$log->error('log an error');

LOG VIA FORWARD

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

my $log = Log::Handler->new();
$log->add(
screen => {
log_to => 'STDERR',
newline => 1,
maxlevel => 'info',
}
);
$log->info('log to the screen');

LOG VIA SOCKET

my $log = Log::Handler->new();
$log->add(
socket => {
peeraddr => '127.0.0.1',
peerport => 44444,
newline => 1,
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;
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',
mode => 'append',
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

my $log = Log::Handler->new();
$log->add(
file => {
filename => 'common.log',
mode => 'append',
maxlevel => 6,
minlevel => 5,
}
);
$log->add(
file => {
filename => 'error.log',
mode => 'append',
maxlevel => 4,
minlevel => 0,
}
);
$log->add(
email => {
host => 'mx.bar.example',
hello => 'EHLO my.domain.example',
timeout => 120,
from => 'bar@foo.example',
to => 'foo@bar.example',
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 foo@bar.example
$log->emergency("this is a emergency message");

FILTER MESSAGES

my $log = Log::Handler->new();
$log->add(
screen => {
newline => 1,
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',
mode => 'append',
newline => 1,
maxlevel => 'warning',
}
);
$log->add(
screen => {
maxlevel => 'debug',
newline => 1,
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 with Config::General.

<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>

Or

<file>
<default>
newline = 1
permissions = 0640
timeformat = %b %d %H:%M:%S
fileopen = 1
reopen = 1
mode = append
debug_mode = 2
message_layout = %T %H[%P] [%L] %S: %m
</default>
<common>
filename = example.log
maxlevel = info
minlevel = warn
</common>
<error>
filename = example-error.log
maxlevel = warn
minlevel = emergency
</error>
<debug>
filename = example-debug.log
maxlevel = debug
minlevel = debug
</debug>
</file>
<screen>
<foo>
log_to = STDERR
dump = 1
maxlevel = debug
minlevel = debug
</foo>
</screen>

Script:

my $log = Log::Handler->new();
$log->config(config => 'file.conf');

CHECK FOR ACTIVE LEVELS

It can be very useful if you want to check if a level is active.

my $log = Log::Handler->new();
$log->add(
file => {
filename => 'file1.log',
mode => 'append',
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>.