Как я могу улавливать предупреждения Perl в журналах Log4perl?

Log4perl - отличный инструмент для ведения журнала.

warnings прагма также является важным инструментом.

Однако, когда скрипты Perl работают как демоны, предупреждения Perl печатаются в STDERR, где их никто не видит, а не в файле журнала Log4perl соответствующей программы.

Есть ли способ уловить предупреждения Perl в журнале Log4perl?

Например, этот код будет достаточно хорошо записываться в файл журнала, но в случае его запуска в качестве демона предупреждения Perl не будут включены в журнал:

#!/usr/bin/env perl
use strict;
use warnings;

use Log::Log4perl qw(get_logger);

# Define configuration
my $conf = q(
                log4perl.logger                    = DEBUG, FileApp
                log4perl.appender.FileApp          = Log::Log4perl::Appender::File
                log4perl.appender.FileApp.filename = test.log
                log4perl.appender.FileApp.layout   = PatternLayout
);

# Initialize logging behaviour
Log::Log4perl->init( \$conf );

# Obtain a logger instance
my $logger = get_logger("Foo::Bar");
$logger->error("Oh my, an error!");

$SIG{__WARN__} = sub {
    #local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1;
    $logger->warn("WARN @_");
};

my $foo = 100;
my $foo = 44;

Это все еще печатает на STDERR:

"my" variable $foo masks earlier declaration in same scope at log.pl line 27.

И файл журнала не распознает это предупреждение.

Ответы

Ответ 1

Это в Log4perl FAQ как Некоторые модули печатают сообщения в STDERR. Как я могу их перехватить в Log:: Log4perl? и Моя программа уже использует warn() и die(). Как переключиться на Log4perl?.

В вашей конкретной проблеме есть добавленная морщина, которую вы видите во время компиляции, поэтому вам необходимо настроить часто задаваемые вопросы, чтобы настроить регистрацию во время компиляции как можно раньше. Сделайте это в блоке BEGIN как можно ближе к верхней части источника:

 BEGIN {
     ... all of your logging setup
     }

Вы можете узнать, было ли это предупреждение о компиляции, выполнив проверку синтаксиса с включенными предупреждениями:

 % perl -cw program

Если вы видите предупреждение во время проверки синтаксиса, это предупреждение о компиляции.

Я бы предпочел поймать предупреждения во время компиляции в разработке. Они не должны проходить через производственную систему.:)

Ответ 2

Для этого можно установить обработчик WARN. Он упоминается в Log4perl FAQ.

Моя программа уже использует warn() и die(). Как я могу переключиться на Log4perl?

Если ваша программа уже использует функцию perl warn() для извлечения сообщений об ошибках и вы хотите перенаправить их в мир Log4perl, просто определите обработчик WARN, где находится ваша программа или модуль:

use Log::Log4perl qw(:easy);
$SIG{__WARN__} = sub {
    local $Log::Log4perl::caller_depth =
        $Log::Log4perl::caller_depth + 1;
    WARN @_;
};

Это позволит зафиксировать любое явное использование WARN в вашей программе, а также предупреждения Perlish об использовании неинициализированных значений и т.д.