Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以使用log::Log4perl注册一个函数来预处理日志消息?_Perl_Logging_Log4perl - Fatal编程技术网

是否可以使用log::Log4perl注册一个函数来预处理日志消息?

是否可以使用log::Log4perl注册一个函数来预处理日志消息?,perl,logging,log4perl,Perl,Logging,Log4perl,在: 我可以很好地打印我的引用,而不是数组(0xFFDFKDJ)。但是每次输入这么长的代码太无聊了。我只想: $logger->preprocessor({ filter => \&Data::Dumper::Dumper, value => $ref }); $logger->debug( $ref, $ref2 ); $logger->info( $array ); 和$ref,$ref2和$array将由Data::Dumper转

在:

我可以很好地打印我的引用,而不是
数组(0xFFDFKDJ)
。但是每次输入这么长的代码太无聊了。我只想:

$logger->preprocessor({
    filter => \&Data::Dumper::Dumper,
    value  => $ref
});

$logger->debug( $ref, $ref2 );
$logger->info( $array );
$ref
$ref2
$array
将由Data::Dumper转储

有没有办法做到这一点

UPD
在你的回答的帮助下,我做了

现在你只要:

log4perl.appender.A1.layout=FallbackLayout
log4perl.appender.A1.layout.chain=PatternLayout
log4perl.appender.A1.layout.chain.ConversionPattern=%m%n
log4perl.appender.A1.warp_message = sub { $#_ = 2 if @_ > 3; \
                                       return @_; }
# OR
log4perl.appender.A1.warp_message = main::warp_my_message

sub warp_my_message {
    my( @chunks ) =  @_;

    use Data::Dump qw/ pp /;
    for my $msg ( @chunks ) {
        $msg =  pp $msg   if ref $msg;
    }

    return @chunks;
}
UPD2

或者你可以使用这个小模块

log4perl.appender.SomeAPP.warp_message  = Preprocess::Messages::msg_filter
log4perl.appender.SomeAPP.layout        = Preprocess::Messages

package Preprocess::Messages;

sub msg_filter {
    my @chunks =  @_;

    for my $msg ( @chunks ) {
        $msg =  pp $msg   if ref $msg;
    }

    return @chunks;
};

sub render {
    my $self =  shift;

    my $layout =  Log::Log4perl::Layout::PatternLayout->new(
        '%d %P %p> %c %F:%L %M%n  %m{indent=2}%n%n'
    );

    $_[-1] += 1; # increase level of the caller
    return $layout->render( join $Log::Log4perl::JOIN_MSG_ARRAY_CHAR, @{ shift() }, @_ );
}


sub new {
    my $class = shift;
    $class = ref ($class) || $class;

    return bless {}, $class;
}

1;
是的,当然可以设置“warp\u message=0”并将msg\u过滤器和渲染组合在一起

log4perl.appender.SomeAPP.warp_message  = 0
log4perl.appender.SomeAPP.layout        = Preprocess::Messages

sub render {
    my($self, $message, $category, $priority, $caller_level) = @_;

    my $layout =  Log::Log4perl::Layout::PatternLayout->new(
        '%d %P %p> %c %F:%L %M%n  %m{indent=2}%n%n'
    );

    for my $item ( @{ $message } ) {
        $item =  pp $item   if ref $item;
    }

    $message =  join $Log::Log4perl::JOIN_MSG_ARRAY_CHAR, @$message;
    return $layout->render( $message, $category, $priority, $caller_level+1 );
}
简单的方法:使用
warp\u消息
最简单的方法是创建一个自定义appender,这样您就可以获得传递给记录器的原始引用:

package DumpAppender;
use strict;
use warnings;

use Data::Dumper;

$Data::Dumper::Indent = 0;
$Data::Dumper::Terse  = 1;

sub new {
    bless {}, $_[0];
}

sub log {
    my($self, %params) = @_;
    print ref($_) ? Dumper($_) : $_ for @{ $params{message} };
    print "\n";
}

package main;   
use strict;
use warnings;

use Log::Log4perl;

Log::Log4perl->init(\q{
    log4perl.rootLogger=DEBUG,Dump
    log4perl.appender.Dump=DumpAppender
    log4perl.appender.Dump.layout=NoopLayout
    log4perl.appender.Dump.warp_message=0
});

