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

I have made a contribution to CPAN. The module is called Log::Log4perl::Shortcuts and its goal is to make the use of Log::Log4perl super easy by minimizing the code needed while keeping the ability to have fine-grained control of the warning level categories using Log4perl's configuration file.

I use it in my own modules and it works well for me. My next goal is to make it into module that can be more useful and adaptable for others as well. For example, the Log4perl configuration file that is bundled with the module is pretty complicated and crufty. It's set up for my own needs/desires so I need to document how it works better so others can create their own custom configurations more easily. Also, some of the log file formatting is hard-coded into the module and I need to figure out a good way to address that.

Before I put that effort in, though, I'd like to feed myself to the wolves and get my fellow Monks' guidance and input. Particularly:

Is the core idea behind this module worth improving upon?

Do you see any major design flaws to the approach of this module?

What confuses you the most about how to implement the module?

Feel free to beat me about the head and neck with your critiques. And thanks to all the monks who have helped answer my questions here on PerlMonks .

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Evaluation of my CPAN module
by tobyink (Canon) on Aug 16, 2018 at 18:34 UTC

    Makes a lot of use of caller. This makes it pretty hard for somebody else to wrap your code if they want an extra layer of abstraction.

    A better way of doing it is something like this:

    sub import { my $me = shift; my $opts = ref($_[0]) ? shift : { for => scalar caller }; my %wanted = map { $_ => 1 } @_; *{ $opts->{for} . "::logf" } = $me->_generate_logf($opts) if $wanted +{logf}; *{ $opts->{for} . "::logw" } = $me->_generate_logw($opts) if $wanted +{logw}; ...; } sub _generate_logf { shift; my $opts = shift; return sub { my $msg = shift; my $log = _get_logger($opts->{for}, shift); return unless $log->is_fatal; $log->fatal($msg); die "\n"; } } ...;

    Exporters like Exporter::Tiny and Sub::Exporter support this kind of pattern — generating subs to export which have been specialized for whatever class is importing them — more easily than Exporter.pm. This technique will not only help avoid reliance on caller, making it easier for people to wrap your module, but will also help you further down the line when you are looking at making it more configurable.

    Also, you didn't use strict or use warnings in your module. (And there's at least one part which would fail under use strict and currently could cause an issue under very contrived circumstances.)

      Awesome, thanks for the advice. Finding a better way to get the callers was on my list of things to improve but I hadn't figured out a good way to accomplish this. In fact, IIRC, I think the code breaks if there are nested calls. I will definitely study this and see if I can get your suggestion incorporated.

      I think I probably had Modern::Perl at some point which automatically inserts those pragmas. I must have accidentally deleted it. Thanks!

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: Evaluation of my CPAN module
by Arunbear (Prior) on Aug 17, 2018 at 13:27 UTC
    In case you weren't familiar with Log4perl's easy mode (also: Re^3: Log Files Module).

    INFO(...), WARN(...), etc seem more intuitive than logw(...) and friends.

      Yeah, was familiar but it wasn't easy enough and it didn't allow me to add categories to fine tune when messages could be turned on and off.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: Evaluation of my CPAN module
by anonymized user 468275 (Curate) on Aug 16, 2018 at 21:31 UTC
    Tricky but what the hell here goes -- I would advise raising your helicopter view a mile or so. The challenge, especially if you are providing a solution to the whole world via CPAN, tends in the context to be to design a cohesive logging system for diverse components written in different sources (fail that and your efforts are relatively futile) e.g. perl, c, bash, SQL, (update plus system and http logs) that meets at least the following criteria:

    Logging has the same format especially timestamp for all components in the system.

    Originating source of each line of logging can be easily determined from the line of logging.

    Logged info must be designed to assist support engineers as well as developers (best achieved by separate or concatenated logging for each audience type

    The difference between the line of logging and further information and/or guilty data needs to be clear from the logging syntax you choose.

    and whatever else other monks might notice (it is also getting late for me).

    I would also advise using a namespace that is less mistakable with the mathematical concept of log, i.e. use Logging instead of log. My first thought was that your module had something to do with logs to base 4 which I suggest is not so stupid given that logs to base 8 are important in devORops - a profession I recently accidentally adopted which might well be on the up.

    upd+ ok you can get away with some diversity and nonconformity but you cannot ignore what the overall objective of logging is (support/maintenace of an application system) to the extent you seem to have done so in the narrowness of your scope.

    upd+ if you do design it for more general use, you'd want to make a callable API of it and have your Perl module also call that.

    One world, one people

      I would also advise using a namespace that is less mistakable with the mathematical concept of log

      The Log::* namespace is already widely in use for logging modules. I'm not aware of any modules in that namespace which deal with logarithms.

        I believe you, but logging would be a clearer term to differentiate from log, given that log (=logarithm) is a standard/core function. The harder question is whether the group will be willing to migrate the whole namespace ;)

        One world, one people