Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Logging Singleton

by Anonymous Monk
on Feb 18, 2013 at 16:45 UTC ( #1019364=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, hoping you can advise. I created a logging singleton to use across various packages. Each time I want some logging done I check to see if there is an instance of the log already ($log = Log->new();) otherwise create the log. Then log what I want $log->log('Log This'); There are 30+ subroutines. Is the call to sub new in each sub an ok practice? Please let me know if there is a better way or a perferred method. Thanks
package Log; my $singleton; sub new { # Check to see if we have a Log instance # Otherwise return singleton unless ( $singleton ){ my ($class,$path) = @_; $singleton = {}; bless $singleton, 'Log'; $singleton->create_logfiles($path); } return $singleton; } sub create_logfile{ create logfile } sub log { print to logfile } # SUBS sub do_this{ my $log = Log->new(); $log->log('Log This'); } sub do_that{ my $log = Log->new(); $log->log('Log That'); }

Comment on Logging Singleton
Download Code
Replies are listed 'Best First'.
Re: Logging Singleton
by tobyink (Abbot) on Feb 18, 2013 at 16:51 UTC

    It's probably overkill. You could do this...

    # SUBS my $log = Log->new(); sub do_this{ $log->log('Log This'); } sub do_that{ $log->log('Log That'); }

    Or even this...

    # SUBS my $log; sub do_this{ ($log||=Log->new)->log('Log This'); } sub do_that{ ($log||=Log->new)->log('Log That'); }
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Logging Singleton
by 7stud (Deacon) on Feb 18, 2013 at 17:26 UTC

    Please let me know if there is a better way or a perferred method.

    1. Rename new() to get_logger()?
    2. Use a closure?
    3. use strict; use warnings; use 5.012; package Log; { my $logger; sub get_logger { if (not $logger) { my ($class, $path) = @_; say "Creating logger..."; $logger = {}; bless $logger, "Log"; $logger->create_logfile($path); } else { say "Logger already exists..." } return $logger; } } sub create_logfile { } sub do_stuff { #$logger = 'hello'; }
      use strict; use warnings; use 5.012; use Log; my $log = Log->get_logger(); #Creating logger... $log = Log->get_logger(); #Logger already exists... $log = Log->get_logger(); #Logger already exists... #$log->do_stuff;

      With a closure, you can't (mistakenly) change the $logger singleton in another subroutine:

      Global symbol "$logger" requires explicit package name at line +32. Compilation failed in require at line 5.

      The my variable $logger ceases to exist after the end of the block, and thereafter only the sub get_logger() can see the $logger variable.

      Thank you. Haven't implemented a closure before but I'll read up on them. Thanks!
Re: Logging Singleton
by blue_cowdawg (Monsignor) on Feb 18, 2013 at 18:45 UTC

    Do you really need a singleton? Consider the following:

    package Log; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( logit ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( logit ); sub logit { # real stuff goes here. printf "%s\n",join("\n",@_); } 1;
    Using the above looks something like this:
    #!/usr/bin/perl -w use strict; use Log qw/ :all /; logit("This is something to log");
    Just another way of doing it I guess...

    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Logging Singleton
by manorhce (Beadle) on Feb 18, 2013 at 18:56 UTC

    Hi It will be easy if you will follow to Log::Log4perl module which cpan provides

    you can call the log method like Log->info($message)

    Create a module with using Log::Log4perl

    BEGIN { require Exporter; push @ISA, qw(Exporter); @EXPORT = ( @Data::Dumper::EXPORT, @Carp::EXPORT, qw($log get_logger); $conf_file="path to log4perl.conf"; eval { Log::Log4perl->init($conf_file); } if ($@) { die "Cann't open the file" if ($@ =~ m/Permission/gi); } Log::Log4perl->get_logger("My::MegaPackage"); } sub new { my $class = shift; return bless {}, $class; } sub info { my ($self, $message) = @_; my ($package, $filename, $line) = caller; my $_log = Log::Log4perl->get_logger($packa +ge); $log->info($message) if ($log->is_info()); } sub error { my ($self, $message) = @_; my ($package, $filename, $line) = caller; my $_log = Log::Log4perl->get_logger($packa +ge); $log->error( longmess($message) ) if ($log->is_error()); } sub debug { my ($self, $message) = @_; my ($package, $filename, $line) = caller; my $_log = Log::Log4perl->get_logger($packa +ge); $log->debug($message) if ($log->is_debug()); }

    and by using this module and calling get_logger() method your job will be easy

    Please let me know if you are unclear on this and I will suggest to follow Log::Log4perl for better logging messages

      Thanks. I would have used log4perl but unfortunately working with older version of Perl.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1019364]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2015-10-07 00:52 GMT
Find Nodes?
    Voting Booth?

    Does Humor Belong in Programming?

    Results (167 votes), past polls