use Log::Log4perl; Log::Log4perl->init(\ <<'EOT'); log4perl.logger = INFO, Screen log4perl.filter.MyFilter = sub { /let this through/ } log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.Filter = MyFilter log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout EOT # Define a logger my $logger = Log::Log4perl->get_logger("Some"); # Let this through $logger->info("Here's the info, let this through!"); # Suppress this $logger->info("Here's the info, suppress this!"); ################################################################# # StringMatch Filter: ################################################################# log4perl.filter.M1 = Log::Log4perl::Filter::StringMatch log4perl.filter.M1.StringToMatch = let this through log4perl.filter.M1.AcceptOnMatch = true ################################################################# # LevelMatch Filter: ################################################################# log4perl.filter.M1 = Log::Log4perl::Filter::LevelMatch log4perl.filter.M1.LevelToMatch = INFO log4perl.filter.M1.AcceptOnMatch = true
Filters have names and can be specified in two different ways in the Log4perl configuration file: As subroutines or as filter classes. Here's a simple filter named "MyFilter" which just verifies that the oncoming message matches the regular expression "/let this through/i":
log4perl.filter.MyFilter = sub { /let this through/i }
It exploits the fact that when the subroutine defined above is called on a message, Perl's special $_ variable will be set to the message text (prerendered, i.e. concatenated but not layouted) to be logged. The subroutine is expected to return a true value if it wants the message to be logged or a false value if doesn't.
Also, Log::Log4perl will pass a hash to the subroutine, containing all key/value pairs that it would pass to the corresponding appender, as specified in Log::Log4perl::Appender. Here's an example of a filter checking the priority of the oncoming message:
log4perl.filter.MyFilter = sub { \ my %p = @_; \ if($p{log4p_level} eq "WARN" or \ $p{log4p_level} eq "INFO") { \ return 1; \ } \ return 0; \ }
If the message priority equals "WARN" or "INFO", it returns a true value, causing the message to be logged.
log4perl.filter.M1 = Log::Log4perl::Filter::LevelMatch log4perl.filter.M1.LevelToMatch = INFO log4perl.filter.M1.AcceptOnMatch = true
This will let the message through if its priority is INFO and suppress it otherwise. The statement can be negated by saying
log4perl.filter.M1.AcceptOnMatch = false
instead. This way, the message will be logged if its priority is anything but INFO.
On a similar note, Log4perl's "StringMatch" filter will check the oncoming message for strings or regular expressions:
log4perl.filter.M1 = Log::Log4perl::Filter::StringMatch log4perl.filter.M1.StringToMatch = bl.. bl.. log4perl.filter.M1.AcceptOnMatch = true
This will open the gate for messages like "blah blah" because the regular expression in the "StringToMatch" matches them. Again, the setting of "AcceptOnMatch" determines if the filter is defined in a positive or negative way.
All class filter entries in the configuration file have to adhere to the following rule: Only after a filter has been defined by name and class/subroutine, its attribute values can be assigned, just like the "true" value above gets assigned to the "AcceptOnMatch" attribute after the filter "M1" has been defined.
log4perl.appender.MyAppender.Filter = MyFilter
This will cause "Log::Log4perl" to call the filter subroutine/method every time a message is supposed to be passed to the appender. Depending on the filter's return value, "Log::Log4perl" will either continue as planned or withdraw immediately.
Typically, filter results will not need to be bumped along chains but combined in a programmatic manner using boolean logic. ``Log if this filter says 'yes' and that filter says 'no''' is a fairly common requirement, but hard to implement as a chain.
"Log::Log4perl::Filter::Boolean" is a specially predefined custom filter for Log4perl. It combines the results of other custom filters in arbitrary ways, using boolean expressions:
log4perl.logger = WARN, AppWarn, AppError log4perl.filter.Match1 = sub { /let this through/ } log4perl.filter.Match2 = sub { /and that, too/ } log4perl.filter.MyBoolean = Log::Log4perl::Filter::Boolean log4perl.filter.MyBoolean.logic = Match1 || Match2 log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.Filter = MyBoolean log4perl.appender.Screen.layout = Log::Log4perl::Layout::SimpleLayout
"Log::Log4perl::Filter::Boolean"'s boolean expressions allow for combining different appenders by name using AND (&& or &), OR (|| or |) and NOT (!) as logical expressions. Also, parentheses can be used for defining precedences. Operator precedence follows standard Perl conventions. Here's a bunch of examples:
Match1 && !Match2 # Match1 and not Match2 !(Match1 || Match2) # Neither Match1 nor Match2 (Match1 && Match2) || Match3 # Both Match1 and Match2 or Match3
package Log::Log4perl::Filter::MyFilter; use base Log::Log4perl::Filter; sub new { my ($class, %options) = @_; my $self = { %options, }; bless $self, $class; return $self; } sub ok { my ($self, %p) = @_; # ... decide and return 1 or 0 } 1;
Log4perl will call the ok() method to determine if the filter should let the message pass or not. A true return value indicates the message will be logged by the appender, a false value blocks it.
Values you've defined for its attributes in Log4perl's configuration file, will be received through its "new" method:
log4perl.filter.MyFilter = Log::Log4perl::Filter::MyFilter log4perl.filter.MyFilter.color = red
will cause "Log::Log4perl::Filter::MyFilter"'s constructor to be called like this:
Log::Log4perl::Filter::MyFilter->new( name => "MyFilter", color => "red" );
The custom filter class should use this to set the object's attributes, to have them available later to base log/nolog decisions on it.
"ok()" is the filter's method to tell if it agrees or disagrees with logging the message. It will be called by Log::Log4perl whenever it needs the filter to decide. A false value returned by "ok()" will block messages, a true value will let them through.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
http://github.com/mschilli/log4perl
Send bug reports or requests for enhancements to the authors via our
MAILING LIST (questions, bug reports, suggestions/patches): log4perl-devel@lists.sourceforge.net
Authors (please contact them via the list above, not directly): Mike Schilli <m@perlmeister.com>, Kevin Goess <cpan@goess.org>
Contributors (in alphabetical order): Ateeq Altaf, Cory Bennett, Jens Berthold, Jeremy Bopp, Hutton Davidson, Chris R. Donnelly, Matisse Enzer, Hugh Esco, Anthony Foiani, James FitzGibbon, Carl Franks, Dennis Gregorovic, Andy Grundman, Paul Harrington, Alexander Hartmaier David Hull, Robert Jacobson, Jason Kohles, Jeff Macdonald, Markus Peter, Brett Rann, Peter Rabbitson, Erik Selberg, Aaron Straup Cope, Lars Thegler, David Viner, Mac Yang.