Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

perl modules design for logging

by pwagyi (Monk)
on Sep 10, 2019 at 07:19 UTC ( [id://11105930] : perlquestion . print w/replies, xml ) Need Help??

pwagyi has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks! Please enlighten me on how to handle, best-practices on logging in OO/non-OO modules. I have a couple of Object oriented modules (Moo/se classes), and since these classes implement business logic, I'd like to have some form of logging (informational/warning/ error/etc).

At the same time I don't want to burden clients of modules with details of logging, ie. modules should be usable without any set-up of logging from client (I am thinking in this case no logging from modules)

Replies are listed 'Best First'.
Re: perl modules design for logging
by Discipulus (Canon) on Sep 10, 2019 at 08:33 UTC
    Hello pwagyi

    you can start here: Logging at Task::Kensho

    Also Log::Any seems interesting and can be used directly inside Moo class:

    package Foo; use Log::Any (); use Moo; has log => ( is => 'ro', default => sub { Log::Any->get_logger }, );

    You can also be interested in logging in my bibliotheca linking to Choosing a log level


    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: perl modules design for logging
by Fletch (Bishop) on Sep 10, 2019 at 13:59 UTC

    You might also check out Log::Log4perl depending on your tolerance of log4j. Or Log::Dispatch which I believe it also works with / uses under the hood.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: perl modules design for logging
by NERDVANA (Deacon) on Sep 14, 2019 at 02:48 UTC

    Both Log::Contextual and Log::Any are designed to be generic logging "routers" for module authors to use, such that the top-level script can decide where to direct the messages.

    They take slightly different stances: Log::Contextual throws an exception if no logging destination gets configured, so every module/distribution that uses it needs to also specify some kind of default logging behavior when first initialized. You can make it so that the default does not override whatever the top-level script decided to do. This can make the boilerplate for your modules a bit ugly.

    Log::Any takes the opposite position, and all log messages are discarded by default unless someone directs them somewhere. This can mean that someone uses your module and can't figure out why it isn't working, because they aren't seeing any of the warnings and don't know that they need to configure Log::Any::Adapter to see them.

    Log::Any has no non-core dependencies. Log::Contextual is also pretty light, but depends on Moo and some other small stuff.

    I work on a large project that uses both - it means that the utility scripts I write need to hook into *both* log streams in order to see the full logging generated by the modules. Having used both, I think I like Log::Any a little better, but it's only a small preference.

    Whatever you do, don't try to integrate Log4Perl or a full-featured logger into a *module*, because then all users of your module have to wrangle the configuration for it.

    One final option is to not use any library, and expect the user of the object to supply the logger as an attribute. This is the approach I took in my, since I expect most people want to capture the log messages into an array (to respond to web-submitted data). Both Log::Any and Log::Contextual make it a bit difficult to *temporarily capture* log messages into an array.