在子例程中使用Log4Perl?

时间:2014-07-30 12:41:44

标签: perl logging log4perl

如果我在内部使用Log4Perl创建一个抽象函数,那么它将输出$logger->error_die($m)行所在的行号,而不是fatalError()函数的位置。

sub fatalError {
    my $m = shift;
    email($m, $c->{subject});
    unlink $c->{lock};
    $logger->error_die($m);
}

fatalError("Directory $d ...");

在Bash中,我通过在每条错误消息的末尾写[###]来解决问题,并在病房之后解析Bash脚本以用唯一数字替换[###]。这样我就知道错误输出的确切位置。但是,让第二个脚本修改源代码并不是最佳选择。

问题

有没有办法让Log4Perl来编写调用fatalError()函数的行号,或者如何解决问题?

4 个答案:

答案 0 :(得分:3)

您可以使用caller获取子程序上方级别的详细信息。

但是,您也可以使用代码refs调用Log4perl方法。您可以执行所需的额外处理并返回您喜欢的消息:

$logger->error_die( sub { ... do some stuff ...; $log_message } );

对于电子邮件位,我想我会添加另一个appender来处理它。

答案 1 :(得分:2)

简单的方法是将此行添加到fatalError方法中:

local $Log::Log4perl::caller_depth++;

这将使Log4perl"跳过"来自调用者上下文的当前子例程。

或者,如果您有许多这样的包装器方法,请将它们封装在一个包中,并使用Log4perl注册它们,如下所示:

Log::Log4perl->wrapper_register('My::Logger');

Log::Log4perl documentation

中介绍了此主题

答案 2 :(得分:1)

令我感到震惊的是,如果您使用类Log::Dispatch::Email之类的其他appender或朋友,并将其绑定到ERROR或FATAL级别,并在unlink的子例程中执行$SIG{__DIE__} { {1}}或DESTROY类的$c方法,则您的子fatalError将变得不必要,从而解决您的问题。

答案 3 :(得分:1)

从偷看Log4Perl的源代码中我可以看出,看起来它尊重warn / die惯例,只是将位置信息附加到不会发送消息的消息上以换行结束。这意味着您可以通过您的函数添加位置并停止Log4Perl附加它:

sub fatalError {
    my $m = shift;
    my (undef, $file, $line) = caller;
    my $at = " at $file line $line.\n";
    email($m, $c->{subject});
    unlink $c->{lock};
    $logger->error_die($m . $at);
}