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

I'm afraid that i am still having unresolved issues that i mentioned in this post. I have read documentation and consulted Q&A to no avail. Responses to my previous post were promising but do not seem to have gotten to the root of the problem. I'm quite prepared to kick myself as I have a feeling I've just been staring at this code for too long (almost 2 full days) without getting anywhere. Whatever wisdom you have to share, either in the form of a solution or more reading material would be much appreciated

The error I am getting is as follows:

Undefined subroutine &csDB::csErrorClass called at f:/projects/site/bin/lib//csDB.pm line 62, <$LOG> line 14.

However the csErrorClass subroutine is being exported from the included csLogs::Error module (It is in the @EXPORT array for said module, and is most definitely defined in said module). I cannot fathom why it is either a) failing to import properly, or b) failing to find the properly imported function.

The script I ran is ErrorLogParser.pl, which I run with perl -w on win32. The two calls to the offending module are marked by 'THIS LINE>'.

#------------------------------------- # PRAGMAS use lib 'f:/projects/site/bin/config/'; use strict; use utf8; #------------------------------------- # IN HOUSE MODULES use csConfig; use csLogsConfig qw( csErrorLog csLogMaster ); use csLogs::Error; use csLogs::Event; use csDB qw( QueryDB SafeQuote ); use csMail; #===================================================================== +================ my $entries = 0; my( %severities,%classes ) = (); if (-f &csErrorLog) # file exists and needs to be processed { my $tmp_logfile = csPath('logs').'/errors'.time().'.log'; my $LOG = undef; #--------------------------------- # renaming the file assures that the processing # this script does doesn't interfere with normal logging. ... rename and open the renamed file ... #--------------------------------- # process the entries <b>$entries = process_errorlog($LOG,\%severities,\%classes);</b> ... close and unlink temporary file, note that process ran success +fully ... } else # file doesn't exist and no processing was necessary { ... note that process ran but had nothing to do ... } ... email summary of results and end ... #===================================================================== +=========================== sub process_errorlog { my ($LOG,$count_severities,$count_classes) = @_; my $entries = 0; # track num of entries processed. my $state = 'none'; #state of the parser; my ( $time, $class, $severity, $message, $debug ) = (); #--------------------------------- # walk the file while( <$LOG> ) { /\[Error\]/ and do { if( $time ) # time gets set later in + the parsing... { #add to db; THIS LINE> QueryDB("insert into csEvents (Ti +me_Logged,Class,SubClass,Importance,Message,Info)". " values ('$time',1,$clas +s,$severity,".SafeQuote($message).",".SafeQuote($debug).")" ); $entries++; #reset variables; ( $time, $class, $severity, $mess +age, $debug ) = (); } $state = 'error'; next; }; ... more wholesome parsing goodness ... } # flush out last record if( $time ) { #add to db; THIS LINE> QueryDB("insert into csEvents (Time_Logged,Class,SubCla +ss,Importance,Message,Info)". " values ('$time',1,$class,$severity,".SafeQuote($mess +age).",".SafeQuote($debug).")" ); $entries++; } return $entries; } ... other subs ...

Here is the module csDB which is where the complaint is arising

