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

I decided to work on improving some code (and start using Perl::Critic) to improve my perl-fu. I have become stuck on what seems like a simple issue.

My program has three log-related options: -l allows the user to specify an output log file and -s instead directs the program output to STDOUT instead of to a file. Throughout the program I print various messages to the log to record the progress. -v specifies a 'verbose' mode where more messages are posted.

I started reading the paltry documentation for the FileHandle module and it has left a lot to be desired (even when going behind it to the IO::File and ::Handle modules). Here is what I have come up with so far, but I feel that there is probably a way to simplify this further.

use FileHandle; our $LOGFH; #can't figure out a way around using a global var here if ( $opt_s ) { $LOGFH = new_from_fd FileHandle fileno(STDOUT), 'a'; } else { $opt_l ||= $DEFAULT_LOG_FILE; $LOGFH = new FileHandle $opt_l, 'a'; } ( ! defined $LOGFH ) and croak 'Could not open logfile, aborting.'; autoflush $LOGFH 1; #autoflush on $LOGFH->print(scalar localtime, ": running MyProgram.\n") or carp 'Could not print to log.';
...during execution optional (verbose) messages are posted (sometimes within subroutines, hence the need for a global filehandle):

$opt_v and $LOGFH->print("$count records were processed.\n") or carp 'Could not print to log.';

...and then, after the program does it's thing:

if ( !$opt_s ) { $LOGFH->print(q{-} x 50, "\n") or carp 'Could not print to log.'; close $LOGFH or croak "Could not close the logfile: $!"; }

I have looked at some of the descriptions for the various logging modules on CPAN, and they all seem like overkill for the very basic logging I want to do. My knowledge of perl always grows when I consult the monks, so I am excited to hear any thoughts on the above code snippets and the problem in general, particularly if there is a logging module that is heavily recommended.

Replies are listed 'Best First'.
Re: Best method for opening/using a log
by ikegami (Patriarch) on Jun 17, 2009 at 00:02 UTC

    Simply changing our to my will avoid the package variable if that's what you meant by global. There's nothing wrong with this particular var being global (whether my or our).

    You're using indirect object notation (method Class @args) which is iffy. Class->method(@args) is more reliable, better recognized and more readable.

    You don't need new_from_fd at all unless you plan on passing the handle to child processes.

    Don't need to include the line number in a message destined to the user.

    use IO::Handle qw( ); my $LOGFH; if ( $opt_s ) { $LOGFH = \*STDOUT; } else { $opt_l = $DEFAULT_LOG_FILE if !defined($opt_l); open( $LOGFH, '>>', $opt_l ) or die("Could not open logfile \" $opt_l\": $!\n"); } $LOGFH->autoflush(1); #autoflush on
Re: Best method for opening/using a log
by targetsmart (Curate) on Jun 17, 2009 at 07:25 UTC
    if there is a logging module that is heavily recommended.
    I don't have a benchmark statistics or a pros and cons comparison chart to recommend the best one.
    but below are the ones I use often. "I don't want to re-invent the wheel"
    log::log4perl
    log::agent

    I have looked at some of the descriptions for the various logging modules on CPAN, and they all seem like overkill for the very basic logging I want to do.
    one thing you have to understand, the process of logging will start with a small requirement , 'just to get some debug trace', but when there are too many debug statements to be logged, the log grows huge, and when your application is a long running program, then you are in deep trouble, you will need log rotation, and it goes on like this. I am sure that your requirement will grow :)
    so better understand the log:: modules available on CPAN and get used to the one which suits your requirement.


    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.