Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

trying to extend Log::Log4perl

by mifflin (Curate)
on Sep 03, 2009 at 18:19 UTC ( #793264=perlquestion: print w/ replies, xml ) Need Help??
mifflin has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to extend Log::Log4perl so that I can trap all messages for a process and, at the end, format them all nicely in an email. The example I have below only deals with error messages to more simply demonstrate my issue.

I'm using perl 5.8.2 and Log::Log4perl 1.22

Here is my logger package:

package Mylogger; use warnings; use strict; use base qw(Log::Log4perl); my @error_msgs; sub init { Log::Log4perl::init(@_); return; } sub get_logger { $Log::Log4perl::caller_depth = 1; my $logger = Log::Log4perl::get_logger(@_); bless $logger, __PACKAGE__; return $logger; } sub error { my ($this, $msg) = @_; push(@error_msgs, "ERROR $msg"); $this->SUPER::error($msg); return; } sub get_logged_errors { return \@error_msgs; } 1;
Here is my test program:
use strict; use warnings; use FindBin; use Mylogger; my $conf = q( log4perl.rootLogger=DEBUG, Screen log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.stderr = 0 log4perl.appender.Screen.layout=PatternLayout log4perl.appender.Screen.layout.ConversionPattern=%d{ISO8601} %-5p + %C %m%n ); Mylogger::init(\$conf); my $log = Mylogger::get_logger(); $log->error('error 1'); $log->error('error 2');
Here is a run of my test program showing two errors: Can't locate object method "error" via package "Mylogger" at Mylogger. +pm line 25. Can't locate object method "DESTROY" via package "Mylogger" at /usr/op +t/perl5/lib/site_perl/5.8.2/Log/Log4perl/ line 60. END failed--call queue aborted.
The error on line 25 in MyLogger is the call the SUPER::error, which somehow cannot be found. Also there is some issue with the way I'm implementing this which causes Log4perl to not find a DESTROY method. What am I missing here?

Comment on trying to extend Log::Log4perl
Select or Download Code
Re: trying to extend Log::Log4perl
by ikegami (Pope) on Sep 03, 2009 at 18:47 UTC

    I'm not knowledged in the use of Log::Log4perl, but it seems to me that the way to go is to create a new appender.

    Going that route also provides lots of code on which you can base your own.

      There is Log::Dispatch::Email but my problem is that it does not appear to give me enough control of the email which needs to contain more that just what I am logging.
Re: trying to extend Log::Log4perl
by Anonymous Monk on Sep 03, 2009 at 23:56 UTC
Re: trying to extend Log::Log4perl
by Bloodnok (Vicar) on Nov 23, 2012 at 23:19 UTC
    Hi ,
    It's a bit late I know buuuut....I'm going to do this anyway:-)

    Having encountered a not unrelated problem myself, I did a little investigating and AFAICT, L4P appears to construct it's methods dynamically (using closures) and doesn't make them available to an inheriting bespoke logger wrapper package via the standard route e.g. @ISA/SUPER:: etc., so they are available only to the L4P instance itself.

    The only 'obvious' way I could think of at the time was to utilise MyWrapper::AUTOLOAD to dispatch non-overridden L4P method calls to the logger object via a get_logger(class) call and let L4P deal with unknown methods etc. e.g. in a manner something similar to ...

    package MyWrapper; use warnings; use strict; use autodie; # Not strictly necessary, but JIC I forget later use base qw/Log::Log4perl; our $AUTOLOAD; sub get_logger { my $self = shift; return Log::Log4perl->get_logger(@_); # or $self->SUPER::get_logge +r(@_) but that requires # sufficient knowledge of L4 +P to know/realise that # get_logger is a standard e +xportable function } sub trace_beg { my $self = shift; __PACKAGE__->debug("Starting with args: " . join ' ', @_); } sub AUTOLOAD { my $self = shift; (my $method = $AUTOLOAD) =~ s,.*::,,; my $class = caller; local $Log::Log4perl::Caller_depth = $Log::Log4perl::caller_depth ++ 1; goto $self->get_logger($class)->$method(@_); } 1;
    The usual caveat emptor applies, but that's close to the way I managed to do it - less an awful lot of extraneous code.

    Hope that helps ...

    A user level that continues to overstate my experience :-))

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://793264]
Approved by ikegami
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2014-08-02 08:35 GMT
Find Nodes?
    Voting Booth?

    Who would be the most fun to work for?

    Results (55 votes), past polls