A_B A_B - 1 month ago 10
Perl Question

Log4perl Singleton usage

I'm new to Log4perl and am trying to figure out why I get two different loggers in the below setup. My understanding is that this should be a singleton and calling get_logger() would return the same instance of the object each time.

Test.pm

#!/usr/bin/perl

package Example::Test;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(test);

sub test
{
my $logger = Log::Log4perl->get_logger();
print $logger, "\n";
}


test.pl

#!/usr/bin/perl

use strict;
use warnings;
use Log::Log4perl;
use Example::Test;

# Logger configuration
Log::Log4perl->init('/etc/log4perl.conf');
my $logger = Log::Log4perl->get_logger();
print $logger, "\n";

my $engine = test();


Output

Log::Log4perl::Logger=HASH(0x12093d0)
Log::Log4perl::Logger=HASH(0x29b4950)

Answer

You didn't specify a logging category, so your code does the equivalent of

Log::Log4perl->get_logger(__PACKAGE__);

where __PACKAGE__ is Example::Test inside your module and main inside your script.

From the documentation:

Categories are also called "Loggers" in Log4perl, both refer to the same thing and these terms are used interchangeably. Log::Log4perl uses categories to determine if a log statement in a component should be executed or suppressed at the current logging level. Most of the time, these categories are just the classes the log statements are located in...

In general, you probably want a separate logger for each module so you can handle log messages from different parts of your codebase differently.


On the other hand, if Example::Test is supposed to be a wrapper for Log::Log4perl, register it:

package My::Wrapper;

use strict;
use warnings 'all';
use 5.010;

use Log::Log4perl;

Log::Log4perl->wrapper_register(__PACKAGE__);

sub foo {
    my $logger = Log::Log4perl->get_logger;

    say $logger;
    $logger->warn('foo');
}

1;

When you call My::Wrapper::foo() from package main, the logging category will be main::.