log4perl:分组消息

时间:2017-09-17 10:06:18

标签: perl logging log4perl

我使用log4perl来记录perl脚本中的消息。如下mwe.pl,我会在test.log

中收到以下(所需)输出
INFO: some information
      more information

我目前的实施使用:

my $logmessage = "some information\n";
$logmessage .= "more information";
$logger->info($logmessage);

特别注意我已使用\n手动指定换行符,我想避免。

有没有办法可以实现我想要的输出(test.log),而无需支持我的记录输入?

mwe.pl

#!/usr/bin/env perl
use strict;
use warnings;
use Log::Log4perl qw(get_logger :levels);

my $logger = get_logger();
$logger->level($INFO);

my $layout = Log::Log4perl::Layout::PatternLayout->new("%p: %m{indent}%n");
my $appender = Log::Log4perl::Appender->new(
    "Log::Dispatch::File",
    filename => "test.log",
    mode     => "write",
);

$appender->layout($layout);
$logger->add_appender($appender);

my $logmessage = "some information\n";
$logmessage .= "more information";
$logger->info($logmessage);

exit(0);

1 个答案:

答案 0 :(得分:3)

一种方法是将custom "cspecs"添加到PatternLayout。使用API​​

Log::Log4perl::Layout::PatternLayout::add_global_cspec(
    'A', sub { ... }
);                    # can now use %A

这需要在调用new之前进行,然后可以使用%A说明符。

这可以在configuration中进行设置,如链接文档中所示。或者可以在add_global_cspec对象上调用$layout方法(但我无法弄清楚界面。)

匿名子接收

($layout, $message, $category, $priority, $caller_level)  
     

layout:调用它的PatternLayout对象
      消息:记录消息(%m)
      类别:例如groceries.beverages.adult.beer.schlitz
      优先权:例如DEBUG | WARN |信息| ERROR | FATAL
      caller_level:备份调用堆栈的级别数           去寻找来电者

可用于实现格式化打印件的标准。

这是一个简单的自定义示例 - 指定整个格式

use strict;
use warnings;
use Log::Log4perl qw(get_logger :levels);

my $logger = get_logger();
$logger->level($INFO);

Log::Log4perl::Layout::PatternLayout::add_global_cspec( 
    'A', sub { return ( 
        $_[1] !~ /^more/                 # /^more/ taken to indicate 
           ?  "$_[3]: "                  # the continuation criterion,
           :  ' ' x length $_[3] . '  '  # or start with 'INFO: '
    ) . $_[1]
});

my $layout = Log::Log4perl::Layout::PatternLayout->new("%A%n");

my $appender = Log::Log4perl::Appender->new(
    "Log::Dispatch::File",
    filename => "new_test.log",
    mode     => "write",
);

$logger->info('some info');
$logger->info('more info');

$logger->info('info');
$logger->info('more and more info');

打印

INFO: some info
      more info
INFO: info
      more and more info

这样的自定义说明符当然可以与提供的自定义说明符组合。

由于info(...)中的列表被记录器连接到一个传递给appender的字符串,我们可以通过明显的接口决定调用者的标题

$logger->info('*', "... message ...");  # * for heading (add INFO:)

上面的第一个字符串是cspec查找的正则表达式。

根据内容格式化每个日志行。更加圆润的选项是write your own appender (FAQ),这是一个相当简单的类,您可以根据需要保留和操作行。例如,请参阅bundling messages (FAQ)的示例。

最后,通过添加category来微调消息选择方式的正确方法。然后,您可以拉出一个新的记录器并将其配置为显示INFO:(对于标题行),而该组中的其余消息由另一个记录器进行,配置为不显示它。有关简单示例,请参阅this post

缺点是现在跟记录器,追加器和布局有很多关系,而且在这种情况下只需要进行一些小调整。

如果这些不合适,请说明您如何决定将哪些印刷品分组。