有没有办法使用Log::Log4perl创建一个智能自我记录模块,即使没有调用脚本而不是初始化Log4perl,也会将其操作记录到文件中?据我从文档中可以看出,使用Log4perl的唯一方法是从配置中运行脚本初始化它,然后实现Log4perl调用的模块根据调用者的Log4perl配置自行记录。
相反,我希望这些模块为Log4perl提供默认的初始化配置。这将为模块的类别提供默认文件追加器。然后,我可以通过在调用者中使用不同的配置启动Log4perl来覆盖此行为,如果需要,所有内容都可以正常工作。
这种防御性日志记录行为是否可行,或者我是否需要依赖于在调用我想要记录的模块的每个.pl脚本中启动Log4perl?
答案 0 :(得分:7)
我在Moose中的自定义日志角色中执行此操作(删除了无关的复杂代码):
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)
};
如您所见,日志对象是自我初始化的 - 如果尚未调用Log::Log4perl->init
,则调用easy_init
。您可以轻松修改此设置以允许每个模块自定义其记录器 - 我使用可选的角色参数,并使用ref($this)
作为默认回退。
PS。您可能还想查看MooseX::Log::Log4perl,这是我在使用上面的记录器角色之前开始的地方。有一天,当我开始讨论它时,我会向MX模块提交一些急需的补丁,以包含我添加的一些功能。
答案 1 :(得分:1)
简短的回答是调用Log :: Log4perl :: initialized();在某些时候,如果它是假的,请设置一些默认的日志记录。
棘手的部分是“某点”。
你不能在BEGIN {}中做到这一点,因为即使你创建了不合法的文件,主脚本也会踩踏你的初始化。您不希望在每次调用get_logger()之前执行此操作,因为这样做很浪费。所以你应该在模块初始化期间这样做,比如sub new或sub init。