Search code examples
perlmooselog4perl

How can I report the line number with Log4perl and Moose?


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.


Solution

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