Log-Log4perl-AutoCategorize
view release on metacpan or search on metacpan
lib/Log/Log4perl/AutoCategorize.pm view on Meta::CPAN
Note also that (4), even if it was uncommented, would have no effect
on the logging, because its just saying that all debug() calls done by
Frob::Vernier::twiddle() are issued at their default level. Keeping
such lines commented is good for documentation, and more efficient; it
saves Log::Log4perl both cpu and memory by not loading config-items
that arent meaningful.
=head1 Other Features
Automatic categorization, logging coverage, and fine-grained control
of logging are the primary value-added features of this wrapper
package. Other secondary features are;
=head2 Configuration Loading
If use Log::Log4perl::AutoCategorize is given an import list which
includes initstr => q{} or initfile => $filename, the string or file
is used to initialize Log::Log4perl. You can still use the old way,
ie $base->init().
=head2 Classname Aliasing
Because it would be inconvenient to type the full classname for every
statement, ex: Log::Log4perl::AutoCategorize->debug(), the package has
the ability to alias itself into a classname of your choice, ex:
use Log::Log4perl::AutoCategorize ( alias => myLogger );
myLogger->debug("ok doing it");
Because aliasing is used in optimization phase, it must be imported
via use, it cannot be deferred as in require, import.
=head2 Easy Initialization
You can initialize the base logger by any of the following;
# as use parameters, least typing
a. use Log::Log4perl::Autocategorize ( initstr => $string );
b. use Log::Log4perl::Autocategorize ( initfile => $filename );
# assuming youve already used the package
c. Log::Log4perl::AutoCategorize->init( $filename );
d. Log::Log4perl::AutoCategorize->init( \$string );
# you can cheat, and use the base class name
e. Log::Log4perl->init( $filename );
f. Log::Log4perl->init( \$string );
# assuming youve aliased
g. Logger->init( $filename );
h. Logger->init( \$string );
i. # no explicit initialization at all (theres a default config)
The default config writes to stdout, and includes a test-coverage
setup. This config is used at import() time, unless a or b is
provided by you. If you explicitly call init(), the base is
re-initialized, and relys on base behavior to work correctly.
I hope at some point to provide init_modify(), which will overlay new
configuration on existing, rather than a full reinitialization. This
will be implemented using Log4perls (currently nonexistent)
configuration include mechanism.
=head2 Automatic Dump of structured data
If you pass in a data-ref, its rendered using Data::Dumper, making it
easy to examine the details of the runtime context. Since the Dump is
embedded inside the logging-method, its only called when needed,
avoiding work to produce output that will just be thrown away.
=head2 SubClassing
As sayeth L<perltoot/Planning for the Future: Better Constructors>,
you make you package suitable for deriving new ones. test
04_subclass.t verifies this, though it wasnt the 1st thing I got
working.
=head1 Module Architecture
The previous section hopefully provides sufficient motivation for why
you should use this module, this section describes how the module
works.
2 phase strategy to achieve both greater filtering capability, and
similar or better efficiency.
=head2 Original AUTOLOAD functionality
In v0.001, AUTOLOAD did the entire job itself, primarily cuz it seemed
better to write the code once, rather than 5 times (for debug, info,
warn, error, fatal). Every time a call like Logger->warn() was
reached, AUTOLOAD would get control, and do the following:
0. determine log-level which was called ($AUTOLOAD)
1. used caller() to construct a category string, $logcat, dynamically.
2. fetched the $logger singleton {$logger = get_logger($logcat)}
3. tested if $logcat was a loggable event {$logger->is_$loglevel()}
4. logged the message, or not, as appropriate.
Doing this repeatedly using caller() for every call is computationally
expensive for a logging subsystem. If the module is to be usable
application wide, it must be efficient.
=head2 Gaining efficiency
The canonical way to get speed from AUTOLOAD is to not call it; or
more helpfully, to create the desired subroutine so that it gets
called for all future calls to that method. But in this case, the
decision reached in step 4 is different for every invocation, so it
cannot be reduced to a single subroutine unless that routine calls
caller(), which defeats the purpose.
The only way to get custom behavior for each invocation is to make
them each invoke a unique method name; ie to munge the method names
where they are invoked. Once this is done, AUTOLOAD can then vivify
subroutines which 'remember' results of caller(), and the log/nolog
decision reachedd for that invocation. Thereafter AUTOLOAD wont be
called again (for that unique method), avoiding steps 0-4 completely.
( run in 2.107 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )