Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Log::Log4perl use strategies

by Excalibor (Pilgrim)
on May 09, 2006 at 10:18 UTC ( [id://548168]=perlquestion: print w/replies, xml ) Need Help??

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

Dear monastery brothers,

I am using Log::Log4perl on a fairly complex project, and I have been assailed by doubt as of late.

I got this error at the end of a Test::Harness run: (in cleanup) Internal error: Root Logger not initialized. at /usr/share/perl5/Log/Log4perl/Logger.pm line 521 during global destruction.

Now, I started to look why I get this error, and I cannot find why. But I thought it could be due to some module being called (or not being called) because the way I was handling the logging objects.

So I started to think, again, on the loggers and how I am using them. I have wrapped the Log::Log4perl->init() call within a module, which gets use()d right at the start of every package, so the root logger, and everything else, like configuration file, appenders, etc is handled rightly. Then, I am using my class hierarchy as the logger categories, as suggested. However, there are several ways to get to the loggers, and maybe I'm not using the best one. Some examples follow.

This is the way I am using it (strategy A):

package Foo; use Init; # initializes Log::Log4perl among other things use Log::Log4perl qw(get_logger); my $logger = get_logger(); sub new { $logger->warn("Creating Foo"); return bless {}, shift; } sub foo { $logger->warn("Fooing") } 1;

Now, I have this possibility (strategy B):

package Bar; use Init; use Log::Log4perl qw(get_logger); sub new { my $logger = get_logger(); $logger->warn("Creating Bar"); return bless { logger => $logger }, shift; } sub bar { my $self = shift; $self->{logger}->warn("Baring"); } 1;

Using this testing code

use Foo; use Bar; $f = Foo->new; $b = Bar->new; $f->foo; $b->bar;

yields the expected result (please, don't mind the format, I am reusing the project format, and this is not the default output):

2006/05/09 11:53:01 WARN> test_log_strategies.pl:8 Foo::new - Creating + Foo 2006/05/09 11:53:01 WARN> test_log_strategies.pl:19 Bar::new - Creatin +g Bar 2006/05/09 11:53:01 WARN> test_log_strategies.pl:10 Foo::foo - Fooing 2006/05/09 11:53:01 WARN> test_log_strategies.pl:21 Bar::bar - Baring

Now, being a singleton, there shouldn't be any differences beetween the lexical-to-the-package logger and the lexical-to-the-object one, right? So which one is better, A or B?

'A' allows writing less and don't fiddling with your objects guts (which is what B does, but it's also hiding things, "encapsulating"), but it gives the same object to all instances. A 'C' approach would be to get the logger in every method that needs it, but I don't see that different (in this singleton-based logging method) to method A.

I can devise even other logging strategies as well, but they are even more contorted (I haven't checked the Aspect Oriented Programming mentioned in other Log::Log4perl threads in the monastery library).

So, in this case of Log::Log4perl, which strategy is best to use? A package lexical logger (A), an instance-contained lexical logger (B), or a procedure lexical logger (C)? And, in general (forgetting it's a singleton), would you prefer A, B, or C (or any other) for your OO projects?

Thank you very much for your help.

--
our $Perl6 is Fantastic;

Replies are listed 'Best First'.
Re: Log::Log4perl use strategies
by rodion (Chaplain) on May 09, 2006 at 12:36 UTC
    Others may have technical reasons for preferring one over the other, but for me the differences are primarily in clarity and esthetics. (A) is more concise and thus the logging does not clutter the main flow of code as much. I also expect logging to be a global resource, at some level, so I wouldn't be looking for logging connected to each instance. If I found it in each instance, as in (B), I'd then be on the lookout for some specific purpose that made instance logging necessary. (I'd be mildly uncertain about my understanding of the code if I never found one, and mildly annoyed if I found that there definitely was no specific purpose.)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://548168]
Approved by wfsp
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-03-19 02:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found