3

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);
4

1 回答 1

3

一种方法是将自定义“cspecs”添加到您的PatternLayout. 使用 API

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

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

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

匿名子接收

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

layout:调用它的 PatternLayout 对象
message:日志消息 (%m)
类别:例如 groceries.beverages.adult.beer.schlitz
优先级:例如 DEBUG|WARN|INFO|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(...)记录器将 in 中的列表连接成一个字符串,然后传递给 appender,我们可以通过明显的接口决定调用者中的标题

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

上面的第一个字符串是我们cspec寻找的任何正则表达式。

这会根据每个日志行的内容对其进行格式化。一个更全面的选择是编写自己的 appender (FAQ),这是一个相当简单的类,您可以在其中根据需要保留和操作行。例如,请参阅捆绑消息 (FAQ)的示例。

最后,微调消息选择方式的正确方法是添加category。然后您可以拉出一个新的记录器并将其配置为显示INFO:(用于标题行),而该组中的其余消息由另一个记录器发送,配置为不显示它。有关简单示例,请参见这篇文章

不利的一面是,现在有更多与记录器、附加程序和布局有关的内容,在这种情况下,所有这些都只需要稍作调整。

如果这些不符合要求,请说明您如何决定对哪些打印进行分组。

于 2017-09-19T20:37:40.193 回答