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

Hello PerlMonks,

I am implementing perl logging using Log4perl. As part of the input to a config file, the user provides the log level (Debug,Info,Warn,Error,Fatal). Depending on this, the log level is set on the log handler($DEBUG,$INFO,$WARN,$ERROR,$FATAL).

Mentioned below is a prototype of the code. I get the following error when i assign "$loglev" to the log handler "$logger->level($loglev)" - "invalid level '$INFO' at line 19".

Is '$INFO' equivalent to $INFO?
#!/usr/software/bin/perl -w use Log::Log4perl qw(get_logger :levels); my $lev = "INFO"; my $loglev; if ($lev =~ /.*DEBUG.*/i){ $loglev = '$DEBUG'; }elsif($lev =~ /.*INFO.*/i){ $loglev = '$INFO'; }elsif($lev =~ /.*WARN.*/i){ $loglev = '$WARN'; }elsif($lev =~ /.*ERROR.*/i){ $loglev = '$ERROR'; }elsif($lev =~ /.*FATAL.*/i){ $loglev = '$FATAL'; }else{ die "\nPlease provide the correct log level\n"; } my $logger = get_logger(); $logger->level($loglev); # $DEBUG,$INFO,$WARN,$ERROR,$FATAL my $appender = Log::Log4perl::Appender->new( "Log::Dispatch::File", filename => "test.log", mode => "append", ); $logger->add_appender($appender); my $layout = Log::Log4perl::Layout::PatternLayout->new( "%d %p> %F{1}:%L %M - %m%n"); $appender->layout($layout); my $cnt = 100; if ($cnt == 100){ hit(); }else{ miss(); } sub hit { $logger->info("\nhit a century"); } sub miss{ $logger->error("\nDid not hit a century"); }

Replies are listed 'Best First'.
Re: Scalar variable value is name of a scalar variable
by dsheroh (Monsignor) on Jul 01, 2009 at 09:00 UTC
    Is '$INFO' equivalent to $INFO?

    No. '$INFO' is a string containing a dollar sign followed by the letters I, N, F, and O. It is a constant. $INFO is a variable named $INFO whose value can be just about anything (although, given the context, I expect it's probably an integer).

    While it is possible to do something like what you're talking about with soft references, that's bad ju-ju, so don't do it unless you enjoy ripping your hair out as you try to figure out how a variable which doesn't even appear in your code is getting modified.

    The better approach in this case would be to simply remove the quotes from your assignments. e.g., Use $loglev = $DEBUG; instead of $loglev = '$DEBUG'; (There are other, even better, options which don't involve if/elsif/elsif/... chains, but this one is the quickest and simplest to implement, given your posted code as a starting point.)

Re: Scalar variable value is name of a scalar variable
by citromatik (Curate) on Jul 01, 2009 at 08:48 UTC

    Symbolic references are very useful in some situations, you just have to be aware of not introducing bugs in your code while using them.

    Be aware that only package (global) variables are visible to symbolic references, and the use of global variables is error-prone.

    Also, the use of symbolic references results in a warning, you have to use no warnings 'ref' to avoid it, so be sure to deactivate them only in the innermost block of code where the symbolic reference is used

    That said, your code uses the symbolic reference on global variables and you are not using strict and you are not using warnings at all, so probably, you will not be bother by introducing a new error-prone feature


Re: Scalar variable value is name of a scalar variable
by perlpal (Scribe) on Jul 01, 2009 at 07:55 UTC
    I tried using symbolic references and it seems to work.

    Had to alter the logic a bit too.Is this implementation correct? I have read a few articles which advocate against using symbolic references.

    my $lev = "INFO"; $logger->level($$lev); # DEBUG,INFO,WARN,ERROR,FATAL

      No need to use symbolic references when you can use real references instead, and with less typing:

      if ($lev =~ /.*DEBUG.*/i){ $loglev = \$DEBUG; }elsif($lev =~ /.*INFO.*/i){ $loglev = \$INFO; }elsif($lev =~ /.*WARN.*/i){ $loglev = \$WARN; }elsif($lev =~ /.*ERROR.*/i){ $loglev = \$ERROR; }elsif($lev =~ /.*FATAL.*/i){ $loglev = \$FATAL; }else{ die "\nPlease provide the correct log level\n"; } my $logger = get_logger(); $logger->level($$loglev); # $DEBUG,$INFO,$WARN,$ERROR,$FATAL

      True laziness is hard work