Making self-logging modules with Log::Log4perl

后端 未结 2 1119
小鲜肉
小鲜肉 2020-12-28 11:35

Is there a way to use Log::Log4perl to make a smart self-logging module that logs its operations to a file even in the absence of the calling script not initializing Log4per

相关标签:
2条回答
  • 2020-12-28 11:52

    The short answer is to call Log::Log4perl::initialized(); at some point and if it is false, set up some default logging.

    The tricky part is "some point."

    You can't do it in BEGIN {}, because then the main script's will stomp your initialisation even though you created unnessary files. You don't want to do it before each call to get_logger() because that is wasteful. So you should do it during the module's initialisation, say sub new or sub init.

    0 讨论(0)
  • 2020-12-28 12:08

    I do this in a custom Log role in Moose (irrelevant complicated code removed):

    package MyApp::Role::Log;
    
    use Moose::Role;
    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;
        $Log::Log4perl::caller_depth += 4;
    
        my $return = $this->$orig(@_);
    
        $Log::Log4perl::caller_depth -= 4;
        return $return;
    
    } foreach @methods;
    
    method _build__logger => sub {
        my $this = shift;
    
        my $loggerName = ref($this);
        Log::Log4perl->easy_init() if not Log::Log4perl::initialized();
        return Log::Log4perl->get_logger($loggerName)
    };
    

    As you can see, the log object is self-initializing -- if Log::Log4perl->init has not been called, then easy_init is called. You could easily modify this to allow each module to customize its logger -- I do so with optional role parameters, with ref($this) as the default fallback.

    PS. You may also want to look at MooseX::Log::Log4perl, which is where I started before I used the logger role above. Someday when I get around to it I will submit some much-needed patches to that MX module to incorporate some features I have added.

    0 讨论(0)
提交回复
热议问题