Faire des modules d'auto-journalisation avec Log:: Log4perl

Est-il possible d'utiliser Log:: Log4perl pour faire un module intelligent d'auto-journalisation qui journalise ses opérations dans un fichier même en l'absence du script d'appel N'initialise pas Log4perl? Pour autant que je puisse le dire à partir de la documentation, la seule façon d'utiliser Log4perl est de l'initialiser dans le script d'exécution à partir d'une configuration, puis les modules implémentant Log4perl se logent eux-mêmes sur la base de la configuration Log4perl de l'appelant.

au lieu de cela, je voudrais que les modules fournissent un configuration d'initialisation par défaut pour Log4perl. Cela fournirait le fichier par défaut appender pour la catégorie du module. Ensuite, je pourrais modifier ce comportement en insérant Log4perl dans L'appelant avec une configuration différente si nécessaire, et tout fonctionnerait avec un peu de chance.

est-ce que ce genre de comportement de journalisation défensive est possible ou vais-je avoir besoin de compter sur L'initting Log4perl dans chaque .le script pl qui appelle le module que je veux enregistré?

8
demandé sur Ether 2010-06-11 01:07:14

2 réponses

je le fais dans un Journal personnalisé rôle dans orignal (non pertinent 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)
};

comme vous pouvez le voir, l'objet log s'auto-initialise -- si Log::Log4perl->init n'a pas été appelé, alors easy_init est appelée. Vous pouvez facilement modifier ceci pour permettre à chaque module de personnaliser son logger -- je le fais avec des paramètres de rôle optionnels, avec ref($this) comme repli par défaut.

PS. Vous pouvez également regarder MooseX:: Log:: Log4perl, qui est où j'ai commencé avant d'utiliser le rôle logger ci-dessus. Un jour, quand j'y arriverai, je soumettrai quelques correctifs indispensables à ce module MX pour y intégrer certaines fonctionnalités que j'ai ajoutées.

7
répondu Ether 2010-06-10 22:22:45

la réponse courte est D'appeler Log:: Log4perl:: initialized(); à un certain point et si elle est fausse, mettez en place une journalisation par défaut.

la partie délicate est " un point."

vous ne pouvez pas le faire dans BEGIN {}, car alors le script principal piétinera votre initialisation même si vous avez créé des fichiers inutiles. Vous ne voulez pas le faire avant chaque appel get_logger() parce que c'est du gaspillage. Vous devez donc le faire lors de l'initialisation du module, par exemple sous nouveau ou sous initialisation.

1
répondu Leolo 2010-11-05 18:08:30