views:

159

answers:

2

Is it possible to get Log4perl to correctly display the line number and package/class of the log event instead of always Method::Delegation at line 99 when used with Moose?

In my case, I have created an attribute isa Log::Log4perl::Logger and delegated the various logging levels to my class (log, warn, error, ...). Doing this also shows the Delegation.pm as the file.

Thanks!

+2  A: 

You don't provide nearly enough information to diagnose your issue (e.g. what is Method::Delegation and how is it connected to Log4perl), but my spidey senses tell me you probably have a wrapper method from which you call the Log4perl methods. You should increase the value of $Log::Log4perl::caller_depth from within this wrapper (and decrement it after calling into Log4perl) so the proper location is determined.

e.g. in Moose, I use:

package MyApp::Role::Log;

use MooseX::Role::Strict;
use Log::Log4perl;

my @methods = qw(
    log trace debug info warn error fatal
    is_trace is_debug is_info is_warn is_error is_fatal
    logexit logwarn error_warn logdie error_die
    logcarp logcluck logcroak logconfess
);

has '_logger' => (
    is => 'ro',
    isa => 'Log::Log4perl::Logger',
    lazy_build => 1,
    handles => \@methods,
);

around $_ => sub {
    my $orig = shift;
    my $this = shift;

    # one level for this method itself
    # two levels for Class::MOP::Method::Wrapped (the "around" wrapper)
    # one level for Moose::Meta::Method::Delegation (the "handles" wrapper)
    local $Log::Log4perl::caller_depth += 4;

    my $return = $this->$orig(@_);

    $Log::Log4perl::caller_depth -= 4;
    return $return;

} foreach @methods;


sub _build__logger
{
    my $this = shift;

    Log::Log4perl->easy_init() if not Log::Log4perl::initialized();
    return Log::Log4perl->get_logger(ref $this)
}

no MooseX::Role::Strict;
1;

Note that the CPAN module MooseX::Log::Log4perl does not increment caller_depth, which it definitely should.

Ether
Doh! Sorry, you are right. Forgot to mention my class is written with Moose.
A ha, well then my example should be spot on then :)
Ether
A: 

Yes. According to Log::Log4perl::Layout::PatternLayout what you want is a combination of %F and %L. %L is the "Line number within the file where the log statement was issued" and %F is the "File where the logging event occurred".

Or, the easiest way would be to use %l which is the:

Fully qualified name of the calling method followed by the callers source the file name and line number between parentheses.

Weegee