|
NAMEDevel::TraceCalls - Track calls to subs, classes and object instancesSYNOPSIS## From the command line perl -d:TraceCalls=Subs,foo,bar script.pl ## Quick & dirty via use use Devel::TraceCalls { Package => "Foo" }; ## Procedural use Devel::TraceCalls; trace_calls qw( foo bar Foo::bar ); ## Explicitly named subs trace_calls { Subs => [qw( foo bar Foo::bar )], ...options... }; trace_calls { Package => "Foo", ## All subs in this package ...options... }; trace_calls { ## Just these subs Package => "Foo", ## Optional Subs => qw( foo, bar ), ...options... }; trace_calls $object; ## Just track this instance trace_calls { Objects => [ $obj1, $obj2 ]; ## Just track these instances ...options... }; ... time passes, sub calls happen ... my @calls = $t1->calls; ## retrieve what happned ## Object orented my $t = Devel::TraceCalls->new( ...parameters... ); undef $t; ## disable tracing ## Emitting additional messages: use Devel::TraceCalls qw( emit_trace_message ); emit_trace_message( "ouch!" ); DESCRIPTIONALPHA CODE ALERT. This module may change before "official" release".Devel::TraceCalls allows subroutine calls to be tracked on a per-subroutine, per-package, per-class, or per object instance basis. This can be quite useful when trying to figure out how some poor thing is being misused in a program you don't fully understand. Devel::TraceCalls works on subroutines and classes by installing wrapper subroutines and on objects by temporarily reblessing the objects in to specialized subclasses with "shim" methods. Such objects are reblessed back when the tracker is DESTROYed. The default action is to log the calls to STDERR. Passing in a "PreCall", or "PostCall" options disables this default behavior, you can reenable it by manually setting "<LogTo =" \*STDERR>>. There are 4 ways to specify what to trace.
Emitting messages if and only if Devel::TraceCalls is loadeduse constant _tracing => defined $Devel::TraceCalls::VERSION; BEGIN { eval "use Devel::TraceCalls qw( emit_trace_message )" if _tracing; } emit_trace_message( "hi!" ) if _tracing; Using the constant "_tracing" allows expressions like emit_trace_message(...) if _tracing; to be optimized away at compile time, resulting in little or no performance penalty. OPTIONSthere are several options that may be passed in the HASH ref style parameters in addition to the "Package", "Subs", "Objects" and "Class" settings covered above.
Captured Data FormatThe LogTo option can be used to log all data to an array instead of to a filehandle by passing it an array reference:LogTo => \@data, When passing in an array to capture call data (by using the "Calls" option), the elements will look like: { Name => "SubName", Self => "$obj", CallTime => $seconds, ## A float if Time::HiRes installed ReturnTime => $seconds, ## A float if Time::HiRes installed TraceDepth => $count, ## How deeply nested the trace is. WantArray => $wantarray_result, Result => [ "c" ], ## Dumped with Data::Dumper, if need be Exception => "$@", Args => [ "foo", ## A scalar was passed "{ a => 'b' }", ## A HASH (dumped with Data::Dumper) ... ], Stack => [ [ ... ], ## Results of caller(0). .... ## More frames if requested ], } NOTE: Many of these fields are optional and off by default. See the "OPTIONS" section for details. Tracing (via the "LogTo" parameter) enables several Capture options regardless of the passed-in settings. "Result" is an array of 0 or more elements. It will always be empty if the sub was called in void context ( WantArray => undef ). Note that "Self", "Args" and "Result" are converted to strings to avoid keeping references that might prevent things from being destroyed in a timely manner. Data::Dumper is used for "Args" and Result, plain stringification is used for Self.
Showing skipped tracesSometimes it's nice to see what you're missing. This can be helpful if you want to be sure that all the methods of a class are being logged for all instance, for instance.Set the environment variable "SHOWSKIPPED" to "yes" or calling "show_skipped_trace_points" to enable or disable this. To enable: Devel::TraceCalls::set_show_skipped_trace_points; Devel::TraceCalls::set_show_skipped_trace_points( 1 ); To disable: Devel::TraceCalls::set_show_skipped_trace_points( 0 ); Calling the subroutine overrides the environment variable. Showing the call stackTo show the call stack in the log at each trace point, set the environment variable "SHOWSTACK" to "yes" or calling "show_stack" to enable or disable this.To enable: Devel::TraceCalls::set_show_stack; Devel::TraceCalls::set_show_stack( 1 ); To disable: Devel::TraceCalls::set_show_stack( 0 ); Calling the subroutine overrides the environment variable. OO APIThe object oriented interface provides for more flexible than the other APIs. A tracer will remove all of it's trace points when it is deleted and you can add (and someday, remove) trace points from a running tracer.Someday you'll also be able to enable and disable tracers.
Using in other Devel:: modulesThe main advantage of the Devel:: namespace is that the "perl -d:Foo ..." syntax is pretty handy. Other modules which use this might want to be in the Devel:: namespace. The only trick is avoiding calling Devel::TraceCalls' import() routine when you do this (unless you want to for some reason).To do this, you can either carefully avoid placing "Devel::TraceCalls" in your Devel::* module's @ISA hierarchy or make sure that your module's "import()" method is called instead of "Devel::TraceCalls"'. If you do this, you'll need to have a "sub DB::DB" defined, because "Devel::TraceCalls"' wont be. See the source and the Devel::TraceSAX module for details. A Word on Devel::TraceCall OverheadMassive.Devel::TraceCall is a debugging aid and is designed to provide a lot of detail and flexibility. This comes at a price, namely overhead. One of the side effects of this overhead is that Devel::TraceCall is useless as a profiling tool, since a function that calls a number of other functions, all of them being traced, will see all of the overhead of Devel::TraceCall in its elapsed time. This could be worked around, but it is outside the scope of this module, see Devel::DProf for profiling needs. TODO
LIMITATIONSThere are several minor limitations.Exports a subroutine by default. Do a "use Devel::TraceCalls ();" to suppress that. If perl's optimized away constant functions, well, there is no call to trace. Because a wrapper subroutine gets installed in place of the original subroutine, anything that has cached a reference (with code like $foo = \&foo or $foo = Bar->can( "foo" )) will bypass the tracing. If a subroutine reference is taken while tracing is enabled and then used after tracing is disabled, it will refer to the wrapper subroutine that no longer has something to wrap. Devel::TraceCalls does not pass these through in that case, but it could. The import based "use Devel::TraceCalls { ... }" feature relies on a "CHECK" subroutine, which is not present on older perls. See perlmod for details. Doesn't warn if you point it at an empty class, or if you pass no subs. This is because you might be passing in a possibly empty list. Check the return value's subs method to count up how many overrides occured. PRIOR ARTSee Devel::TraceMethods and Aspect::Trace for similar functionality.Merlyn also suggested using Class::Prototyped to implement the instance subclassing, but it seems too simple to do without incurring a prerequisite module. A miscellany of tricky modules like Sub::Versive, Hook::LexWrap, and Sub::Uplevel. SEE ALSODevel::DProf for profiling, Devel::TraceSAX for an example of a client module.AUTHORBarrie Slaymaker <barries@slaysys.com> Maintainer from version 0.04 is Cosimo Streppone <cosimo@cpan.org> COPYRIGHTCopyright (c) 2002 Barrie Slaymaker, All Rights Reserved. You may use this module under the terms of the Artistic License or the GPL, any version. POD ERRORSHey! The above document had some coding errors, which are explained below:
Visit the GSP FreeBSD Man Page Interface. |