While working on an existing Perl package file, I would like to log the start/end of each method call (preferably without adding any new dependencies to the module). I've already added a rudimentary __dbg sub, which I'm fond of, like so...

our $DEBUG_LEVEL = 5; sub __dbg (&;$) { my ($code, $verbosity) = @_; if ($DEBUG_LEVEL >= ($verbosity // 1)) { my $msg = join('', $code->()); print STDERR "DEBUG: ", $msg, "\n" if length($msg); } } # ...the meat of the package is below...

I think I have been able to monkey-patch all the methods in the package, by adding the following to the bottom of the package file:

# ...the meat of the package is above... __dbg { no strict 'refs'; no warnings 'redefine'; my $package = __PACKAGE__; my %patched = ('__dbg' => 1); foreach (grep { defined &{"${package}::$_"} } keys %{"${package}:: +"}) { unless (exists $patched{$_}) { $patched{$_} = 1; __dbg { "Monkeypatching '${package}::$_' for tracing..." } + 5; my $fname = $_; my $fn = \&{"${package}::$_"}; *$_ = sub { __dbg { "Starting ${package}::${fname}(", join(',', @_ +), ')' } 4; my @ret = $fn->(@_); __dbg { "Ending ${package}::${fname} with return value +s: ", join(',', @ret) } 4; return unless defined(wantarray); return @ret if wantarray; return @ret[0] if scalar(@ret); } } } }; 1;

Now, whether this is a good thing to do or not (I promise to remove it at the end of the dev cycle), it seems to be working, but now I'm worried that my 'light-touch' profiling will actually have unintended side-effects on the subs it touches. For example:

  1. It warns on subs that have prototypes (e.g. Prototype mismatch: sub MyModule::method1 (&;$) vs none at /MyModule.pm line Y.), where Y is the closing brace to the unless (exists... block. I can suppress with no warnings 'prototype' but does that mean that the interpreter may no longer apply the syntactic distinctions that prototypes intend to provide?
  2. Even though I'm trying to reflect the requirements of the caller using wantarray, am I altering the results of wantarray in the actual wrapped call? Better to check wantarray first?
  3. I think it's also attaching to subs that are imported into the module (i.e. I don't think try, with or time are actually part of the package), but I can't see the 'best' way to exclude them
  4. (Also, it doesn't actually output the arguments, but I can't see the bug -- should I copy @_ to a local variable first (i.e. my @args = @_)?)

Any other wisdom to be shared here (bar the obvious "don't" and "use a cpan module")?


In reply to Monkey patching all subs with a basic 'starting subname' message by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.