#------------------------------------- # PACKAGE INFO package csDB; $VERSION = .6; use Exporter (); @ISA = qw(Exporter); @EXPORT_OK = qw(QueryDB SafeQuote SetLongLen GetLongLen $dbh); #------------------------------------- # PRAGMAS use lib 'f:/projects/site/bin/config/'; use strict; use utf8; #------------------------------------- # 3RD PARTY MODULES use DBI; #------------------------------------- # IN HOUSE MODULES use csConfig; use csLogs::Error; our $dbh; #===================================================================== +===================================== # Database Connection BEGIN { $dbh = DBI->connect(csDBAuth()) or &csDie( class=>&csErrorClass('SERVER_DATABASE'),severity=>&csError +Scale('CRITICAL'), message=>'Could not connect to database server', debug=>$DBI::errstr ); } END { $dbh->disconnect(); } #===================================================================== +===================================== # Basic query, returns a statement handle sub QueryDB { $dbh->{RaiseError}=0; $dbh->{PrintError}=0; my $qstring = $_[0]; my $dbquery= $dbh->prepare("$qstring") or &csDie( class=>&csErrorClass('CODE_DATABASE'),severity=>&csErrorSc +ale('SEVERE'), message=>'Database Query Preparation Error', debug=>$DBI::errstr."\n$qstring" ); $dbquery->execute or &csDie( class=>&csErrorClass('CODE_DATABASE'),severity=>&csErrorSc +ale('SEVERE'), message=>'Database Query Execution Error', debug=>$DBI::errstr."\n$qstring" ); $dbh->{RaiseError}=1; $dbh->{PrintError}=1; return ($dbquery); } ... more useful subs ... #---- 1;

and lastly here is csLogs::Error, which is where csErrorClass is being imported from

#------------------------------------- # PACKAGE INFO package Error; $VERSION = .3; use Exporter (); @ISA = qw(Exporter); @EXPORT = qw( csWarn csDie csErrorClass csErrorScale ErrorScaleName Er +rorClassName); #------------------------------------- # PRAGMAS use lib 'f:/projects/site/bin/config/'; use strict; use utf8; #------------------------------------- # IN HOUSE MODULES use csLogsConfig qw( csErrorLog ); #================================================== #Error Constants my %ErrorClasses = ( ... ); my %ErrorScale = ( ... ); #-------------------------------------------------- # Accessors sub csErrorClass { return $ErrorClasses{$_[0]}; } sub ErrorClassName { foreach my $key ( keys %ErrorClasses ) { return $key if $ErrorClasses{$key} == $_[0]; } return 'UNKNOWN'; } sub csErrorScale { return $ErrorScale{$_[0]}; } sub ErrorScaleName { foreach my $key ( keys %ErrorScale ) { return $key if $ErrorScale{$key} == $_[0]; } return 'UNKNOWN'; } #================================================== # Replacements for User-called warn and die ...where we define csWarn and csDie... #================================================== # Private Functions ... more yummy subs ... #================================================== #Overload SIGWARN and SIGDIE ... to behave like csWarn and csDie with default values, wrapped in BE +GIN ... #---- 1;

Replies are listed 'Best First'.
(tye)Re: Symbols not importing/exporting correctly
by tye (Sage) on May 03, 2001 at 19:26 UTC

    and lastly here is csLogs::Error, which is where csErrorClass is being imported from package Error;

    That needs to be package csLogs::Error.

            - tye (but my friends call me "Tye")
      Great, it works. Question: I was under the impression that by using something like csLogs::Error that while, yes, this specifies a specific namespace, that in use it simply helped specify which subdirectory the module should be found in from one of the @INC locations. Am I walking fine lines here?

      I think my old assumption is that Perl knew that csLogs::Error was the same namespace as Error if Error was in the csLogs directory.

        use csLogs::Error qw(a b) expands to:

        BEGIN { require csLogs::Error; import csLogs::Error qw(a b); }
        which expands to:
        BEGIN { require "csLogs/Error.pm"; csLogs::Error->import( qw(a b) ); }
        and that last line eventually becomes something like one of these:
        Exporter::import( "csLogs::Error", qw(a b) ); UNIVERSAL::import( "csLogs::Error", qw(a b) );
        So "csLogs::Error" is used both to find the Error.pm file and to find import(). So you need to get it right. Unfortunately, there is really no enforcement that the file csLogs/Error.pm defines a csLogs::Error::import() or sets @csLogs::Error::ISA= qw(Exporter) and @csLogs::Error::EXPORT.

        It would be nice if UNIVERSAL::import() complained about such things so you might find Universally unimportant and overused useful (and important).

                - tye (but my friends call me "Tye")