Bug 19933: Move instantiation of in deletemem.pl
[koha.git] / Koha / Logger.pm
index a3b58ab..ed85c99 100644 (file)
@@ -20,11 +20,15 @@ package Koha::Logger;
 
 =head1 NAME
 
-Koha::Log
+Koha::Logger
 
 =head1 SYNOPSIS
 
-  use Koha::Log;
+    use Koha::Logger;
+
+    my $logger = Koha::Logger->get;
+    $logger->warn( 'WARNING: Serious error encountered' );
+    $logger->debug( 'I thought that this code was not used' );
 
 =head1 FUNCTIONS
 
@@ -39,54 +43,148 @@ use C4::Context;
 
 BEGIN {
     Log::Log4perl->wrapper_register(__PACKAGE__);
+}
+
+=head2 get
+
+    Returns a logger object (based on log4perl).
+    Category and interface hash parameter are optional.
+    Normally, the category should follow the current package and the interface
+    should be set correctly via C4::Context.
+
+=cut
+
+sub get {
+    my ( $class, $params ) = @_;
+    my $interface = $params ? ( $params->{interface} || C4::Context->interface ) : C4::Context->interface;
+    my $category = $params ? ( $params->{category} || caller ) : caller;
+    my $l4pcat = $interface . '.' . $category;
+
+    my $init = _init();
+    my $self = {};
+    if ($init) {
+        $self->{logger} = Log::Log4perl->get_logger($l4pcat);
+        $self->{cat}    = $l4pcat;
+        $self->{logs}   = $init if ref $init;
+    }
+    bless $self, $class;
+    return $self;
+}
+
+=head1 INTERNALS
+
+=head2 AUTOLOAD
+
+    In order to prevent a crash when log4perl cannot write to Koha logfile,
+    we check first before calling log4perl.
+    If log4perl would add such a check, this would no longer be needed.
+
+=cut
+
+sub AUTOLOAD {
+    my ( $self, $line ) = @_;
+    my $method = $Koha::Logger::AUTOLOAD;
+    $method =~ s/^Koha::Logger:://;
+
+    if ( !exists $self->{logger} ) {
+
+        #do not use log4perl; no print to stderr
+    }
+    elsif ( !$self->_recheck_logfile ) {
+        warn "Log file not writable for log4perl";
+        warn "$method: $line" if $line;
+    }
+    elsif ( $self->{logger}->can($method) ) {    #use log4perl
+        $self->{logger}->$method($line);
+        return 1;
+    }
+    else {                                       # we should not really get here
+        warn "ERROR: Unsupported method $method";
+    }
+    return;
+}
+
+=head2 DESTROY
+
+    Dummy destroy to prevent call to AUTOLOAD
+
+=cut
+
+sub DESTROY { }
+
+=head2 _init, _check_conf and _recheck_logfile
 
+=cut
+
+sub _init {
+    my $rv;
     if ( exists $ENV{"LOG4PERL_CONF"} and $ENV{'LOG4PERL_CONF'} and -s $ENV{"LOG4PERL_CONF"} ) {
+
         # Check for web server level configuration first
+        # In this case we ASSUME that you correctly arranged logfile
+        # permissions. If not, log4perl will crash on you.
+        # We will not parse apache files here.
         Log::Log4perl->init_once( $ENV{"LOG4PERL_CONF"} );
     }
     elsif ( C4::Context->config("log4perl_conf") ) {
-        # If no web server level config exists, look in the koha conf file for one
-        Log::Log4perl->init_once( C4::Context->config("log4perl_conf") );
-    } else {
-        my $logdir = C4::Context->config("logdir");
-        my $conf = qq(
-            log4perl.logger.intranet = WARN, INTRANET
-            log4perl.appender.INTRANET=Log::Log4perl::Appender::File
-            log4perl.appender.INTRANET.filename=$logdir/intranet-error.log
-            log4perl.appender.INTRANET.mode=append
-            log4perl.appender.INTRANET.layout=PatternLayout
-            log4perl.appender.INTRANET.layout.ConversionPattern=[%d] [%p] %m %l %n
-
-            log4perl.logger.opac = WARN, OPAC
-            log4perl.appender.OPAC=Log::Log4perl::Appender::File
-            log4perl.appender.OPAC.filename=$logdir/opac-error.log
-            log4perl.appender.OPAC.mode=append
-            log4perl.appender.OPAC.layout=PatternLayout
-            log4perl.appender.OPAC.layout.ConversionPattern=[%d] [%p] %m %l %n
-        );
-        Log::Log4perl->init_once(\$conf);
+
+        # Now look in the koha conf file. We only check the permissions of
+        # the default logfiles. For the rest, we again ASSUME that
+        # you arranged file permissions.
+        my $conf = C4::Context->config("log4perl_conf");
+        if ( $rv = _check_conf($conf) ) {
+            Log::Log4perl->init_once($conf);
+            return $rv;
+        }
+        else {
+            return 0;
+        }
+    }
+    else {
+        # This means that you do not use log4perl currently.
+        # We will not be forcing it.
+        return 0;
     }
+    return 1;    # if we make it here, log4perl did not crash :)
 }
 
-=head2 get
-
-    Returns a log4perl object.
-    Category and interface parameter are optional.
-    Normally, the category should follow the current package and the interface
-    should be set correctly via C4::Context.
+sub _check_conf {    # check logfiles in log4perl config (at initialization)
+    my $file = shift;
+    return if !-r $file;
+    open my $fh, '<', $file;
+    my @lines = <$fh>;
+    close $fh;
+    my @logs;
+    foreach my $l (@lines) {
+        if ( $l =~ /(OPAC|INTRANET)\.filename\s*=\s*(.*)\s*$/i ) {
+
+            # we only check the two default logfiles, skipping additional ones
+            return if !-w $2;
+            push @logs, $1 . ':' . $2;
+        }
+    }
+    return if !@logs;    # we should find one
+    return \@logs;
+}
 
-=cut
+sub _recheck_logfile {    # recheck saved logfile when logging message
+    my $self = shift;
 
-sub get {
-    my ( $class, $category, $interface ) = @_;
-    $interface ||= C4::Context->interface();
-    $category = caller if !$category;
-    return Log::Log4perl->get_logger( $interface. '.'. $category );
+    return 1 if !exists $self->{logs};    # remember? your own responsibility
+    my $opac = $self->{cat} =~ /^OPAC/;
+    my $log;
+    foreach ( @{ $self->{logs} } ) {
+        $log = $_ if $opac && /^OPAC:/ || !$opac && /^INTRANET:/;
+        last if $log;
+    }
+    $log =~ s/^(OPAC|INTRANET)://;
+    return -w $log;
 }
 
 =head1 AUTHOR
 
 Kyle M Hall, E<lt>kyle@bywatersolutions.comE<gt>
+Marcel de Rooy, Rijksmuseum
 
 =cut