File Coverage

blib/lib/Devel/TraceCalls.pm
Criterion Covered Total %
statement 328 428 76.6
branch 139 250 55.6
condition 58 114 50.8
subroutine 33 40 82.5
pod 4 12 33.3
total 562 844 66.5


line stmt bran cond sub pod time code
1             package Devel::TraceCalls;
2              
3             =head1 NAME
4              
5             Devel::TraceCalls - Track calls to subs, classes and object instances
6              
7             =head1 SYNOPSIS
8              
9             ## From the command line
10             perl -d:TraceCalls=Subs,foo,bar script.pl
11              
12             ## Quick & dirty via use
13             use Devel::TraceCalls { Package => "Foo" };
14              
15             ## Procedural
16             use Devel::TraceCalls;
17              
18             trace_calls qw( foo bar Foo::bar ); ## Explicitly named subs
19              
20             trace_calls {
21             Subs => [qw( foo bar Foo::bar )],
22             ...options...
23             };
24              
25             trace_calls {
26             Package => "Foo", ## All subs in this package
27             ...options...
28             };
29              
30             trace_calls { ## Just these subs
31             Package => "Foo", ## Optional
32             Subs => qw( foo, bar ),
33             ...options...
34             };
35              
36             trace_calls $object; ## Just track this instance
37              
38             trace_calls {
39             Objects => [ $obj1, $obj2 ]; ## Just track these instances
40             ...options...
41             };
42              
43             ... time passes, sub calls happen ...
44              
45             my @calls = $t1->calls; ## retrieve what happned
46              
47             ## Object orented
48             my $t = Devel::TraceCalls->new( ...parameters... );
49              
50             undef $t; ## disable tracing
51              
52             ## Emitting additional messages:
53             use Devel::TraceCalls qw( emit_trace_message );
54              
55             emit_trace_message( "ouch!" );
56              
57             =head1 DESCRIPTION
58              
59             B.
60              
61             Devel::TraceCalls allows subroutine calls to be tracked on a per-subroutine,
62             per-package, per-class, or per object instance basis. This can be quite useful
63             when trying to figure out how some poor thing is being misused in a program you
64             don't fully understand.
65              
66             Devel::TraceCalls works on subroutines and classes by installing wrapper
67             subroutines and on objects by temporarily reblessing the objects in to
68             specialized subclasses with "shim" methods. Such objects are reblessed back
69             when the tracker is DESTROYed.
70              
71             The default action is to log the calls to STDERR. Passing in a C, or
72             C options disables this default behavior, you can reenable it
73             by manually setting C< \*STDERR>>.
74              
75             There are 4 ways to specify what to trace.
76              
77             =over
78              
79             =item 1
80              
81             By Explicit Sub Name
82              
83             trace_calls "foo", "bar"; ## trace to STDOUT.
84            
85             trace_calls {
86             Subs => [ "foo", "bar" ],
87             ...options...
88             };
89              
90             The first form enables tracking with all Capture options enabled (other than
91             CaptureSelf which has no effect when capturing plain subs). The second allows
92             you to control the options.
93              
94             =item 2
95              
96             By Package Name
97              
98             trace_calls {
99             Package => "My::Module",
100             ...options...
101             };
102              
103             # Multiple package names
104             trace_calls {
105             Package => [ "My::Module", "Another::Module" ],
106             ...options...
107             };
108              
109             trace_calls {
110             Package => "My::Module",
111             Subs => [ "foo", "bar" ],
112             ...options...
113             };
114              
115             This allows you to provide a package prefix for subroutine names
116             to be tracked. If no "Subs" option is provided, all subroutines
117             in the package will be tracked.
118              
119             This does not examine @ISA like the C and C (covered
120             next) techniques do.
121              
122             =item 3
123              
124             By Class Name
125              
126             trace_calls {
127             Class => "My::Class",
128             ...options...
129             };
130              
131             trace_calls {
132             Class => "My::Class",
133             ...options...
134             };
135              
136             trace_calls {
137             Class => "My::Class",
138             Subs => [ "foo", "bar" ],
139             ...options...
140             };
141              
142             This allows tracking of method calls (or things that look like method
143             calls) for a class and it's base classes. The $self ($_[0]) will not be
144             captured in C (see L), but may be captured
145             in C if C is enabled.
146              
147             C can't differentiate between C<$obj->foo( ... )> and
148             C, which can lead to extra calls being tracked if the
149             latter form is used. The good news is that this means that idioms like:
150              
151             $meth = $obj->can( "foo" );
152             $meth->( $obj, ... ) if $meth;
153              
154             are captured.
155              
156             If a C parameter is provided, only the named methods will be
157             tracked. Otherwise all subs in the class and in all parent classes are
158             tracked.
159              
160             =item 3
161              
162             By Object Instance
163              
164             trace_calls $obj1, $obj2;
165              
166             trace_calls {
167             Objects => [ $obj1, $obj2 ],
168             ...options...
169             };
170              
171             trace_calls {
172             Objects => [ $obj1, $obj2 ],
173             Subs => [ "foo", "bar" ],
174             ...options...
175             };
176              
177             This allows tracking of method calls (or things that look like method
178             calls) for specific instances. The $self ($_[0]) will not be captured
179             in C, but may be captured in Self if CaptureSelf is enabled.
180              
181             The first form (C) enables all capture options,
182             including CaptureSelf.
183              
184             =back
185              
186             =head2 Emitting messages if and only if Devel::TraceCalls is loaded
187              
188             use constant _tracing => defined $Devel::TraceCalls::VERSION;
189              
190             BEGIN {
191             eval "use Devel::TraceCalls qw( emit_trace_message )"
192             if _tracing;
193             }
194              
195             emit_trace_message( "hi!" ) if _tracing;
196              
197             Using the constant C<_tracing> allows expressions like
198              
199             emit_trace_message(...) if _tracing;
200              
201             to be optimized away at compile time, resulting in little or
202             no performance penalty.
203              
204             =head1 OPTIONS
205              
206             there are several options that may be passed in the HASH ref style
207             parameters in addition to the C, C, C and
208             C settings covered above.
209              
210             =over
211              
212             =item LogTo
213              
214             LogTo => \*FOO,
215             LogTo => \@array,
216             LogTo => undef,
217              
218             Setting this to a filehandle causes tracing messages to be emitted to
219             that filehandle. This is set to STDERR by default if no PreCall or
220             PostCall intercepts are given. It may be set to undef to suppress
221             tracing if you need to.
222              
223             Setting this to an ARRAY reference allows call data to be captured,
224             see below for more details.
225              
226             =item LogFormatter
227              
228             This is not supported yet, the API will be changing.
229              
230             But, it allows you some small control over how the parameters list
231             gets traced when LogTo points to a filehandle.
232              
233             =item ShowStack
234              
235             Setting this causes the call stack to be logged.
236              
237             =item PreCall
238              
239             PreCall => \&sub_to_call_before_calling_the_target,
240              
241             A reference to a subroutine to call before calling the target sub. This
242             will be passed a reference to the data captured before the call and
243             a reference to the options passed in when defining the trace point
244             (this does not contain the C, C, C and
245             C settings.
246              
247             The parameters are:
248              
249             ( $trace_point, $captured_data, $params )
250              
251             =item PostCall
252              
253             PreCall => \&sub_to_call_after_calling_the_target,
254              
255             ( $trace_point, $captured_data, $params )
256              
257             A reference to a subroutine to call after calling the target sub. This
258             will be passed a reference to the data captured before and after the call and
259             a reference to the options passed in when defining the trace point
260             (this does not contain the C, C, C and
261             C settings.
262              
263             The parameters are:
264              
265             ( $trace_point, $captured_data, $params )
266              
267             =item Wrapper
268              
269             B
270              
271             Wrapper => \&sub_to_delegate_the_target_call_to,
272              
273             A reference to a subroutine that will be called instead of calling
274             the target sub. The parameters are:
275              
276             ( $code_ref, $trace_point, $captured_data, $params )
277              
278             =item Data Capture Options
279              
280             These options affect the data captured in the C array (see L
281             Calls ARRAY>) and passed to the C and C handlers.
282              
283             Options may be added to the hash refs passed to C. Here are
284             the options and their default values (all defaults chosen to minimize
285             overhead):
286              
287             CaptureStack => 0,
288             CaptureCallTimes => 0,
289             CaptureReturnTimes => 0,
290             CaptureSelf => 0,
291             CaptureArgs => 0,
292             CaptureResult => 0,
293              
294             CaptureAll => 0, ## Shorthand for setting all of the others
295              
296             Is CaptureStack is true, the
297              
298             StackCaptureDepth => 1_000_000,
299              
300             option controls the maximum number of stack frames that will be captured.
301             Set this to "1" to capture just a single stack frame (equiv. to caller 0).
302              
303             =back
304              
305             =head1 Captured Data Format
306              
307             The LogTo option can be used to log all data to an array instead of
308             to a filehandle by passing it an array reference:
309              
310             LogTo => \@data,
311              
312             When passing in an array to capture call data (by using the C
313             option), the elements will look like:
314              
315             {
316             Name => "SubName",
317             Self => "$obj",
318             CallTime => $seconds, ## A float if Time::HiRes installed
319             ReturnTime => $seconds, ## A float if Time::HiRes installed
320             TraceDepth => $count, ## How deeply nested the trace is.
321             WantArray => $wantarray_result,
322             Result => [ "c" ], ## Dumped with Data::Dumper, if need be
323             Exception => "$@",
324             Args => [
325             "foo", ## A scalar was passed
326             "{ a => 'b' }", ## A HASH (dumped with Data::Dumper)
327             ...
328             ],
329             Stack => [
330             [ ... ], ## Results of caller(0).
331             .... ## More frames if requested
332             ],
333             }
334              
335             NOTE: Many of these fields are optional and off by default. See
336             the L section for details. Tracing (via the C
337             parameter) enables several Capture options regardless of the
338             passed-in settings.
339              
340             C is an array of 0 or more elements. It will always be empty if
341             the sub was called in void context ( WantArray => undef ).
342              
343             Note that C, C and C are converted to strings
344             to avoid keeping references that might prevent things from being
345             destroyed in a timely manner. Data::Dumper is used for C and
346             Result, plain stringification is used for Self.
347              
348             =cut
349              
350             $VERSION = 0.04;
351              
352             @ISA = qw( Exporter );
353             @EXPORT = qw( trace_calls );
354             %EXPORT_TAGS = ( all => \@EXPORT );
355              
356 5     5   51352 use strict;
  5         12  
  5         206  
357 5     5   27 use Exporter;
  5         11  
  5         173  
358              
359 5     5   30 use Carp ();
  5         14  
  5         85  
360 5     5   6602 use Data::Dumper;
  5         65698  
  5         433  
361 5     5   5217 use UNIVERSAL;
  5         68  
  5         28  
362              
363             sub debugging() { 0 }
364             sub debugging_caller() { 0 }
365              
366 5     5   642 BEGIN { eval "use Time::HiRes qw( time )" }
  5     5   6415  
  5         13426  
  5         24  
367              
368             my @trace_after_compile;
369             CHECK {
370 5 100   5   19230 return unless @trace_after_compile;
371 1         7 trace_calls( @trace_after_compile );
372             }
373              
374             ##
375             ## Camouflage the call stack., kinda like Sub::Uplevel
376             ##
377             ## When reading this, it helps to see a "raw" call stack:
378             ##
379             ## +------+-----------------+----------------------------+----+----------------------------+-----+---------+---------+----------+-----+------------+
380             ## |height|package |file |line|subroutine |has |wantarray|eval text|is_require|hints|bitmask |
381             ## | | | | | |args | | | | | |
382             ## |0 |main |(eval 3) |9 |Devel::TraceCalls::__ANON__ |1 |0 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
383             ## |1 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |main::stack |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
384             ## |2 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |(eval) |0 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
385             ## |3 |Devel::TraceCalls|(eval 5) |2 |Devel::TraceCalls::_call_sub|1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
386             ## |4 |main |(eval 3) |32 |Devel::TraceCalls::__ANON__ |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
387             ## |5 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |main::dive |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
388             ## |6 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |(eval) |0 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
389             ## |7 |Devel::TraceCalls|(eval 4) |2 |Devel::TraceCalls::_call_sub|1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
390             ## |8 |main |(eval 3) |32 |Devel::TraceCalls::__ANON__ |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
391             ## |9 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |main::dive |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
392             ## |10 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |(eval) |0 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
393             ## |11 |Devel::TraceCalls|(eval 4) |2 |Devel::TraceCalls::_call_sub|1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
394             ## |12 |main |(eval 3) |32 |Devel::TraceCalls::__ANON__ |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
395             ## |13 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |main::dive |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
396             ## |14 |Devel::TraceCalls|blib/lib/Devel/TraceCalls.pm|529 |(eval) |0 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
397             ## |15 |Devel::TraceCalls|(eval 4) |2 |Devel::TraceCalls::_call_sub|1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
398             ## |16 |main |t/caller.t |79 |Devel::TraceCalls::__ANON__ |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
399             ## |17 |main |t/caller.t |96 |main::check_stack |1 |1 |<>|<> |0 |^@^@^@^@^@^@^@^@^@^@^@^@|
400             ## |18 |main |t/caller.t |96 |main::BEGIN |1 |0 |<>|<> |2 |^@^@^@^@^@^@^@^@^@^@^@^@|
401             ## |19 |main |t/caller.t |96 |(eval) |0 |0 |<>|<> |2 |^@^@^@^@^@^@^@^@^@^@^@^@|
402             ## +------+-----------------+----------------------------+----+----------------------------+-----+---------+---------+----------+-----+------------+
403             ##
404             ## Not sure why the Devel::TraceCalls::__ANON__ is showing up in column 3, but
405             ## there's extra logic below to deal with it. Sub::Uplevel does not have this
406             ## issue.
407             ##
408              
409 5     5   1424 use vars qw( $show_all );
  5         10  
  5         1735  
410              
411 0     0 0 0 sub carp { local $show_all = 1; &Carp::carp }
  0         0  
412 4     4 0 5 sub croak { local $show_all = 1; &Carp::croak }
  4         52  
413 0     0 0 0 sub confess{ local $show_all = 1; &Carp::confess }
  0         0  
414 0     0 0 0 sub cluck { local $show_all = 1; &Carp::cluck }
  0         0  
415              
416             my %hide_packages;
417              
418             =item hide_package
419              
420             Devel::TraceCalls::hide_package;
421             Devel::TraceCalls::hide_package $pkg;
422              
423             Tells Deve::TraceCalls to ignore stack frames with caller eq $pkg.
424             The caller's package is used by default. This is useful when overloading
425             require().
426              
427             =cut
428              
429             sub hide_package {
430 5 50   5 1 31 my $pkg = @_ ? shift : caller;
431 5         17 ++$hide_packages{$pkg};
432             }
433              
434             =item unhide_package
435              
436             Devel::TraceCalls::unhide_package;
437             Devel::TraceCalls::unhide_package $pkg;
438              
439             Undoes the last hide_package. These calls nest, so
440              
441             Devel::TraceCalls::hide_package;
442             Devel::TraceCalls::hide_package;
443             Devel::TraceCalls::unhide_package;
444              
445             leaves the caller's package hidden.
446              
447             =cut
448              
449             sub unhide_package {
450 0 0   0 1 0 my $pkg = @_ ? shift : caller;
451 0 0       0 --$hide_packages{$pkg} if $hide_packages{$pkg};
452             }
453              
454             hide_package;
455              
456             BEGIN {
457 5     5   32 use vars qw( $in_caller );
  5         10  
  5         3134  
458              
459             *CORE::GLOBAL::caller = sub {
460 120 50   120   4496 if ( $in_caller ) {
461             ## This is only needed when something called in here
462             ## (Text::Formatter when I break it, for instance) call caller.
463 0         0 warn "Not recursing in caller()";
464 0         0 return ();
465             }
466              
467 120         164 local $in_caller = 1;
468 120   100     413 my $d = $_[0] || 0;
469 120         128 my @rows;
470              
471 120         109 if ( debugging_caller ) {
472             my $j= 0;
473             while (1) {
474             my @d = CORE::caller $j ;
475             last unless @d ;
476             push @rows, [ "", "xxx", map defined $_ ? $_ : "<>", $j, @d ];
477             ++$j;
478             }
479             }
480              
481 120         114 $rows[0]->[0] = "---"
482             if debugging_caller;
483              
484 120         131 my $i = 1;
485 120         125 my $h = 0;
486 120         123 my @caller;
487             my $callee;
488              
489 120         116 warn "hide_packages = (", join( ", ", keys %hide_packages ), ")\n"
490             if debugging_caller;
491              
492 120         249 while ( $h <= $d ) {
493 601         2850 my @c = CORE::caller $i;
494              
495 601 100       1387 unless ( @c ) {
496 6         13 @caller = @c;
497 6         13 last;
498             }
499              
500 595 100 66     2964 if ( @c && exists $hide_packages{$c[0]} && ! $show_all ) {
      100        
501             ## We need to set the fields in @caller that refer to the callee
502             ## and not count this frame.
503 195 100       383 $callee = $c[3] unless defined $callee;
504 195         210 $rows[$i]->[0] = "---"
505             if debugging_caller;
506             }
507             else {
508             ## We need to return this frame verbatim
509 400         1229 @caller = @c;
510 400 100 66     1522 if ( @caller && defined $callee ) {
511 82         118 $caller[3] = $callee;
512 82         100 $callee = undef;
513             }
514 400         465 ++$h;
515             }
516 595         602 $rows[$i]->[1] = $d
517             if debugging_caller;
518 595         1709 ++$i;
519             }
520              
521 120         125 if ( debugging_caller ) {
522             require Text::FormatTable;
523             my $t = Text::FormatTable->new( "|l|r|r|l|l|r|l|r|r|l|r|r|r|");
524             $t->rule( "-" );
525             $t->head( "del", "eff_height", "height", "package", "file", "line", "subroutine", "has_args", "wantarray", "eval_text", "is_require", "hints", "bitmask" );
526             $t->rule( "-" );
527             $t->row( @$_ ) for @rows;
528             $t->rule( "-" );
529             warn $t->render;
530             }
531              
532 120 100       1566 ! wantarray ? $caller[0] ## Scalar context
    100          
533             : ! @_ ? @caller[0..2] ## list context, no args
534             : @caller; ## list context with args
535 5     5   148 };
536             }
537              
538             ## Being lazy about installing this sub allows other Devel:: modules to
539             ## use this module.
540 5     5   30 use vars qw( @db_args );
  5         48  
  5         3661  
541             my $DB_DB = <<'DB_DB_END';
542             my $initted;
543              
544             sub DB::DB {
545             return if $initted;
546             $initted = 1;
547              
548             ## TODO: correct this message.
549             die qq{No parameters passed to -d. Need something like "-d:TraceCalls { Subs => [qw(...)] }" (including the quotes)\n}
550             unless @db_args;
551             trace_calls( @db_args );
552             }
553             DB_DB_END
554              
555              
556             sub import {
557 5     5   52 my $self = shift;
558             ## line 0 seems to indicate that we're in -M or -D land.
559 5 50       21 if ( ! (caller(0))[2] ) {
560 0         0 push @db_args, @_;
561 0 0       0 eval $DB_DB if $DB_DB;
562 0         0 undef $DB_DB;
563 0         0 return;
564             }
565              
566             @_ = (
567 1         24 $self,
568             grep {
569 5         20 my $is_ref = ref;
570 1 50 33     24 push @trace_after_compile, {
    50          
571             exists $_->{Subs}
572             && ! exists $_->{Package}
573             && ! exists $_->{Class}
574             && ! exists $_->{Objects}
575             ? ( Package => scalar caller )
576             : (),
577             %$_,
578             } if $is_ref;
579 1 50       21 $is_ref ? () : $_;
580             } @_
581             );
582              
583 5         395 goto &Exporter::import;
584             }
585              
586             =head1 Showing skipped traces
587              
588             Sometimes it's nice to see what you're missing. This can be helpful
589             if you want to be sure that all the methods of a class are being
590             logged for all instance, for instance.
591              
592             Set the environment variable C to "yes" or calling
593             C to enable or disable this.
594              
595             To enable:
596              
597             Devel::TraceCalls::set_show_skipped_trace_points;
598             Devel::TraceCalls::set_show_skipped_trace_points( 1 );
599              
600             To disable:
601              
602             Devel::TraceCalls::set_show_skipped_trace_points( 0 );
603              
604             Calling the subroutine overrides the environment variable.
605              
606             =cut
607              
608             my $show_skipped_trace_points = $ENV{SHOWSKIPPED};
609              
610             sub set_show_skipped_trace_points {
611 0 0   0 0 0 $show_skipped_trace_points = @_ ? shift : 1;
612             }
613              
614             =head1 Showing the call stack
615              
616             To show the call stack in the log at each trace point, set the environment
617             variable C to "yes" or calling C to enable or
618             disable this.
619              
620             To enable:
621              
622             Devel::TraceCalls::set_show_stack;
623             Devel::TraceCalls::set_show_stack( 1 );
624              
625             To disable:
626              
627             Devel::TraceCalls::set_show_stack( 0 );
628              
629             Calling the subroutine overrides the environment variable.
630              
631             =cut
632              
633             my $show_stack = $ENV{SHOWSTACK};
634              
635              
636             ## This is not documented or supported, it needs to be made better,
637             ## 'My::Class::Name' should be made to look like \(My::Class::Name)
638             ## or something and the depth at which it kicks in needs to be
639             ## controllable.
640             my $stringify_blessed_refs = $ENV{STRINGIFY};
641              
642             sub set_stringify_blessed_refs {
643 0 0   0 0 0 $stringify_blessed_refs = @_ ? shift : 1;
644             }
645              
646             my %builtin_types = map { ( $_ => undef ) } qw(
647             SCALAR
648             ARRAY
649             Regexp
650             REF
651             HASH
652             CODE
653             );
654              
655             sub _stringify_blessed_refs {
656 0     0   0 my $s = shift;
657 0         0 my $type = ref $s;
658              
659 0 0 0     0 return $s if ! $type || $type eq "Regexp" ;
660              
661 0 0       0 if ( $type eq "HASH" ) {
    0          
    0          
    0          
662 0         0 $s = {
663             map {
664 0         0 ( $_ => _stringify_blessed_refs( $s->{$_} ) );
665             } keys %$s
666             };
667             }
668             elsif ( $type eq "ARRAY" ) {
669 0         0 $s = [ map _stringify_blessed_refs( $_ ), @$s ];
670             }
671             elsif( $type eq "Regexp" ) {
672 0         0 $s = "$s";
673             }
674             elsif ( !exists $builtin_types{$type} ) {
675             ## A blessed ref...
676 0         0 $s = $type;
677             }
678              
679 0         0 return $s;
680             }
681              
682              
683             ##
684             ## %trace_points is the master registry of all active trace points.
685             ##
686             ## It is keyed on sub name and contains / refers to HASHes that
687             ## contain the Name and Ref of the original subroutine (for logging and
688             ## calling purposes, respectively) and an ARRAY of all of the trace points
689             ## active for that subroutine.
690             ##
691             my %trace_points;
692              
693             ##
694             ## This is the wrapper subroutine used when tracing a sub or a class's methods.
695             ## It's not used when tracing an object instance, see below for that.
696             ##
697 5     5   33 use vars qw( $nesting_level );
  5         19  
  5         15465  
698             $nesting_level = 0;
699              
700             sub _call_sub {
701 22     22   45 my $sub_id = shift;
702              
703 22         35 my $context = wantarray;
704 22         63 my @result;
705              
706 22         36 local $Data::Dumper::Indent = 1;
707 22         34 local $Data::Dumper::Terse = 1;
708 22         32 local $Data::Dumper::Quotekeys = 0;
709              
710             ## use local on this one just in case some exception happens,
711             ## or an "exiting subroutine via next" kinda thing.
712 22         32 local $nesting_level = $nesting_level + 1;
713              
714 22 50       113 confess unless defined $trace_points{$sub_id}->{TracePoints};
715              
716 22         45 my $sub_name = $trace_points{$sub_id}->{Name};
717 22         37 my $sub_ref = $trace_points{$sub_id}->{Ref};
718 22         28 my @trace_points = @{$trace_points{$sub_id}->{TracePoints}};
  22         60  
719 22         30 my @r;
720              
721 22         69 warn "tracing $sub_name\n" if debugging;
722              
723 22         28 my $record_call_time;
724             my $record_return_time;
725              
726 0         0 my $log_formatter;
727              
728 26         97 my @tps = grep {
729 22         35 my $is_instance_method = exists $_->{_TraceInstance};
730 26         45 my $is_class_method = exists $_->{_TraceClasses};
731              
732 5         36 ( ! $is_instance_method || @_ && $_->{_TraceInstance} == $_[0] )
733             && ( ! $is_class_method
734             || ( @_
735 26 100 66     208 && grep UNIVERSAL::isa( $_[0], $_ ), keys %{$_->{_TraceClasses}}
      66        
      66        
      66        
736             )
737             );
738             } @trace_points;
739              
740              
741 22 50 66     70 if ( ! @tps && $show_skipped_trace_points ) {
742             ## Sometimes it's nice to see what you're missing
743 0         0 push @tps, {
744             _Signature => "MISSING",
745             LogTo => \*STDERR,
746             };
747             }
748              
749 22         94 my %master_r = (
750             Name => $sub_name,
751             TraceDepth => $nesting_level,
752             WantArray => $context,
753             );
754              
755 22         40 my %log_to;
756             my $params_cache;
757              
758 22 100       53 --$nesting_level unless @tps;
759              
760 22         37 for my $tp ( @tps ) {
761 23         124 my %r = %master_r;
762              
763 23         31 warn "...to tracepoint $tp->{_Signature}\n"
764             if debugging;
765              
766 23   100     1301 my $is_method = exists $tp->{_TraceInstance}
767             || exists $tp->{_TraceClasses};
768              
769 23         45 $r{LooksLikeAMethod} = $is_method;
770              
771 23   66     103 $record_call_time ||= $tp->{CaptureCallTime};
772 23   66     119 $record_return_time ||= $tp->{CaptureReturnTime};
773              
774 15 50       57 $r{Args} = [
775             @{
776 23 50 66     116 $params_cache ||= [
777             map {
778 23 100 100     142 my $d = Dumper(
779             $stringify_blessed_refs
780             ? _stringify_blessed_refs $_
781             : $_
782             );
783 15         3661 chomp $d;
784 15         81 $d;
785             } $is_method
786             ? @_[1..$#_]
787             : @_
788             ]
789             }
790             ] if $tp->{CaptureArgs} || $tp->{LogTo};
791              
792 23 50 33     113 $r{Self} = "$_[0]"
      66        
793             if $is_method && ( $tp->{CaptureSelf} || $tp->{LogTo} ) ;
794              
795             ## Doing this for each $r instead of caching them for a couple
796             ## of reasons: code simplicity, multiple traces on a func should
797             ## be rare, and we'd need to copy them anyway to give each $r it's
798             ## own copy so that changing one can't change the others, and
799             ## different trace points can go to different stack depths.
800 23 50 66     237 if ( $tp->{CaptureStack} || $tp->{ShowStack} || $show_stack ) {
      66        
801 2   50     18 for ( 1..( $tp->{StackCaptureDepth} || 1_000_000 ) ) {
802 4         7 my @c = caller( $_ );
803 4 100       9 last unless @c;
804 2         3 push @{$r{Stack}}, \@c;
  2         7  
805             }
806             }
807              
808 23         42 push @r, \%r;
809              
810 23 50       115 $tp->{PreCall}->( \%r, \@_ ) if $tp->{PreCall};
811              
812             ##
813             ## Logging
814             ##
815 23 50       58 if ( $tp->{LogTo} ) {
816 23 100       65 if ( ref $tp->{LogTo} eq "ARRAY" ) {
817 13         19 push @{$tp->{LogTo}}, \%r;
  13         47  
818             }
819             else {
820 10         11 my $msg;
821 10 50       25 $msg = $tp->{LogFormatter}->( $tp, \%r, \@_ )
822             if $tp->{LogFormatter};
823              
824 10         14 my %l;
825 10 50       24 if ( ref $msg eq "HASH" ) {
826 0         0 %l = %$msg;
827 0         0 $msg = undef;
828             }
829              
830 10 50       30 if ( ! defined $msg ) {
831             ## Shorten the subname if possible
832 10         16 my $sub_name = $r{Name};
833 10 50       35 if ( $r{LooksLikeAMethod} ) {
834 0         0 my $object_id = $r{Self};
835 0         0 my $sub_name_prefix = $sub_name;
836 0         0 $sub_name_prefix =~ s/::[^:]*$//;
837 0 0 0     0 if ( length( $object_id ) > length( $sub_name_prefix )
838             && index( $object_id, $sub_name_prefix ) == 0
839             ) {
840 0         0 $sub_name =~ s/.*://;
841             }
842             }
843              
844             $l{Object} =
845 10 0 0     53 exists $tp->{ObjectId} && defined $tp->{ObjectId}
    50 33        
846             ? $tp->{ObjectId} . "->"
847             : $r{Self} . "->"
848             if ! defined $l{Object} && $r{LooksLikeAMethod};
849              
850 10 50       39 $l{Sub} = $sub_name
851             if ! defined $l{Sub};
852              
853 10 50       23 if ( ! defined $l{Args} ) {
    0          
854             ## get the dumped args list out of %r
855 10         24 $l{Args} = $r{Args};
856             }
857             elsif ( ref $l{Args} ) {
858             ## dump it, just like $r{Args} was.
859 0         0 $l{Args} = [
860             map {
861 0         0 my $d = Dumper( $_ );
862 0         0 chomp $d;
863 0         0 $d;
864             } $is_method
865 0         0 ? @{$l{Args}}[1..$#{$l{Args}}]
  0         0  
866 0 0       0 : @{$l{Args}}
867             ];
868             }
869              
870 10         34 $l{Args} = join( "",
871             "(",
872 10         23 @{$l{Args}} ? " " : (),
873 10         46 join( ", ", @{$l{Args}} ),
874 10 100       38 @{$l{Args}} ? " " : (),
    100          
    50          
875             ")",
876             ) if ref $l{Args};
877              
878 10   50     128 $msg = join( "",
      50        
      50        
      50        
      50        
879             $l{Prefix} || "",
880             $l{Object} || "",
881             $l{Sub} || "",
882             $l{Args} || "",
883             $l{Suffix} || "",
884             );
885             }
886              
887 10         25 chomp $msg;
888 10         16 $msg .= "\n";
889              
890 10 50 33     46 if ( $tp->{ShowStack} || $show_stack ) {
891 0         0 $msg .= join( "",
892             map(
893             join( " ",
894             $_->[3],
895             "at",
896             $_->[1],
897             "line",
898             $_->[2],
899             ) . "\n",
900 0         0 @{$r{Stack}}
901             )
902             );
903             }
904              
905 10         32 my $indent = "| ! " x ( ( $r{TraceDepth} - 1 ) >> 1 );
906 10 100       28 $indent .= "| " if ( $r{TraceDepth} - 1 ) & 1;
907              
908 10         48 $msg =~ s{(.)^}{
909 0         0 $1 . " : $indent| "
910             }gmes;
911              
912 10         26 $indent =~ s/..$/+-/;
913              
914 10         17 my $dest = $tp->{LogTo};
915 10         331 print $dest join( "",
916             "TRACE: ",
917             $indent,
918             $msg
919             );
920              
921 10         51 $tp->{_LogInfo} = \%l;
922             }
923             }
924             }
925              
926             ## Using the &$ref form here on the off chance it might
927             ## avoid the subroutine prototypes
928 22         64 my $call_time;
929             my $return_time;
930 0         0 my $no_exception;
931 22 100       77 if ( $context ) {
    50          
932 8 50       26 $call_time = time if $record_call_time;
933 8         10 eval { @result = &$sub_ref( @_ ); $no_exception = 1 };
  8         138  
  8         68  
934 8 50       21 $return_time = time if $record_return_time;
935             }
936             elsif ( defined $context ) {
937 14 100       43 $call_time = time if $record_call_time;
938 14         44 eval { $result[0] = &$sub_ref( @_ ); $no_exception = 1 };
  14         89  
  14         68  
939 14 100       47 $return_time = time if $record_return_time;
940             }
941             else {
942 0 0       0 $call_time = time if $record_call_time;
943             ## DON'T BREAK THE VOID CONTEXT IF YOU EDIT THIS.
944 0         0 eval { &$sub_ref( @_ ); $no_exception = 1 };
  0         0  
  0         0  
945 0 0       0 $return_time = time if $record_return_time;
946             }
947 22         27 my $exception;
948 22 50       49 $exception = $@ unless $no_exception;
949              
950 22         42 for my $tp ( reverse @tps ) {
951 23         37 my $r = pop @r;
952 23 100       65 $r->{CallTime} = $call_time if defined $call_time;
953 23 100       51 $r->{ReturnTime} = $return_time if defined $return_time;
954 23         43 $r->{Exception} = $exception;
955             ## See comment above about build the call stack each time through
956             ## instead of caching it.
957 23 50       361 $r->{Result} = [
958             map ref $_ ? Dumper( $_ ) : $_, @result
959             ];
960 23 50       73 $tp->{PostCall}->( $r, \@_ ) if $tp->{PostCall};
961 23 50       65 $r->{Exception} = "$exception" if defined $exception;
962              
963 23 0 33     58 if ( $exception && $tp->{LogTo} && ref $tp->{LogTo} ne "ARRAY" ) {
      33        
964 0         0 my $l = $tp->{_LogInfo};
965              
966 0   0     0 my $msg = join( "",
967             "EXCEPTION:",
968             $l->{Prefix} || "",
969             $l->{Object},
970             $l->{Sub},
971             " threw: ",
972             $exception
973             );
974            
975 0         0 chomp $msg;
976 0         0 $msg .= "\n";
977              
978 0         0 $msg =~ s{(.)^}{
979 0         0 $1 . " :" . " " x ( $r->{TraceDepth} - 1 ) . " "
980             }gmes;
981              
982 0         0 my $dest = $tp->{LogTo};
983 0         0 print $dest join( "",
984             "TRACE: ",
985             " " x ( $r->{TraceDepth} - 1 ),
986             $msg
987             );
988              
989             }
990              
991 23         97 delete $tp->{_LogInfo};
992             }
993              
994 22 50       53 die $exception if $exception;
995 22 100       1777 return $context ? @result : $result[0];
996             };
997              
998              
999             sub _intercept_sub {
1000 21     21   35 my ( $name, $proto, $sub_id ) = @_;
1001 21 100       61 $proto = defined $proto ? "($proto)" : "";
1002 21 50       66 $sub_id = $name unless defined $sub_id;
1003 21 50       51 die if $name =~ /^Devel::TraceCalls/;
1004 21 50       76 cluck if grep ! defined, $proto, $sub_id;
1005 21         2063 return <
1006             sub $proto {
1007             Devel::TraceCalls::_call_sub( "$sub_id", \@_ ) ;
1008             }
1009             INTERCEPT_END
1010             }
1011              
1012             sub _get_named_subs {
1013 15     15   25 my %options = %{pop()};
  15         69  
1014              
1015 15         37 my $package = $options{Package};
1016              
1017 15         33 delete $options{Package};
1018 15         26 delete $options{Subs};
1019 15         22 delete $options{Objects};
1020 15         23 delete $options{Class};
1021              
1022 19 100       93 return map {
1023 15         41 my $name = index( $_, ":" ) >= 0 ? $_ : "${package}::$_";
1024 19         25 my $ref = do {
1025 5     5   41 no strict "refs";
  5         10  
  5         1165  
1026 19 100       80 defined &$name? \&$name: undef;
1027             };
1028 19 100       200 $ref
1029             ? {
1030             %options, ## first in case a "Name" or Ref sneaks in, say.
1031             Name => $name,
1032             Ref => $ref,
1033             _Signature => "sub $name",
1034             }
1035             : "Subroutine $name not defined";
1036             } @_;
1037             }
1038              
1039              
1040             sub _get_methods {
1041             ## Traipses through @ISA hierarchy.
1042 8     8   16 my $package = shift;
1043 8         10 my $orig_options = pop;
1044              
1045 8 50       16 cluck Dumper $orig_options unless defined $orig_options;
1046              
1047 8         30 my $options = { %$orig_options };
1048              
1049 8 50       22 $package = $options->{Package} unless defined $package;
1050 8 50       15 confess "undef package" unless defined $package;
1051              
1052 8         16 my $pattern = delete $options->{_Pattern};
1053              
1054 8         16 delete $options->{Subs};
1055 8         10 delete $options->{Package};
1056 8         10 delete $options->{Objects};
1057 8         11 delete $options->{Class};
1058              
1059 5     5   43 no strict "refs";
  5         47  
  5         5512  
1060             return (
1061 8         234 map(
1062             ! defined $pattern || $_ =~ $pattern
1063             ? {
1064             %$options,
1065             _Signature => $options->{_Signature} . "->sub $_",
1066             Name => $_,
1067             Ref => \&$_,
1068             }
1069             : (),
1070             grep
1071             defined &$_,
1072             map "${package}::$_",
1073 8         69 keys %{"${package}::"}
1074             ),
1075             map( _get_methods( $_, $orig_options ),
1076             # grep $_ ne "Exporter",
1077 8 50 33     10 @{"${package}::ISA"} ),
1078             ) ;
1079             }
1080              
1081              
1082             my $tracer;
1083             sub trace_calls {
1084 3     3 0 705 my $caller = caller;
1085 3   33     37 $tracer ||= __PACKAGE__->new;
1086 4 50 33     53 $tracer->add_trace_points(
    50          
    50          
    100          
1087             map {
1088 3         7 ref $_
1089             ? ( exists $_->{Subs}
1090             && ! exists $_->{Package}
1091             && ! exists $_->{Objects}
1092             && ! exists $_->{Class}
1093             )
1094             ? { Package => $caller, %$_ }
1095             : $_
1096             : /(.*)::$/
1097             ? { Package => $1 }
1098             : /(.*)->$/
1099             ? { Class => $1 }
1100             : { Package => $caller, Subs => [ $_ ] }
1101             } @_
1102             );
1103             }
1104              
1105             my $devel_trace_calls_pkg_re = "^" . __PACKAGE__;
1106             $devel_trace_calls_pkg_re = qr/$devel_trace_calls_pkg_re/;
1107              
1108             sub emit_trace_message {
1109 12     12 0 537 local $Data::Dumper::Indent = 1;
1110 12         18 local $Data::Dumper::Terse = 1;
1111 12         12 local $Data::Dumper::Quotekeys = 0;
1112              
1113             ## use local on this one just in case some exception happens,
1114             ## or an "exiting subroutine via next" kinda thing.
1115              
1116 12 0       28 my $msg = join "", map {
    50          
1117 12         22 my $d = ref()
1118             ? Dumper(
1119             $stringify_blessed_refs
1120             ? _stringify_blessed_refs $_
1121             : $_
1122             )
1123             : $_;
1124 12         17 chomp $d;
1125 12         35 $d;
1126             } @_;
1127              
1128 12         18 chomp $msg;
1129 12         15 $msg .= "\n";
1130              
1131 12         20 my $indent = "| ! " x ( $nesting_level >> 1 );
1132 12 100       27 $indent .= "| " if $nesting_level & 1;
1133              
1134 12         36 $msg =~ s{(.)^}{
1135 0         0 $1 . " : $indent| "
1136             }gmes;
1137              
1138 12         24 $indent =~ s/..$/+=/;
1139              
1140             ## TODO: allow log formatting and emission to custom trace destinations.
1141 12         12615 print STDERR "TRACE: ", $indent, $msg;
1142             };
1143              
1144             =head1 OO API
1145              
1146             The object oriented interface provides for more flexible than the other
1147             APIs. A tracer will remove all of it's trace points when it is deleted
1148             and you can add (and someday, remove) trace points from a running
1149             tracer.
1150              
1151             Someday you'll also be able to enable and disable tracers.
1152              
1153             =over
1154              
1155             =item new
1156              
1157             my $t = Devel::TraceCalls->new(
1158             ... any params you might pass to trace_calls...
1159             );
1160              
1161             =cut
1162              
1163             sub new {
1164 20     20 1 14226 my $self = do {
1165 20         36 my $proto = shift;
1166 20   33     100 my $class = ref $proto || $proto;
1167 20         65 bless {}, $class;
1168             };
1169 20         78 $self->add_trace_points( @_ );
1170 16         66 return $self;
1171             }
1172              
1173             =item add_trace_points
1174              
1175             $t->add_trace_points(
1176             ...any params you might pass to trace_calls...
1177             );
1178              
1179             Add trace points to an existing tracer. Trace points for subs that
1180             already have trace points will be ignored (we can add an option to
1181             enable this; send me a patch or contact me if need be).
1182              
1183             =cut
1184              
1185             ## Class trace points are oddballs. We need to attach multiple class objects
1186             ## to a class trace point so the trace point will fire for any class it
1187             ## exists in.
1188              
1189             sub add_trace_points {
1190 23     23 1 227 my $self = shift;
1191              
1192 23         60 my $package = caller;
1193              
1194             ##
1195             ## Parse the parameters
1196             ##
1197 23         45 my @trace_points;
1198             my @objects;
1199 0         0 my @errors;
1200 23         49 for my $parm (@_ ) {
1201 22 100       97 if ( ! ref $parm ) {
    100          
    50          
1202             ## It's the name of a subroutine
1203 4         33 push @trace_points, _get_named_subs $parm, {
1204             Package => $package,
1205             CaptureCallTime => 1,
1206             CaptureReturnTime => 1,
1207             CaptureArgs => 1,
1208             CaptureResult => 1,
1209             CaptureStack => 1,
1210             };
1211             }
1212             elsif ( ref $parm eq "HASH" ) {
1213             ## It's a HASH of options
1214 17 100       81 if ( exists $parm->{Package} ) {
    100          
    100          
    50          
1215             ## It's a package trace request
1216 9 100       26 unless ( defined $parm->{Package} ) {
1217 1         9 push @errors, "Undefined Package parameter";
1218 1         2 next;
1219             }
1220              
1221 8 100       26 if ( exists $parm->{Subs} ) {
1222 6 50       19 unless ( defined $parm->{Subs} ) {
1223 0         0 push @errors, "Undefined Subs parameter";
1224 0         0 next;
1225             }
1226 6 50       26 unless ( ref $parm->{Subs} eq "ARRAY" ) {
1227 0         0 push @errors,
1228             "Subs parameter must be an ARRAY, not '$parm->{Subs}'";
1229 0         0 next;
1230             }
1231 6         11 push @trace_points, _get_named_subs @{$parm->{Subs}}, $parm;
  6         33  
1232             }
1233             else {
1234 2         5 my $p = $parm->{Package};
1235             ## We don't want to look at @ISA, so grab the sub
1236             ## names manually instead of calling _get_methods
1237 5     5   101 no strict "refs";
  5         26  
  5         7234  
1238 2         3 my @sub_names;
1239 2         5 my @packages = $p;
1240 2 50       6 @packages = @$p if ref $p eq 'ARRAY';
1241              
1242 2         4 for my $pkg (@packages)
1243             {
1244 2         21 @sub_names = grep
1245             defined &$_,
1246             map "${pkg}::$_",
1247 2         3 keys %{"${pkg}::"};
1248 2         8 push @trace_points, _get_named_subs @sub_names, $parm;
1249             }
1250             }
1251             }
1252             elsif ( exists $parm->{Class} ) {
1253 3 50       10 unless ( defined $parm->{Class} ) {
1254 0         0 push @errors, "Undefined Class parameter";
1255 0         0 next;
1256             }
1257              
1258 3         4 my $pat;
1259 3 50       9 if ( exists $parm->{Subs} ) {
1260 0 0       0 unless ( defined $parm->{Subs} ) {
1261 0         0 push @errors, "Undefined Subs parameter";
1262 0         0 next;
1263             }
1264 0 0       0 unless ( ref $parm->{Subs} eq "ARRAY" ) {
1265 0         0 push @errors,
1266             "Subs parameter must be an ARRAY, not '$parm->{Subs}'";
1267 0         0 next;
1268             }
1269              
1270             ## Throw away unwanted methods
1271 0         0 $pat = join
1272             "|",
1273             map(
1274             ( /:/ ? "^$_" : $_ ) . "(?!\n)\$",
1275 0 0       0 @{$parm->{Subs}}
1276             );
1277             }
1278              
1279             ## All class subs use a single trace point with
1280             ## possibly multiple _TraceClasses, so the signature
1281             ## is set to indicate that it's a class trace point and
1282             ## the sub name is left to differentiate it. We
1283             ## decode these signals below where the trace points are
1284             ## actually set.
1285 3         21 push @trace_points, _get_methods
1286             $parm->{Class},
1287             {
1288             %$parm,
1289             _Pattern => $pat,
1290             _TraceClass => $parm->{Class},
1291             _Signature => "(class)",
1292             };
1293             }
1294             elsif ( exists $parm->{Objects} ) {
1295 2 50       6 unless ( defined $parm->{Objects} ) {
1296 0         0 push @errors, "Undefined Objects parameter";
1297 0         0 next;
1298             }
1299 2 50       7 unless ( ref $parm->{Objects} eq "ARRAY" ) {
1300 0         0 push @errors,
1301             "Object parameter must be an ARRAY, not '$parm->{Objects}'";
1302 0         0 next;
1303             }
1304              
1305 2         3 my $pat;
1306 2 50       8 if ( exists $parm->{Subs} ) {
1307 0 0       0 unless ( defined $parm->{Subs} ) {
1308 0         0 push @errors, "Undefined Subs parameter";
1309 0         0 next;
1310             }
1311 0 0       0 unless ( ref $parm->{Subs} eq "ARRAY" ) {
1312 0         0 push @errors,
1313             "Subs parameter must be an ARRAY, not '$parm->{Subs}'";
1314 0         0 next;
1315             }
1316              
1317             ## Throw away unwanted methods
1318 0         0 $pat = join
1319             "|",
1320             map(
1321             ( /:/ ? "^$_" : $_ ) . "(?!\n)\$",
1322 0 0       0 @{$parm->{Subs}}
1323             );
1324              
1325             }
1326 2         34 push @trace_points, map
1327             _get_methods(
1328             ref $_,
1329             {
1330             %$parm,
1331             _Pattern => $pat,
1332             _TraceInstance => int $_,
1333             _Signature => int $_,
1334             }
1335             ),
1336 2         2 @{$parm->{Objects}};
1337             }
1338             elsif ( exists $parm->{Subs} ) {
1339             ## Named subs, perhaps with options.
1340 3 50       11 unless ( defined $parm->{Subs} ) {
1341 0         0 push @errors, "Undefined Subs parameter";
1342 0         0 next;
1343             }
1344 3         5 push @trace_points, _get_named_subs @{$parm->{Subs}}, {
  3         24  
1345             Package => $package,
1346             %$parm,
1347             };
1348             }
1349             else {
1350 0         0 push @errors,
1351             "options hash does not have Package, Objects, or Subs" ;
1352 0         0 next;
1353             }
1354             }
1355             elsif ( index( "GLOB|SCALAR|ARRAY|Regexp|REF|CODE|HASH", ref $parm )<0 ){
1356             ## Object instance... we hope.
1357             ## TODO: Improve the blessedness check :).
1358 0         0 push @trace_points, _get_methods
1359             ref $parm,
1360             {
1361             CaptureCallTime => 1,
1362             CaptureReturnTime => 1,
1363             CaptureArgs => 1,
1364             CaptureResult => 1,
1365             CaptureStack => 1,
1366             CaptureSelf => 1,
1367             _TraceInstance => int $parm,
1368             _Signature => int $_,
1369             };
1370             }
1371             else {
1372 1         5 push @errors, "Invalid parameter '$parm'";
1373             }
1374             }
1375              
1376 23         66 push @errors, grep !ref, @trace_points;
1377 23 100       73 croak join "\n", @errors if @errors;
1378              
1379 38         49 @trace_points = map {
1380 19         31 my $tp = $_;
1381 38 100 66     127 if ( exists $tp->{CaptureAll} && $tp->{CaptureAll} ) {
1382 1         9 $tp->{$_} = 1 for qw(
1383             CaptureCallTime
1384             CaptureReturnTime
1385             CaptureArgs
1386             CaptureResult
1387             CaptureStack
1388             CaptureSelf
1389             );
1390             }
1391              
1392 38 50 66     164 $tp->{LogTo} = \*STDERR
      33        
1393             if ! exists $tp->{LogTo}
1394             && ! $tp->{PreCall}
1395             && ! $tp->{PostCall};
1396              
1397 38         85 $tp;
1398             } @trace_points;
1399              
1400             ##
1401             ## Install sub wrappers
1402             ##
1403             {
1404 19         30 for my $tp ( @trace_points ) {
  19         38  
1405 38         64 my $sub_id = $tp->{Name};
1406 38         51 my $sig = $tp->{_Signature};
1407              
1408 38 50 33     174 confess "No signature for ", Dumper( $tp ) unless
1409             defined $sig and length $sig;
1410              
1411             ## Don't add more traces to the one we're already
1412             ## tracing.
1413 38 50       124 if ( exists $self->{TracePoints}->{$sig} ) {
1414 0 0       0 if ( substr( $sig, 0, 7 ) eq "(class)" ) {
1415             ## Just add the _TraceClass to the existing
1416             ## trace point's _TraceClasses.
1417 0         0 warn "adding a tracepoint $sig (",
1418             join( ", ", sort keys %$tp),
1419             ") to existing _TraceClasses for $sub_id\n"
1420             if debugging;
1421              
1422 0         0 $self->{TracePoints}->{$sig}->{_TraceClasses}
1423             ->{$tp->{_TraceClass}} = undef;
1424 0         0 next;
1425             }
1426              
1427             warn(
1428 0         0 "NOT adding an additional tracepoint $sig (",
1429             join( ", ", sort keys %$tp),
1430             ") for $sub_id)\n"
1431             ) if debugging;
1432              
1433 0         0 next;
1434             }
1435              
1436 38 100       203 $tp->{_TraceClasses}->{$tp->{_TraceClass}} = undef
1437             if exists $tp->{_TraceClass};
1438              
1439 38 50       174 if ( $sub_id =~ $devel_trace_calls_pkg_re ) {
1440 0         0 cluck "Can't place a trace inside ", __PACKAGE__, ", ignoring";
1441 0         0 next;
1442             }
1443              
1444 38 100       93 if ( $trace_points{$sub_id} ) {
1445 17         22 warn( "adding a tracepoint $sig (",
1446             join( ", ", sort keys %$tp),
1447             ") for $sub_id\n"
1448             ) if debugging;
1449              
1450 17         83 push @{$trace_points{$sub_id}->{TracePoints}}, $tp;
  17         43  
1451             }
1452             else {
1453 21 50       74 confess if $sub_id =~ /^::/;
1454 21 50       71 confess if $sub_id =~ /^Devel::TraceCalls/;
1455              
1456 21         24 warn( "creating tracepoint $sig (",
1457             join( ", ", sort keys %$tp),
1458             ") for $sub_id\n"
1459             ) if debugging;
1460              
1461 21         44 my $proto = prototype $tp->{Ref};
1462              
1463 21         100 $trace_points{$sub_id} = {
1464             Name => $sub_id,
1465             Ref => $tp->{Ref},
1466             TracePoints => [ $tp ],
1467             };
1468              
1469 21 50   8   64 my $sub = eval _intercept_sub( $tp->{Name}, $proto ) or die $@;
  8         1612  
1470 5     5   41 no strict "refs";
  5         11  
  5         1910  
1471 21         74 local $^W = 0; ## Suppress subroutine redefined warnings.
1472 21         30 *{$tp->{Name}} = $sub;
  21         121  
1473             }
1474              
1475             ## Do this last in case of problems above
1476 38         1332 $self->{TracePoints}->{$tp->{_Signature}} = $tp;
1477             }
1478             }
1479             }
1480              
1481             ## NOTE: when and if we write a "remove_trace_point" sub, it's going to
1482             ## have to deal with (class) trace points very carefully.
1483              
1484              
1485             ## This is private until we come up with an API for individual trace points.
1486             sub _trace_points {
1487 32 50   30   189 croak "Can't set subs" if @_ > 1;
1488 30         37 return values %{shift()->{TracePoints}};
  30         161  
1489             }
1490              
1491              
1492             sub DESTROY {
1493 17     17   4772 my $self = shift;
1494              
1495             ##
1496             ## Remove trace points.
1497             ##
1498 17         46 for my $tp ( $self->_trace_points ) {
1499 33         57 my $name = $tp->{Name};
1500 33         89 my $tps = $trace_points{$name}->{TracePoints};
1501              
1502             ## Remove all of our trace points from this sub
1503 33         136 @$tps = grep $_ != $tp, @$tps;
1504              
1505 33 100       103 if ( ! @$tps ) {
1506 16         30 my $ref = $trace_points{$name}->{Ref};
1507              
1508 16         19 warn "Restoring tracepoint $name ($tp->{_Signature}) to $ref\n"
1509             if debugging;
1510              
1511 16         45 delete $trace_points{$name};
1512 5     5   31 no strict "refs";
  5         13  
  5         1494  
1513 16         48 local $^W = 0;
1514 16         21 *{$name} = $ref;
  16         476  
1515             }
1516             else {
1517 17         179 warn "Removing tracepoint $name ($tp->{_Signature})\n" if debugging;
1518             }
1519             }
1520             }
1521              
1522             =back
1523              
1524             =head1 Using in other Devel:: modules
1525              
1526             The main advantage of the Devel:: namespace is that the C
1527             ...> syntax is pretty handy. Other modules which use this might want
1528             to be in the Devel:: namespace. The only trick is avoiding
1529             calling Devel::TraceCalls' import() routine when you do this (unless
1530             you want to for some reason).
1531              
1532             To do this, you can either carefully avoid placing C in
1533             your Devel::* module's C<@ISA> hierarchy or make sure that your module's
1534             C method is called instead of C'. If you
1535             do this, you'll need to have a C defined, because
1536             C' wont be. See the source and the
1537             L module for details.
1538              
1539             =head1 A Word on Devel::TraceCall Overhead
1540              
1541             Massive.
1542              
1543             Devel::TraceCall is a debugging aid and is designed to provide a lot
1544             of detail and flexibility. This comes at a price, namely overhead.
1545              
1546             One of the side effects of this overhead is that Devel::TraceCall is
1547             useless as a profiling tool, since a function that calls a number of
1548             other functions, all of them being traced, will see all of the overhead
1549             of Devel::TraceCall in its elapsed time. This could be worked around,
1550             but it is outside the scope of this module, see L for
1551             profiling needs.
1552              
1553             =head1 TODO
1554              
1555             =over
1556              
1557             =item *
1558              
1559             Wrap AUTOLOAD and automatically enable tracing on subs handled by and
1560             created by AUTOLOADing.
1561              
1562             =item *
1563              
1564             Wrapper subs.
1565              
1566             =item *
1567              
1568             Does not get parameters from the call stack. It will be optional, on by
1569             default.
1570              
1571             =item *
1572              
1573             Flesh out and debug the -d:TraceCalls=... feature.
1574              
1575             =item *
1576              
1577             Add testing for PreCall and PostCall features.
1578              
1579             =item *
1580              
1581             Migrate the CORE::GLOBAL::require feature from Devel::TraceSAX so that
1582             run-time C statements can result in classes being traced.
1583              
1584             =item *
1585              
1586             Enable wildcards, probably by passing qr/.../ refs, in class, package
1587             and sub names.
1588              
1589             =item *
1590              
1591             Migrate the namespace walking feature from Devel::TraceSAX, so that the
1592             above wildcards can be used to specify categories of classes and
1593             packages to trace.
1594              
1595             =item *
1596              
1597             Optional logging of returned values.
1598              
1599             =back
1600              
1601             =head1 LIMITATIONS
1602              
1603             There are several minor limitations.
1604              
1605             Exports a subroutine by default. Do a C to
1606             suppress that.
1607              
1608             If perl's optimized away constant functions, well, there is no call
1609             to trace.
1610              
1611             Because a wrapper subroutine gets installed in place of the original
1612             subroutine, anything that has cached a reference (with code like
1613             $foo = \&foo or $foo = Bar->can( "foo" )) will bypass the tracing.
1614              
1615             If a subroutine reference is taken while tracing is enabled and then
1616             used after tracing is disabled, it will refer to the wrapper subroutine
1617             that no longer has something to wrap. Devel::TraceCalls does not pass
1618             these through in that case, but it could.
1619              
1620             The import based C feature relies on a
1621             C subroutine, which is not present on older perls. See
1622             L for details.
1623              
1624             Doesn't warn if you point it at an empty class, or if you pass no subs.
1625             This is because you might be passing in a possibly empty list. Check
1626             the return value's subs method to count up how many overrides occured.
1627              
1628             =head1 PRIOR ART
1629              
1630             See Devel::TraceMethods and Aspect::Trace for similar functionality.
1631              
1632             Merlyn also suggested using Class::Prototyped to implement the
1633             instance subclassing, but it seems too simple to do without incurring
1634             a prerequisite module.
1635              
1636             A miscellany of tricky modules like Sub::Versive, Hook::LexWrap, and
1637             Sub::Uplevel.
1638              
1639             =head1 SEE ALSO
1640              
1641             L for profiling, L for an example of
1642             a client module.
1643              
1644             =head1 AUTHOR
1645              
1646             Barrie Slaymaker
1647              
1648             Maintainer from version 0.04 is
1649             Cosimo Streppone
1650              
1651             =head1 COPYRIGHT
1652              
1653             Copyright (c) 2002 Barrie Slaymaker, All Rights Reserved.
1654              
1655             You may use this module under the terms of the Artistic License or the
1656             GPL, any version.
1657              
1658             =cut
1659              
1660             1;