The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

modify_debug_to_l4p.pl - Modify SPOPS 0.80 and earlier logging statements to use log4perl

SYNOPSIS

 $ cd /path/to/my/SPOPS/source
 $ perl modify_debug_to_l4p.pl

DESCRIPTION

This script modifies your .pm files to use Log4perl instead of the woefully inadequate SPOPS debugging. It probably won't get 100% of your debugging statements, but it will take care of the common cases and leave you to deal manually with the (hopefully) small handful of exceptions.

Configuration

You shouldn't need to do any configuration to make this work. That said...

Changing Directory Processed

By default it recursively processes all files ending in '.pm' in the current directory. To use a different directory pass it in on the command-line:

 # Use the current directory
 $ perl modify_debug_to_l4p.pl
 
 # Use another directory
 $ perl modify_debug_to_l4p.pl /path/to/other/source

Changing Files Processed

You can modify the files processed by changing the variable '$VALID_EXTENSION_RE' from:

 my $VALID_EXTENSION_RE = 'pm';

to something like:

 my $VALID_EXTENSION_RE = '(pm|pl|cgi)';

Changing Level Mapping

The old SPOPS debugging used numbers for logging levels, but log4perl uses names. (Much better!) We map the numbers to levels like this:

 0 => warn
 1 => info
 2 => debug
 3 => debug
 4 => debug
 5 => debug

So this:

 _w( 0, "Message goes here" );

will become:

 $log->warn( "Message goes here" );

and:

 _w( 1, "Other message goes here" );

will become:

 $log->is_info &&
     $log->info( "Other message goes here" );

You can change this by modifying the %LEVELS variable.

Note also that 'debug' and 'info' levels get the initial 'is_debug' or 'is_info' check, while 'warn', 'error' and 'fatal' do not.

What It Changes

Import statements

The import of the debugging constants is no longer needed, so:

 use SPOPS qw( _w DEBUG );

becomes:

 use SPOPS;

Most people won't even need the 'use', but we left it in just in case. (It won't hurt anything...)

What It Changes: Debugging Statements

This is where most of the work is done. The main cases are:

With _w and DEBUG

Change:

 DEBUG() && _w( 0, "This is my message (0)" );
 DEBUG() && _w( 1, "This is my message (1)" );
 DEBUG() && _w( 2, "This is my message (2)" );

to:

 $log->warn( "This is my message (0)" );
 $log->is_info &&
     $log->info( "This is my message (1)" );
 $log->is_debug &&
     $log->debug( "This is my message (2)" );

With _w

Change:

 _w( 0, "This is my message (0)" );
 _w( 1, "This is my message (1)" );
 _w( 2, "This is my message (2)" );

to:

 $log->warn( "This is my message (0)" );
 $log->is_info &&
     $log->info( "This is my message (1)" );
 $log->is_debug &&
     $log->debug( "This is my message (2)" );

With _wm and DEBUG

Note that we discard the comparison with the old variable:

Change:

 DEBUG() && _wm( 0, $LEVEL_VAR, "This is my message (0)" );
 DEBUG() && _wm( 1, $LEVEL_VAR, "This is my message (1)" );
 DEBUG() && _wm( 2, $LEVEL_VAR, "This is my message (2)" );

to:

 $log->warn( "This is my message (0)" );
 $log->is_info &&
     $log->info( "This is my message (1)" );
 $log->is_debug &&
     $log->debug( "This is my message (2)" );

With _wm

Note that we discard the comparison with the old variable:

Change:

 _wm( 0, $LEVEL_VAR, "This is my message (0)" );
 _wm( 1, $LEVEL_VAR, "This is my message (1)" );
 _wm( 2, $LEVEL_VAR, "This is my message (2)" );

to:

 $log->warn( "This is my message (0)" );
 $log->is_info &&
     $log->info( "This is my message (1)" );
 $log->is_debug &&
     $log->debug( "This is my message (2)" );

What It Adds

Log4perl include

We add a:

 use Log::Log4perl qw( get_logger );

somewhere after 'use strict' and 'use base'. If you care about alphabetizing your includes this might drive you crazy. Patches welcome.

Package-level logger

Taking the side of simplicity we didn't add a logger declaration in every scope we found the previous debugging statements in. Instead we just added:

 my $log = get_logger();

somewhere after the 'use' statements are done. This may cause problems with premature initialization of the logger, but hopefully in whatever scripts you're using SPOPS for you initialize the logger before initializing SPOPS. In fact you may want to change something like:

 use strict;
 use SPOPS::Initialize;
 ...
 sub runs_at_startup {
     my ( $class ) = @_;
     my %config = get_spops_config();
     SPOPS::Initialize->process({ config => \%config });
 }

to:

 use strict;
 use Log::Log4perl;
 ...
 sub runs_at_startup {
     my ( $class ) = @_;
     Log::Log4perl::init( '/path/to/my/log4perl.conf' );
     my %config = get_spops_config();
     require SPOPS::Initialize;
     SPOPS::Initialize->process({ config => \%config });
 }

SEE ALSO

Log::Log4perl

AUTHOR

Chris Winters <chris@cwinters.com>