NAME

Log::Localized - Localize your logging

SYNOPSIS

What you most probably want to do is something like:

package Foo;
use Log::Localized; 

sub bar {
    # this message will be displayed if method bar's verbosity is >= 1
    llog(1,"running bar()");
}

# this message will be displayed if package Foo's verbosity is >= 3
llog(3,"loaded package Foo");

Then paste the following local verbosity rules in a file called 'verbosity.conf', in the same directory as your program:

# log everything from wherever inside Foo and its subclasses, up to level 3
Foo:: = 3
# except for function Foo::foo who shall have verbosity 0
Foo::bar = 0

SYNOPSIS - ADVANCED

In a program accepting command line arguments, you may want to do:

use Getopt::Long;
use Log::Localized log => 1;

GetOptions("verbose|v+" => sub { $Log::Localized::VERBOSITY++; } );

llog(1,"you used -v");
llog(2,"you used -v -v");

You may alter local verbosity from within the running code:

package Foo;
use Log::Localized log => 1;

# verbosity level is 0 by default

{
    # set verbosity locally in this block
    local $Log::Debug::VERBOSITY = 5;  
    llog(5,"this will be logged");
}

debug(5,"but this won't");

If you want to import 'llog' under another name in the calling module:

package Foo;
use Log::Localized rename => "my_log";

# call Log::Localized::llog()
my_log(1,"renamed llog()");

See the examples directory in the module distribution for more real life examples.

DESCRIPTION

Log::Localized provides you with an interface for defining dynamically exactly which part of your code should log messages and with which verbosity.

Log::Localized addresses one issue of traditional logging: in very large systems, a slight increase in logging verbosity usually generates insane amounts of logs. Hence the need of being able to turn on verbosity selectively in some areas of code only, in a localized way.

Log::Localized is based on the concept of local verbosity. Each package and each function in a package has its own local verbosity, set to 0 by default. With Log::Localized you can change the local verbosity in just a function, just a package or just a class hierarchy via a so called verbosity rule. Verbosity rules are passed to Log::Localized either via a configuration file or via an import parameter. By changing verbosity rules according to the needs of the moment, you can alter your program's logging flow in a very fine-grained way, and get logs from only the code areas you are interested in.

Log::Localized comes with default settings that make it usable 'out of the box', but its configuration options will let you redefine pretty much everything in its behavior.

The actual logging in Log::Localized is handled by Log::Dispatch.

DEFAULT SETTINGS

DEFAULT VERBOSITY The local verbosity is everywhere 0 by default.
DEFAULT DISPATCHER Log::Localized dispatches its log to STDOUT by default and with no Log::Dispatch preformatting of the log messages. You can change the default dispatcher with the option Log::Localized::dispatchers.
DEFAULT SEARCH PATH The default search path in which Log::Localized will search for verbosity rules files or dispatcher config files is (in this order) the local directory, the user's home directory and the root directory (to enable the use of absolute paths in options). The default search path can be overriden with the Log::Localized::search_path option.
DEFAULT VERBOSITY RULES FILE NAME By default, the verbosity rules file should be called 'verbosity.conf'. This name can be changed with the option Log::Localized::use_rules.
DEFAULT LOG FUNCTION NAME Log::Localized's logging function is by default exported under the name llog, but this can be changed with the option Log::Localized::rename or via the import parameter rename.
DEFAULT GLOBAL VERBOSITY ENVIRONMENT VARIABLE NAME The environment variable setting the global verbosity level is by default 'LOG_LOCALIZED_VERBOSITY'. This can be changed with the option Log::Localized::global_verbosity.
DEFAULT FORMATTING Log::Localized pre-formats log messages by default. The message 'whatever' coming from function test in module Foo::Bar and logged at line 25 with level 2 will be logged as '# [Foo::Bar::test() l.25] [LEVEL 2]: whatever'. This default pre-formatting can be changed with the Log:Localized::format option.

CONFIGURATION

Log::Localized provides 4 mechanisms to affect local verbosity. They are, in order of precedence:

ENVIRONMENT VARIABLE

If the environment variable LOG_LOCALIZED_VERBOSITY is set, logging is turned on and Log::Localized will log everywhere in the code to the level of verbosity set in LOG_LOCALIZED_VERBOSITY. LOG_LOCALIZED_VERBOSITY's value must be a positive integer. This overrides even the verbosity level eventually set vith verbosity rules. Note that the name of this environment variable can be changed vith the appropriate option.