my $logger = Log::Log4perl->get_logger;

$logger->debug(
    'This is a string, but this is a reference: ',
    { foo => 'bar' },
);
输出:
这是一个字符串,但这是一个引用:{'foo'=>'bar'}
不幸的是,如果您采用这种方法,您将无法编写自己的代码来处理布局、打开文件等。除了只需要打印到屏幕上的非常简单的项目外,我不会采用这种方法

更好的方法:复合追加器 更好的方法是自己写。复合appender在以某种方式对消息进行操作(例如过滤或缓存)后,将消息转发到另一个appender。使用这种方法,您只能编写用于转储引用的代码,并让现有的appender来完成繁重的工作

下面显示如何编写复合追加器。其中一些在的文档中有解释,但我从Mike Schilli的中复制了很多:

输出:
2015/09/14 13:38:47调试这是一个字符串,但这是一个引用:{'foo'=>'bar'}

请注意,如果通过API而不是文件初始化Log::Log4perl,则必须执行一些额外的步骤。这在Log::Log4perl::Appender文档的一节中有记录。

如果我没记错的话,我想您可以定制一个Appender并调用它。找不到我的旧代码,但文档中有一个缩进示例,我认为您可以创建一个日志子,如果ref()eq'ARRAY'。。。
package DumpAppender;
use strict;
use warnings;

use Data::Dumper;

$Data::Dumper::Indent = 0;
$Data::Dumper::Terse  = 1;

sub new {
    bless {}, $_[0];
}

sub log {
    my($self, %params) = @_;
    print ref($_) ? Dumper($_) : $_ for @{ $params{message} };
    print "\n";
}

package main;   
use strict;
use warnings;

use Log::Log4perl;

Log::Log4perl->init(\q{
    log4perl.rootLogger=DEBUG,Dump
    log4perl.appender.Dump=DumpAppender
    log4perl.appender.Dump.layout=NoopLayout
    log4perl.appender.Dump.warp_message=0
});

my $logger = Log::Log4perl->get_logger;

$logger->debug(
    'This is a string, but this is a reference: ',
    { foo => 'bar' },
);
package DumpAppender;   
use strict;
use warnings;

our @ISA = qw(Log::Log4perl::Appender);

use Data::Dumper;

$Data::Dumper::Indent = 0;
$Data::Dumper::Terse  = 1;

sub new {
    my ($class, %options) = @_;

    my $self = {
        appender => undef,
        %options
    };

    # Pass back the appender to be limited as a dependency to the configuration
    # file parser.
    push @{ $options{l4p_depends_on} }, $self->{appender};

    # Run our post_init method in the configurator after all appenders have been
    # defined to make sure the appenders we're connecting to really exist.
    push @{ $options{l4p_post_config_subs} }, sub { $self->post_init() };

    bless $self, $class;
}

sub log {
    my ($self, %params) = @_;

    # Adjust call stack so messages are reported with the correct caller and
    # file
    local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 2;

    # Dump all references with Data::Dumper
    $_ = ref($_) ? Dumper($_) : $_ for @{ $params{message} };

    $self->{app}->SUPER::log(
        \%params,
        $params{log4p_category},
        $params{log4p_level}
    );
}

sub post_init {
    my ($self) = @_;

    if(! exists $self->{appender}) {
        die "No appender defined for " . __PACKAGE__;
    }

    my $appenders = Log::Log4perl->appenders();
    my $appender = Log::Log4perl->appenders()->{$self->{appender}};

    if(! defined $appender) {
        die "Appender $self->{appender} not defined (yet) when " .
            __PACKAGE__ . " needed it";
    }

    $self->{app} = $appender;
}

package main;

use strict;
use warnings;

use Log::Log4perl;

Log::Log4perl->init(\q{
    log4perl.rootLogger=DEBUG, Dump

    log4perl.appender.Dump=DumpAppender
    log4perl.appender.Dump.appender=SCREEN

    log4perl.appender.SCREEN=Log::Log4perl::Appender::Screen
    log4perl.appender.SCREEN.layout=PatternLayout
    log4perl.appender.SCREEN.layout.ConversionPattern=%d %p %m%n
});

my $logger = Log::Log4perl->get_logger;

$logger->debug(
    'This is a string, but this is a reference: ',
    { foo => 'bar' },
);