NAME

Log::ger::Manual::FAQ - FAQ on Log::ger

VERSION

version 0.023.000

GENERAL

Why am I not seeing the logs?

By default log messages don't go anywhere (stealth/null logging). Only after you set up an output, the messages will go somewhere:

use Log::ger::Output 'Screen';
use Log::ger;

log_warn("hey!");

One mistake might be that you write this instead:

use Log::ger::Output::Screen;

This does nothing; you need to do:

use Log::ger::Output 'Screen';

or:

use Log::ger::Output;
Log::ger::Output->set('Screen');

Another reason why your logs are not showing might be that you use levels info, debug, or trace. By default, log level is set to warn. You need to increase log level first to show messages logged at higher level.

Why am I getting error "Undefined subroutine &main::log_warn called at ..."?

You need to import Log::ger using:

use Log::ger;

and not:

require Log::ger;
use Log::ger ();

because Log::ger sets up the logger routines to the calling package via import().

This will not work either:

require Log::ger;
Log::ger::log_warn("blah");

because the logger routines (log_warn et al) are not defined statically in the Log::ger package but constructed dynamically for each calling package.

How to use OO style?

The default in Log::ger is to use procedural style:

use Log::ger;

log_warn("blah");
if (log_is_debug()) {
    log_debug("Format: %s %s", "blah ...", {data=>'structure'});
}

However, you can also use objects:

use Log::ger (); # don't initialize and export logger subroutines
my $log = Log::ger->get_logger;
$log->warn("blah");
if ($log->is_debug) {
    $log->debug("Format: %s %s", "blah ...", {data=>'structure'});
}

How to create multiple loggers?

For example, in Log::Any:

my $log = Log::Any->get_logger;
my $log_dump = Log::Any->get_logger(category => "dump"); # to dump contents

$log->debugf("Headers is: %s", $http_res->{headers});
$log_dump->debug($http_res->{content});

in Log::ger:

# instead of installing to package, we setup objects (or hashes) for the
# secondary loggers
my $log_dump = Log::ger->get_logger(category => "dump");

log_debug("Headers is: %s", $http_res->{headers});
$log_dump->debug($http_res->{content});

How to log Perl warning/die message?

use Log::ger;
$SIG{__WARN__} = sub {
    log_warn(join "", @_);
    warn @_;
};
$SIG{__DIE__} = sub {
    log_fatal(join "", @_);
    die @_;
};

warn "This is a warning"; # message will also be logged
die  "This is an error";  # message will also be logged before script dies

or you can use Log::ger::LogException that shorten the above incantation to just:

use Log::ger::LogException;

OUTPUT

How to switch output?

Just issue another Log::ger::Output->set() which will replace previous output plugin.

Log::ger::Output->set("Screen");
log_warn("foo!"); # goes to screen
Log::ger::Output->set("SimpleFile", path=>"app.log");
log_warn("bar!"); # goes to file

How to send logs to several outputs?

