Posted on 2009-02-05 19:33:55-08 by balldarrens
CSPEC issue: lossing scope (or incorrect scope) in cspec subroutine.
I've attempted to add a global spec to my logging configuration, and it will not see the scope of which I would like it to.
If possible can anyone take a quick look at this and let me know if there is a way to do this?

The general premise of this is that I have a top level package that starts up my environment (in this case DBALL.pm).
Inisde of this library, I initialize and watch a standardized configuration file, in which any other libraries are added as categories.

I have a resource type of factory in this example of which returns a newly instantiated object (in this case DBALL::TESTOBJECT).
Inside of this object I have set attributes that I would like to be able to add to every log statement (I have done this via a cspec - of which is not acting like I would like it to).
The cspec override is stipulated inside of DBALL.pm, and I would like to reference the calling object (in this case DBALL::TESTOBJECT), but it sees self as something coming from Log::Log4perl::Layout::PatternLayout.

I've added a if routine to dump out caller to let me know who's calling the cspec, and it dumps that out for viewing.

If you are able, can you unzip this and run test.pl to see the output?

I will put them in line here as well, they are rudimentary, but they can reproduce my problem easily.

Any help that you can provide would be great.


The log configuration file:

<<<< ./logger.conf >>>>
log4perl.rootLogger = INFO, ScreenApp
log4perl.appender.ScreenApp= Log::Log4perl::Appender::Screen
log4perl.appender.ScreenApp.stderr = 0
log4perl.appender.ScreenApp.layout = PatternLayout
log4perl.appender.ScreenApp.layout.ConversionPattern = %d %-5p %-4L %M %U %m%n
log4perl.appender.ScreenApp.Threshold = TRACE
log4perl.logger.DBALL.RESOURCEFACTORY = INFO,ScreenApp
log4perl.logger.DBALL.TESTOBJECT = INFO, ScreenApp
log4perl.oneMessagePerAppender = 1
<<<< logger.conf >>>>


The test.pl file:

<<<< ./test.pl >>>>
#!/usr/bin/perl -w
use strict;
use DBALL;
my $object = DBALL::RESOURCEFACTORY->new();
print "DONE";
<<<<test.pl >>>>

<<<< ./DBALL.pm >>>>
package DBALL;

use lib "../DBALL";

use Module::Locate qw / locate /;
use File::Basename;
use Log::Log4perl;
use Data::Dumper;

BEGIN {
use Module::Locate qw / locate /;
my $location = locate __PACKAGE__;
my ($name,$path,$suffix) = fileparse($location,"\.pm");
my $logConf = $path . "logger.conf";
Log::Log4perl::Layout::PatternLayout::add_global_cspec( 'U',
sub {
if(defined($self->{id}) && defined($self->{mgmt_ip})){
return sprintf(" [%s:%s]", $self->{id}, $self->{mgmt_ip});
}else{
print Dumper(caller(0));
return " ERROR ";
}

} );
Log::Log4perl->init_and_watch($logConf, 3);
}
require DBALL::RESOURCEFACTORY;
1;
<<<< ./DBALL.pm >>>>


The resource factory file:

<<<< ./DBALL/RESOURCEFACTORY.pm >>>>
package DBALL::RESOURCEFACTORY;
use strict;
use Log::Log4perl;

use lib "./DBALL";

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw();


sub new {
my($class, $args) = @_;
my ($self, $factoryClass);
$self = bless {}, $class;
$self->{logger} = Log::Log4perl::get_logger($class);
$self->{logger}->info("RESOURCE FACTORY INSTANTIATED");
eval "require DBALL::TESTOBJECT";
return new DBALL::TESTOBJECT->new($args);
}
<<<< ./DBALL/RESOURCEFACTORY.pm >>>>

and finally the TESTOBJECT

<<<< ./DBALL/TESTOBJECT.pm >>>>
package DBALL::TESTOBJECT;
use strict;
use Log::Log4perl;

sub new {
my($class, $args) = @_;
my $self = bless {
attr1=>"hello",
attr2=>"world",
id => "TESTOBJECT",
mgmt_ip => "1.1.1.1",
logger => undef,
},$class;
$self->{logger} = Log::Log4perl::get_logger($class);
$self->{logger}->info("REF: " . ref($self));
$self->{logger}->info("CLASS: $class");
return $self;
}
1;
<<<< ./DBALL/TESTOBJECT.pm >>>>
Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.