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 )