VERBOSITY RULES VIA IMPORT PARAMETERS

Verbosity rules can be loaded at 'use' time via the import parameter 'rules'. If Log::Localized is passed rules in that way, those rules will be merged with the rules eventually loaded from a rules file at compile time, and logging is turned on.

VERBOSITY RULES IN A FILE

If at compilation time there exists a file called 'verbosity.conf' in the search path, the rules it contains are loaded and logging is turned on. Note that you can modify both the default search path and rules file name with the appropriate options.

LOCAL VERBOSITY

You can also set verbosity locally in the code, by locally setting the class variable $Log::Localized::VERBOSITY. See the examples in SYNOPSIS. Verbosity set in this way will be overriden by any verbosity defined via the environment variable or via rules.

VERBOSITY RULES

Verbosity rules follow the Tiny::Config syntax. Read its pod before continuing.

Below is an example of verbosity rules:

# default block
main:: = 4
Foo::* = 3

# additional rules specific to program 'test.pl'
[test.pl]
main:: = 0
Foo::bar = 0

Those rules read like this: set local verbosity to 4 everywhere in package 'main' and all subpackages of package 'main'. Set local verbosity everywhere in package 'Foo' to 3. But if the running program is 'test.pl', use the same rules, except that local verbosity should be set to 0 everywhere in package 'main' and all its subpackages, and verbosity should be set to 0 for function bar in package 'Foo'.

CONFIG BLOCKS

See Config::Tiny. The default heading block contains default verbosity rules that apply to all programs. Following configuration blocks are named with, in brackets, the name of a program to which the block's rules apply. Rules in a named block apply only to the program having the same name, and will override any default rules with similar keys.

VERBOSITY RULES

A verbosity rule is a key-value pair of the form 'key = value', where value must be an integer. Those pairs can have one of the following syntaxes:

namespace:: = value where namespace is a Perl namespace, such as 'main' or 'Foo::Bar'. This rule reads 'set local verbosity to value everywhere in package namespace and all its sub-packages'. Everywhere means in all functions, blocks, methods...
namespace::* = value reads 'set local verbosity to value everywhere in package namespace (but not in its sub-packages)'.
namespace::function = value reads 'set local verbosity to value in function function from package namespace'.
function = value is the same as 'main::function = value'.

See 'LOGGING ALGORITHM' for details about rule precedence.

LOG::LOCALIZED OPTIONS

When feeding verbosity rules to Log::Localized via a rules file or via the import parameter 'rules', you can alter the default settings of Log::Localized by declaring some of the following special rules:

Log::Localized::rename = $name instructs Log::Localized to export llog under the name $name.
Log::Localized::dispatchers = $file instructs Log::Localized to use the dispatchers defined in the Log::Dispatch::Config file called $file located in the search path. Those dispatchers replace Log::Localized's default dispatcher (ie STDOUT).
Log::Localized::format = $format instructs Log::Localized to pre-format log messages according to the macro in $format. The default format macro is '# [%PKG::%FNC() l.%LIN] [LEVEL %LVL]: %MSG'. %MSG is replaced by the log message, %FNC by the name of the function calling llog and %PKG by the name of this function's package, %LIN by the line code number where llog is called and %LVL with the level of the message passed to llog. The $format string can be any string containing some of these 5 keywords.
Log::Localized::global_verbosity = $name instructs Log::Localized to use $name as the name of the global verbosity environment variable.
Log::Localized::use_rules = $rules indicates the name of a verbosity rules file from which all rules should be reloaded. The use_rule option makes that all rules loaded so far are droped and that new rules are searched in a file called $rules located in the search path. This option allows you to change the default name for rules files ('verbosity.conf'). You may want to combine it with the search_path option to specify the directory in which the new rules file is located.
Log::Localized::search_path = $pathlist specifies the search path in which to search for the use_rules and dispatchers files. $pathlist is a traditional UNIX style search path made of a colon separated list of paths (ex: "~/config/:/opt/log/:$SYSTEM_ROOT/conf/"). Log::Localized will substitute any occurence of '~' with the path of the current user's home directory (see File::HomeDir), and any name starting with a dollar sign by the content of the environment variable having the same name, if this variable exists. If the variable does not exist, the path is left unchanged.

LOGGING ALGORITHM

Upon calling 'llog($level,$message)', llog does the following to find out the local verbosity.

If the global verbosity environment variable is set, its value is used as the local verbosity.

Otherwise, llog identifies the calling function and its module and checks whether there exists a rule with the key 'module::function'. If not it searches for a rule with the key 'module::*'. If not, it searches for a rule with the key 'module::', then with keys corresponding to parent packages of 'module'. For example, if module is 'Foo::Bar::Naph', the following keys will be successively searched for: 'Foo::Bar:Naph::', 'Foo::Bar::' then 'Foo::'. This explain the 'package and all subpackages' mechanism named previously.

Finally, if no matching verbosity rule was found, llog uses the value of the class variable $Log::Localized::VERBOSITY, defaulting to 0.

If the message level is less or equal to the local verbosity, llog will log the message.

In that case, if the message was a closure, llog executes it and takes its result as the message. llog pre-formats the message, then dispatch it to its Log::Dispatch object.

IMPORT PARAMETERS

"rename => $name" exports llog into the calling module under the name $name.
"rules => $rules" lets you inject verbosity rules into Log::Localized. The syntax of $rules is the same as for the verbosity rules file. This is particularly usefull for passing configuration options to Log::Localized. Note though that option changes will apply globally to all modules using Log::Localized, and not only to the one calling Log::Localized with the import parameter 'rules'. Example:
use Log::Localized rules => "Log::Localized::search_path = / \n".
                            "Log::Localized::dispatchers = /opt/conf/dispatch.conf \n".
                            "Log::Localized::use_rules = /opt/conf/rules.conf \n";
"log => [0|1]" turns logging on or off. llog is exported into the calling module only if logging is turned on. Logging is turned on if a rule verbosity file was found at compilation time or passed via the 'rules' parameter, or if the global verbosity environment variable is defined upon importing. If neither exists, but you still want to log, you have to use the 'log' parameter with the value 0 (off) or 1 (on):
use Log::Localized log => 1;

EXPORTED FUNCTIONS

llog($level,$message)

Where $level is an integer, and $message is either a string or a reference to a function that returns a string.

llog dispatches the message $message if $level is inferior or equal to the local verbosity in the code where llog is called. llog has no return value.

See 'LOGGING ALGORITHM' for details on how llog works.

By convention, messages with a $level of 0 are always logged (if logging is on), since the default local verbosity is 0 too.

If $message is a function reference instead of a string, this function is executed and the string it returns is used as the log message. Note that the function is executed only if the message level is <= to the local verbosity. Indeed, a call like:

llog(4,"content of this hugely complex object: ".Dumper($obj));

will slow things down in code where speed matters, since it executes Dumper even when the local verbosity is lower than 4. If you want Dumper to execute only when the message would actually be logged, wrap it in an anonymous function:

llog(4, sub { "content of this hugely complex object: ".Dumper($obj); } );

CLASS VARIABLES

$Log::Localized::VERBOSITY

See 'LOGGING ALGORITHM' for details and 'SYNOPSIS' for examples.

$Log::Localized::LEVEL

Contains the level of the message last received by llog. This class variable is made to be used by closures that are passed to llog. See the example in the 'examples' directory.

WARNING

Forking, threading Log::Localized is not designed to be used simultaneously by multiple threads or processes.
Monitoring rule changes Log::Localized loads the verbosity rules only once, at 'use' time, and will not notice later changes of the rules file during runtime. This may be implemented in the future.

SEE ALSO

See Log::Dispatch, Log::Log4perl.

BUGS AND LIMITATIONS

Please report any bugs or feature requests to bug-log-localized@rt.cpan.org, or through the web interface at http://rt.cpan.org.

FOR FUN

By the way, Log::Localized llogs itself :) To get a glimpse of Log::Localized's internals, 'use Log::Localized;', then dump the rule 'Log::Localized:: = 3' in a local file called 'verbosity.conf'...

AUTHOR

Written by Erwan Lemonnier <erwan@cpan.org> and co-designed by Claes Jacobsson <claesjac@cpan.org>.

COPYRIGHT AND LICENSE

Copyright (C) 2005 by Erwan Lemonnier <erwan@cpan.org>

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.