2010-06-10 15 views
8

¿Existe alguna forma de utilizar Log::Log4perl para crear un módulo inteligente de auto registro que registre sus operaciones en un archivo incluso si el script de llamada no está inicializando Log4perl? Por lo que puedo decir de la documentación, la única forma de usar Log4perl es inicializarlo en el script en ejecución desde una configuración, luego los módulos que implementan las llamadas a Log4perl se registran a sí mismos basándose en la configuración de Log4perl del llamador.Creación de módulos de auto registro con Log :: Log4perl

En su lugar, me gustaría que los módulos proporcionen una configuración de inicialización predeterminada para Log4perl. Esto proporcionaría el apéndice de archivo predeterminado para la categoría del módulo. Entonces, podría anular este comportamiento ingresando Log4perl en la persona que llama con una configuración diferente si es necesario, y todo funcionaría con suerte.

¿Este tipo de comportamiento de registro defensivo es posible o voy a tener que confiar en inciar Log4perl en cada script .pl que llame al módulo que quiero registrar?

Respuesta

7

hago esto en una función personalizada Acceder Moose (complicado código irrelevante eliminado):

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

Como se puede ver, el objeto de registro se auto-inicialización - si Log::Log4perl->init no ha sido llamado, a continuación, easy_init se llama. Podría modificar esto fácilmente para permitir que cada módulo personalice su registrador; lo hago con parámetros de función opcionales, con ref($this) como alternativa predeterminada.

PS. También puede consultar MooseX::Log::Log4perl, que es donde comencé antes de usar el rol de registrador anterior. Algún día, cuando lo encuentre, enviaré algunos parches muy necesarios a ese módulo MX para incorporar algunas características que he agregado.

+1

Afortunadamente, esto registrará objetos Moose, por lo que parece que será lo suficientemente simple como para ponerse en marcha. ¡Gracias! – Oesor

+0

@Oesor: hooray, Moose FTW! :) – Ether

+0

¿Puedo preguntar qué es un módulo MX? Sé PP y XS, ¿MX es una forma abreviada de Moose? – DVK

1

La respuesta corta es llamar a Log :: Log4perl :: initialized(); en algún momento, y si es falso, configure algunos registros predeterminados.

La parte difícil es "algún punto".

No puede hacerlo en BEGIN {}, porque entonces las secuencias de comandos principales pisarán su inicialización a pesar de que haya creado archivos poco éticos. No desea hacerlo antes de cada llamada a get_logger() porque es un desperdicio. Por lo tanto, debe hacerlo durante la inicialización del módulo, por ejemplo, sub new o sub init.

Cuestiones relacionadas