使用 Log::Log4perl 制作自记录模块

发布于 2024-09-05 08:34:53 字数 424 浏览 3 评论 0原文

有没有办法使用 Log::Log4perl 制作智能自记录模块即使在没有初始化 Log4perl 的调用脚本的情况下,它也会将其操作记录到文件中?据我从文档中可以看出,使用 Log4perl 的唯一方法是在运行脚本中从配置初始化它,然后实现 Log4perl 调用的模块根据调用者的 Log4perl 配置记录自己。

相反,我希望模块为 Log4perl 提供默认的初始化配置。这将为模块的类别提供默认的文件附加器。然后,如果需要,我可以通过使用不同的配置在调用者中初始化 Log4perl 来覆盖此行为,并且一切都会正常工作。

这种防御性日志记录行为是否可能,或者我是否需要在每个调用我想要记录的模块的 .pl 脚本中依赖初始化 Log4perl?

Is there a way to use Log::Log4perl to make a smart self-logging module that logs its operations to a file even in the absence of the calling script not initializing Log4perl? As far as I can tell from the documentation, the only way to use Log4perl is to initialize it in the running script from a configuration, then modules implementing Log4perl calls log themselves based on the caller's Log4perl config.

Instead, I'd like the modules to provide a default initialization config for Log4perl. This would provide the default file appender for the module's category. Then, I could override this behavior by initing Log4perl in the caller with a different config if needed, and everything would hopefully just work.

Is this sort of defensive logging behavior possible or am I going to need to rely on initing Log4perl in every .pl script that calls the module I want logged?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绻影浮沉 2024-09-12 08:34:54

我在 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) 作为默认后备。

附言。您可能还想查看 MooseX::Log::Log4perl,这是我在使用上面的记录器角色之前开始的地方。有一天,当我有时间时,我会向该 MX 模块提交一些急需的补丁,以合并我添加的一些功能。

I do this in a custom Log role in Moose (irrelevant complicated code removed):

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

As you can see, the log object is self-initializing -- if Log::Log4perl->init has not been called, then easy_init is called. You could easily modify this to allow each module to customize its logger -- I do so with optional role parameters, with ref($this) as the default fallback.

PS. You may also want to look at MooseX::Log::Log4perl, which is where I started before I used the logger role above. Someday when I get around to it I will submit some much-needed patches to that MX module to incorporate some features I have added.

别挽留 2024-09-12 08:34:54

简短的答案是调用 Log::Log4perl::initialized();在某些时候,如果它是 false,则设置一些默认日志记录。

棘手的部分是“某个点”。

您不能在 BEGIN {} 中执行此操作,因为即使您创建了不必要的文件,主脚本也会阻止您的初始化。您不想在每次调用 get_logger() 之前执行此操作,因为这是浪费的。因此,您应该在模块初始化期间执行此操作,例如 sub new 或 sub init。

The short answer is to call Log::Log4perl::initialized(); at some point and if it is false, set up some default logging.

The tricky part is "some point."

You can't do it in BEGIN {}, because then the main script's will stomp your initialisation even though you created unnessary files. You don't want to do it before each call to get_logger() because that is wasteful. So you should do it during the module's initialisation, say sub new or sub init.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文