Use Log::ger::Output::Composite, which can multiplex log message to multiple outputs, including multiple outputs of the same type (e.g. two or more File's).

How to send trace/debug messages to screen, but warnings/errors to file?

Using Log::ger::Output::Composite's per-output level:

Log::ger::Output Composite => (
    Screen => {
        level => ['trace', 'debug'],
    },
    File => {
        conf => { path=>'/path/to/file.log' },
        level => ['warn', 'error'],
    },
);

How to send trace/debug messages to a file, but warnings/errors to another file?

Using Log::ger::Output::Composite's per-output level:

Log::ger::Output Composite => (
    File => [
        {
            conf => { path=>'file1.log' },
            level => ['trace', 'debug'],
        },
        {
            conf => { path=>'file2.log' },
            level => ['warn', 'error'],
        },
    ],
);

How to filter by category?

Using Log::ger::Output::Composite.

TODO example.

OUTPUT: FILE

How to have different applications log to the same file?

You need to use a file output module which supports locking, e.g. FileWriteRotate or File then enable locking so that on every log a lock is acquired first.

One nice thing about the FileWriteRotate output module is that File::Write::Rotate provides a buffer so when you temporarily fail writing (e.g. disk is momentarily full or lock momentarily cannot be acquired) log messages (up to a certain number of them) is kept at the memory buffer first.

LEVEL

How to use custom levels?

One way:

use Log::ger ();
BEGIN {
    our %Log::ger::Levels = (
        critical => 1,
        error    => 2,
        warning  => 3,
        info     => 4,
        extra    => 5,
    );
    our %Log::ger::Level_Aliases = (
        warn     => 3,
        verbose  => 4,
    );

Do this before initializing any package with use Log::ger. The above example will create these logging routines: log_critical, log_error, log_warning, log_info, log_extra. The aliases won't get the logging routines but Log::ger::Util::numeric_level will recognize them.

CATEGORY

How to log under a different category than the current package?

Normally, using the procedural interface you are logging under the category of your package:

package My::App;
use Log::ger;

log_warn("this will be logged under category 'My::App'");

If you want to log under a different category, you can use the OO interface:

package My::App;
use Log::ger;

my $log_foo = Log::ger->get_logger(category => "Foo");
$log_foo->warn("this will be logged under category 'Foo'");

How to direct log messages under a certain category to a separate output?

For example, you want category Foo to go to a separate file /tmp/foo.log while the rest go to /path/app.log, you can do something like this:

use Log::ger::Output Composite => (
    outputs => {
        File => [
            {
                conf => {path=>'/path/app.log'},
                category_level => { Foo => 'off' },
            },
            {
                conf => {path=>'/path/foo.log'},
                level => 'off',
                category_level => { Foo => 'trace' },
            },
        ],
    },
);

FORMAT & LAYOUT

How to do sprintf-style formatting?

By default, the Log::ger formatter already does sprintf-style formatting:

log_warn("Format %s %s", "blah ...", {data=>'structure'});

If there is only one argument, no formatting is done.

log_warn("blah ...");

Why doesn't Log::ger log multiple arguments?

Logging multiple arguments is not supported by the default formatter because by default Log::ger adopts sprintf style:

log_warn("blah ...", "more blah ...");

Either join the arguments first, use sprintf style, or use some of the other formatters that support this, e.g. Log::ger::Like::LogAny.

How to use deferred calculation of arguments?

Use a formatter like Log::ger::Format::Block, or Log::ger::Format::Flogger, or develop your own formatter to do what you want.

You can also do this:

if (log_is_trace()) {
    log_trace("Format %s", $foo->something_that_is_expensive_to_calculate);
}

How to dump data structures?

The default formatter already dumps data structures:

log_warn("Format %s %s", "blah ...", {data=>'structure'});

How to log raw data structure?

You can use a formatter like Log::ger::Format::None which will prevent your log message from being stringified. To output this to destination, combine this with a layout plugin like Log::ger::Layout::JSON or Log::ger::Layout::LTSV. Or perhaps write your own output module that accepts raw data structure instead of formatted string and send it somewhere.

How to do custom formatting?

For example, a la Log::Contextual:

log_warn { 'The number of stuffs is: ' . $obj->stuffs_count };

See Log::ger::Format::Block for an example.

How to add timestamps (and other stuffs)?

Use a layouter, e.g. Log::ger::Layout::Pattern.

How to use microsecond in timestamps?

TODO

How to redact sensitive information?

TODO

How to customize layout per output?

For example, you want to use [%r] %m on the screen, but the more complete [%d] [PID %P] %m in log file. Use Log::ger::Output::Composite, e.g.:

use Log::ger::Output Composite => (
    outputs => {
        Screen => {
            layout => [Pattern => {format => '[%r] %m'}],
        },
        File => {
            path => '/path/to/logfile',
            layout => [Pattern => {format => '[%d] [PID %P] %m'}],
        },
    },
);

TARGETS

How to customize format/layout, output, plugin on a per-target basis?

To use a plugin only for the current package:

package MyPackage;

use Log::ger::Plugin;
Log::ger::Plugin->set_for_current_package(
    'PluginName',
    conf1 => ..., ...);
use Log::ger;

Do the same thing for format (using Log::ger::Format), layout (using Log::ger::Layout), or output (using Log::ger::Output).

SEE ALSO

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2018, 2017 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.