Category: Debugging
Author/Contact Info chromatic
Description: Based on tye's suggestion in (tye)Re: Automatic Debugging, this prints out the name of all subroutines called. It respects can and doesn't interfere with AUTOLOAD. It could easily be modified to call your own custom logger and to handle multiple modules in the use line.

I kinda like it, and I could be persuaded to put it up on the CPAN if it's well-received.

You can test it out with the following code:

package Test; sub foo {} sub bar{} sub AUTOLOAD {} package main; use Devel::TraceMethods qw ( Test ); Test::foo(); Test::bar(); Test::blah(); if (UNIVERSAL::can('Test', 'foo')) { print "Can works!\n"; }
package Devel::TraceMethods;

use strict;

sub import {
    my ($package, $caller) = @_;

    my $src;
    {
        no strict 'refs';
        $src = \%{$caller . '::'};
    }
    
    foreach my $symbol (keys %$src) {
        my $sub;
        if (defined($sub = *{$src->{$symbol}}{CODE}) 
        and (defined(&$sub))) {
            undef $src->{$symbol};
            $src->{$symbol} = sub {
                logCall($symbol);
                return $sub->(@_);
            };
        }
    }
}

sub logCall {
    print STDERR "Executing $_[0]!\n";
}

1;
Replies are listed 'Best First'.
Re: An Implementation of Devel::TraceMethods
by grinder (Bishop) on May 30, 2001 at 14:28 UTC

    Funky stuff! My only suggestion would be to let the developer set his/her own callback, in case the default output isn't what's wanted (notably tracing to something other than STDERR). update: oh duh! which is exactly what you said in the comments.. Something like:

    use Carp qw/croak/; BEGIN { my $logger; sub callback { my $coderef = shift; croak "$coderef is not a code reference, cannot use as a callb +ack.\n" unless ref($coderef) eq 'CODE'; $logger = $coderef; } callback( sub { print STDERR "Executing $_[0]!\n" } ); sub logCall { &$logger( @_ ); } }

    This gives the following output (if the example script is changed as follows):

    Test::foo(); Devel::TraceMethods::callback( sub { print STDERR "called $_[0].\n" } +); Test::bar(); Test::blah(); __END__ gives: Executing foo! called bar. called AUTOLOAD. Can works!

    You would not believe how much I needed this code a couple of months ago....


    --
    g r i n d e r
(tye)Re: An Implementation of Devel::TraceMethods
by tye (Sage) on May 30, 2001 at 18:56 UTC

    Thanks for coding that up.

    Actually, what I had in mind is a bit more complicated so that it works in the face of inheritance and autoloading and uses goto so that its presence is less likely to be noticed.

    I also have some ideas on how to make it work when the module hasn't been loaded yet so you can do: perl -MDevel::MethodTrace=CGI script and get good trace w/o modifying any files.

            - tye (but my friends call me "Tye")
Re: An Implementation of Devel::TraceMethods
by clemburg (Curate) on May 30, 2001 at 12:11 UTC

    This should be uploaded to CPAN. Do it, chromatic.

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com