NAME

Log::Handler::Examples - Examples.

CREATE LOGGER

Quite simple

use Log::Handler;

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

use Log::Handler;

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;
use Log::Handler;
# Import it with get_logger()
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 );

You can add output objects on this way as well:

use Log::Handler;
use Log::Handler::Output::File;

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

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

use Log::Handler;

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

use Log::Handler;

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

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',
        newline  => 1,
        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,
        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;
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',
    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

use Log::Handler;

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:

use Log::Handler;

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.

use Log::Handler;
use Data::Dumper;

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