Koha Logger

=  Koha::Logger =
== Instantiation ==
A logger instance is created at it's most basic like so: 
my $logger = Koha::Logger->get( { interface => $interface, category => $category } ); 
The get method takes two parameters, interface and category. 
=== The interface paramater ===
This parameter defines which part of Koha we are executing code for. The two primary interfaces of Koha are intranet and opac, but we can consider other interfaces such as commandline, sip and possibly others. See Bug 14751 
So, for example, to get a logger for an opac cgi script, we would do something like: 
my $logger = Koha::Logger->get( { interface => 'opac' } );
 
For a staff side script it would be: 
my $logger = Koha::Logger->get( { interface => 'intranet' } );
 
Please note that you should only set the interface for Perl scripts and not for Perl modules. Modules may be used from any interface, so we want loggers fetched for Perl modules to detect the interface using C4::Context. For example, you may do this in a script: 
C4::Context->interface('intranet');
my $logger = Koha::Logger->get(); 
This will explicity tell Koha what interface it is using right now. Koha already attempts to set the interface to intranet or opac, but setting it manually is guaranteed to work. 
Any script that does not call get_template_and_user will need to have the interface set manually. 
=== The category parameter ===
The category parameter is one you should be using every time you get a logger. It is very important, as this parameter defines the main part of the namespace for any data you log. The namespace consists of the interface, joined with the category. 
For example: 
my $logger = Koha::Logger->get( { interface => 'intranet', category => 'C4.Circulation.AddReturn' } );
 
would give use the namespace "intranet.C4.Circulation.AddReturn". 
The logger namespace is similar but not actually connected to Perl namespaces. The primary difference is that we are using periods as a separator instead of double colons. 
Please not that the category does not have to align with the module and subroutine name, though that is a very helpful model which should often be used. 
For scripts the namespace could be the path of the script, for circ/returns.pl a namespace of "circ.returns" makes perfect sense. 
my $logger = Koha::Logger->get( { interface => 'intranet', category => 'circ.returns' } );
 
The default configuration of Koha's logger is to split everything into two large pots, intranet and opac. Each of these categories has a single error file. However, we are not limited to this configuration. 
=== The importance of setting a good category ===
Log4Perl, the library which Koha::Logger uses, is incredibly flexible. Not only can we redirect different logged data to different files based on the namespace, we can also set up email triggers, direct data to other services such as syslog or a database and more! 
For example, if we want to filter the logging for a certain subroutine ( let's say Koha::Borrower::Debarments::AddDebarment ) to a separate file, we can do that. All we need to do to give the logger this flexibility is to set our categories well ( in this case, it could be Koha.Borrower.Debarments.AddDebarment )
== Using the logger ==
Now that we know how to create a logger instance, what do we do with it? At it's most basic, we can use it as a replacement for warn. 
$logger->warn("Item $itemnumber has no homebranch!"); 
we can also take advantage of other log levels to log data that we may need in the future, but don't need on a daily basis. 
Koha::Logger has 6 logging levels of increasing severity 
$logger->trace("..."); # Use trace for the least important messages, such as logging the parameters of a subroutine call $logger->debug("..."); # Use debug for messages that may be useful to developers attempting to understand how a piece of code functions $logger->info("..."); # Use info for messages that may be useful to Koha server administrators, but are not errors $logger->warn("..."); # Use warn for situations where something bad has happened $logger->error("..."); # Use error for situations where something really bad has happened $logger->fatal("..."); # Use fatal for messages where we can't continue executing and we should end execution 
By default, only messages of warn, error or fatal will be logged in Koha. To reveal less severe messages a Koha admin will need to modify the Koha's Log4Perl configuration file. 
==== Efficiency ====
If you're afraid that generating the parameters to the logging function is fairly expensive, use closures: 
sub MySub {
 my ( $params ) = @_;
 $logger->trace( sub { "MySub called with parameters: " . Dumper($params) } );
}
 
This will keep the processing from occurring unless that log statement will actually be used!
== Best Pratices ==
For modules, it is best to create a shared package level logger to avoid the overhead of creating a logger every time a given subroutine/method is called. Only in specific cases where it is necessary should a subroutine level logger be used.
== Resources ==
Log::Log4perl on CPAN
Log::Log4perl::Config on CPAN