NAME
Devel::DumpTrace - Evaluate and print out each line before it is executed.
VERSION
0.26
SYNOPSIS
perl -d:DumpTrace program.pl
perl -d:DumpTrace=verbose program.pl
perl -d:DumpTrace=quiet program.pl
perl -d:DumpTrace=<n> program.pl
perl -d:DumpTrace::PPI program.pl
perl -d:DumpTrace::noPPI program.pl
DESCRIPTION
Similar to Devel::Trace, this module will cause a message to be printed to standard error for each line of source code that is executed. In addition, this module will attempt to identify variable names in the source code and substitute the values of those variables. In this way you can say the path of execution through your program as well as see the value of your variables at each step of the program.
For example, if your program looks like this:
#!/usr/bin/perl
# a demonstration of Devel::DumpTrace
$a = 1;
$b = 3;
$c = 2 * $a + 7 * $b;
@d = ($a, $b, $c + $b);
then the DumpTrace
output will look like:
$ perl -d:DumpTrace demo.pl
>>>>> demo.pl:3: $a:1 = 1;
>>>>> demo.pl:4: $b:3 = 3;
>>>>> demo.pl:5: $c:23 = 2 * $a:1 + 7 * $b:3;
>>>>> demo.pl:6: @d:(1,3,26) = ($a:1, $b:3, $c:23 + $b:3);
There are also more verbose modes which will produce even more detailed output:
$ perl -d:DumpTrace=verbose demo.pl
>> demo.pl:3:
>>> $a = 1;
>>>>> 1 = 1;
-------------------------------------------
>> demo.pl:4:
>>> $b = 3;
>>>>> 3 = 3;
-------------------------------------------
>> demo.pl:5:
>>> $c = 2 * $a + 7 * $b;
>>>> $c = 2 * 1 + 7 * 3;
>>>>> 23 = 2 * 1 + 7 * 3;
-------------------------------------------
>> demo.pl:6:
>>> @d = ($a, $b, $c + $b);
>>>> @d = (1, 3, 23 + 3);
>>>>> (1,3,26) = (1, 3, 23 + 3);
-------------------------------------------
See $Devel::DumpTrace::TRACE
under the "VARIABLES" section for more details about the different levels of verbosity.
This distribution comes with both a basic parser and a PPI-based parser (which relies on PPI to understand your source code). If the PPI module is installed on your system, then this module will automatically use the PPI-based parser to analyze the traced code. You can force this module to use the basic parser by running with the -d:DumpTrace::noPPI
argument or by setting the DUMPTRACE_NOPPI
environment variable:
# use PPI if available, otherwise use basic parser
$ perl -d:DumpTrace program.pl
# use PPI, fail if it is not available
$ perl -d:DumpTrace::PPI program.pl
# always uses basic parser
$ perl -d:DumpTrace::noPPI program.pl
$ DUMPTRACE_NOPPI=1 perl -d:DumpTrace program.pl
See the "BUGS AND LIMITATIONS" section for important, er, limitations of this module, especially for the basic parser.
SUBROUTINES/METHODS
None of interest.
VARIABLES
$Devel::DumpTrace::TRACE
Controls whether and how much output is produced by this module. Setting $Devel::DumpTrace::TRACE
to zero will disable the module. Since this module can produce a lot of output and has other overhead that can considerably slow down your program (by a factor of 50 or more), you may find it useful to toggle this variable for critical sections of your code rather than leave it set for the entire program. For example:
BEGIN { $Devel::DumpTrace::TRACE = 0 }
&some_non_critical_code_that_more_or_less_works();
$Devel::DumpTrace::TRACE = 'normal';
&the_critial_code_you_want_to_debug();
$Devel::DumpTrace::TRACE = 0;
&some_more_non_critical_code();
or to enable tracing in a local
block:
{
local $Devel::DumpTrace::TRACE = 1;
&the_critical_code;
}
In general higher values of $Devel::DumpTrace::TRACE
will cause more output to be produced. Let's consider this simple program to see how the different $Devel::DumpTrace::TRACE
settings affect the output:
@a = (1 .. 40);
$b = $a[4];
$Devel::DumpTrace::TRACE
== 1-
is the quietest mode. One line of output for each statement evaluated. The name of each variable in the source code and its value are included in the same line of output. Values of long scalars, long arrays, or long hash tables are heavily abbreviated:
$ perl -d:DumpTrace=1 littledemo.pl >>>>> littledemo.pl:1:[__top__]: @a:(1,2,3,4,5,6,...,40) = (1 .. 40); >>>>> littledemo.pl:2:[__top__]: $b:5 = $a:(1,2,3,4,5,6,...,40)[4];
$Devel::DumpTrace::TRACE
== 2-
uses a single line of output for each statement evaluated. The name of each variable in the source code and its source code are included in the same line of output. Values of long scalar, arrays, and hashes are less heavily abbreviated.
$ perl -I. -d:DumpTrace=2 littledemo.pl >>>>> littledemo.pl:1:[__top__]: @a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14, \ 15,16,17,18,19,20,21,22,23,24,25,26,27,...,40) = (1 .. 40); >>>>> littledemo.pl:2:[__top__]: $b:5 = $a:(1,2,3,4,5,6,7,8,9,10,11,12, \ 13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,...,40)[4];
$Devel::DumpTrace::TRACE
== 3-
produces one line of output for each statement evaluated. The name of each variable in the source code and its source code are included in the same line of output. Values of long scalar, arrays, and hashes are not abbreviated at all. This is the default setting for the module.
$ perl -I. -d:DumpTrace=3 littledemo.pl >>>>> littledemo.pl:1:[__top__]: @a:(1,2,3,4,5,6,7,8,9,10,11,12,13,14, \ 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, \ 38,39,40) = (1 .. 40); >>>>> littledemo.pl:2:[__top__]: $b:5 = $a:(1,2,3,4,5,6,7,8,9,10,11,12, \ 13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35, \ 36,37,38,39,40)[4];
$Devel::DumpTrace::TRACE
== 4-
produces up to four lines of output for each statement evaluated:
the source (file and line number) of the statement being evaluated
the origianl source code for the statement being evaluated
a valuation of the code before the statement has been evaluated by the Perl interpreter.
a valuation of the code after the statement has been evaluated by the Perl interpreter
A separator line will also be displayed between statements. Long scalar, arrays, and hashes may be abbreviated. Example output:
$ perl -d:DumpTrace=4 littledemo.pl >> littledemo.pl:1:[__top__]: >>> @a = (1 .. 40); >>>>> (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, \ 21,22,23,24,25,26,27,...,40) = (1 .. 40); ------------------------------------------- >> littledemo.pl:2:[__top__]: >>> $b = $a[4] + $a[5]; >>>> $b = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,...,40)[4]; >>>>> 5 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,...,40)[4]; -------------------------------------------
$Devel::DumpTrace::TRACE
== 5-
Like
$TRACE
4, but long scalars, arrays, and hashes are not abbreviated.$ perl -I. -d:DumpTrace=5 littledemo.pl >> littledemo.pl:1:[__top__]: >>> @a = (1 .. 40); >>>>> (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, \ 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40) = (1 .. 40); ------------------------------------------- >> littledemo.pl:2:[__top__]: >>> $b = $a[4] + $a[5]; >>>> $b = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)[4]; >>>>> 5 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, \ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)[4];
As these demos suggest, you can pass the $TRACE
variable through the command line using the syntax -d:DumpTrace=level
. In place of a number, you may also use the keywords quiet
or verbose
which will set the $TRACE
variable to 1 and 5, respectively.
By default Devel::DumpTrace
does not evaluate statements in any "system" modules, which are defined as any module from a file that resides under an absolute path in your system's @INC
list of directories. If the $TRACE
variable is set to a value larger than 100, then this module will drill down into such modules. See also "EXCLUDE_PKG" and "INCLUDE_PKG" for another way to exercise control over what packages this module will explore.
For convenience, the $Devel::DumpTrace::TRACE
variable is aliased to the $Devel::Trace::TRACE
variable. This way you can enable settings in your program that can be used by both Devel::Trace and Devel::DumpTrace
.
$Devel::DumpTrace::DUMPTRACE_FH
By default, all output from the Devel::DumpTrace
module is written to standard error. This behavior can be changed by setting $Devel::DumpTrace::DUMPTRACE_FH
to the desired I/O handle:
BEGIN {
# if Devel::DumpTrace is loaded, direct output to trace.txt
if ($INC{'Devel/DumpTrace.pm'}) {
open $Devel::DumpTrace::DUMPTRACE_FH, '>', '/path/trace.txt';
}
}
The output stream for the Devel::DumpTrace
module can also be controlled with the environment variable DUMPTRACE_FH
. If this variable is set to STDOUT
, then output will be directed to standard output. If this variable contains another value that looks like a filename, this module will open a file with that name and write the trace output to that file.
Backwards-incompatible change: in v0.06, this variable was called XTRACE_FH
.
$Devel::DumpTrace::ARRAY_ELEM_SEPARATOR = ','
$Devel::DumpTrace::HASH_ENTRY_SEPARATOR = ';'
$Devel::DumpTrace::HASH_PAIR_SEPARATOR = '=>'
The Devel::DumpTrace
module uses the preceding default values as delimiters when creating string representations of arrays, hashes, and array/hash references. If you wish to use different delimiters for whatever reason (maybe your arrays have a lot of elements with commas in them), you can change these values.
$Devel::DumpTrace::XEVAL_SEPARATOR = ':'
In normal (non-verbose) mode, Devel::DumpTrace
will display this token between the name of a variable and its value (e.g., $c:23
). The default token is a colon (:
), but you may change it by changing the value of the variable $Devel::DumpTrace::XEVAL_SEPARATOR
.
%Devel::DumpTrace::EXCLUDE_PKG, %Devel::DumpTrace::INCLUDE_PKG
Sets of packages that this module will never/always explore. These settings take precedence over the setting of the $Devel::DumpTrace::TRACE
variable, and the settings of %Devel::DumpTrace::INCLUDE_PKG
take precendence over the settings of %Devel::DumpTrace::EXCLUDE_PKG
(that is, a package that is specified in both %EXCLUDE_PKG
and %INCLUDE_PKG
will be included).
@Devel::DumpTrace::EXCLUDE_PATTERN, @Devel::DumpTrace::INCLUDE_PATTERN
List of regular expressions representing the packages that this module will never/always trace through.
Patterns can be from the command line or at module import time by passing arguments that begin with +
to include packages or -
to exclude packages:
# always trace through Foo::xxx packages
perl -d:DumpTrace=+Foo::.* my_script.pl
# trace through Foo::Bar but not through Foo::Baz
perl -d:DumpTrace=+Foo::Bar,-Bar::Foo my_script.pl
Any pattern from user input will be implicitly anchored (bracketed by ^
and $
), so you must explicitly include wildcards to match a general pattern of package names.
# don't trace any package containing /Foo/ except for Xyz::Foo
perl -d:DumpTrace=-.*Foo.*,+Xyz::Foo my_script.pl
Settings in @INCLUDE_PATTERN
take precendence over @EXCLUDE_PATTERN
, so a package that matches a pattern in @INCLUDE_PATTERN
will always be traced, even if it also matches one or more patterns in <@EXCLUDE_PATTERN>.
# -Foo::Bar is ignored, because Foo::Bar also matches included .*::Bar
perl -d:DumpTrace=-Foo::Bar,+.*::Bar my_script.pl
CONFIGURATION AND ENVIRONMENT
Devel::DumpTrace
uses the DUMPTRACE_FH
and DUMPTRACE_LEVEL
environment variables to configure some package variables. See "VARIABLES". For Perl v5.8.8, which has a bug when the -d
switch is used like perl -d:Foo=xxx ...
, supplying the DUMPTRACE_LEVEL
environment variable is a workaround to this bug.
The DUMPTRACE_NOPPI
variable can be set to force this module to use the basic code parser and to ignore the PPI-based version.
If the DUMPTRACE_PID
environment variable is set to a true value, this module will include process ID information with the file and line number in all trace output. This setting can be helpful in debugging multi-process programs (programs that fork
). Since v0.23, the trace output when DUMPTRACE_PID
is set also includes thread ID information.
If the DUMPTRACE_TIME
environment variable is set to a true value, this module will include program runtime information with the file and line number in all trace output. Depending on the evaluation needs of each line of the code, the timestamp associated with a line may be created either immediately before or immediately after the line is executed.
If the DUMPTRACE_COUNT
environment variable is set to a true value, this module will include a count with the file and line number in all trace output, indicating how many times your program has visited a particular line of code.
The default behaviour of Devel::DumpTrace
is to include the name of the current subroutine each time the file and line number are displayed. If DUMPTRACE_NO_SUB
environment variable is set to a true value, then the subroutine name will not be displayed.
DUMPTRACE_TIME
, DUMPTRACE_PID
, DUMPTRACE_COUNT
, and DUMPTRACE_NO_SUB
may be used separately or in any combination.
When more than one environment variable needs to be set, the caller can use the DUMPTRACE
environment variable to set multiple variables concisely. If $ENV{DUMPTRACE}
is set, this module will split the variable value into key value pairs and update the other relevant environment variables. That is,
DUMPTRACE=PID=1,FH=trace.out,EXCLPKG=My::Module
is equivalent to the longer
DUMPTRACE_PID=1 DUMPTRACE_FH=trace.out DUMPTRACE_EXCL=My::Module
If DUMPTRACE_COLOR
is set, and if the Term::ANSIColor module can be loaded, then Devel::DumpTrace
output will be colored in the specified color. If your program produces output and you are writing Devel::DumpTrace
output to your console, the different color of the DumpTrace output will help the actual output from the program stand out.
Example:
DUMPTRACE_COLOR="bold yellow on_black" perl -d:DumpTrace myScript.pl
INCOMPATIBILITIES
None known.
EXPORT
Nothing is exported from this module.
DIAGNOSTICS
All output from this module is for diagnostics.
DEPENDENCIES
PadWalker for arbitrary access to lexical variables.
Scalar::Util for the reference identification convenience methods.
BUGS AND LIMITATIONS
Parser limitations
Some known cases where the output of this module will be incorrect or misleading include:
Multiple statements on one line
$b = 7;
$a=4; $b=++$a;
=================================
>>>>> 4=4; 7=++undef;
>>>>> 5=4; 7=++4;
All expressions on a line are evaluated, not just expressions in the statement currently being executed.
Statements with chained assignments; complex assignment expressions
($a,$b) = ('','bar');
$a = $b = 'foo';
>>>>> 'foo' = 'bar' = 'foo';
$rin=$ein=3;
>> select $rout=$in,undef,$eout=$ein,0;
>>> select $rout=3,undef,undef=3,0;
>>>>> select 3=3,undef,undef=3,0;
Everything to the right of the first assignment operator in a statement is evaluated before the statement is executed.
Displayed value of @_ variable is unreliable
The displayed value of @_
inside a subroutine is subject to some of the issues described in "caller" in perlfunc:
... be aware that setting @DB::args is best effort, intended for
debugging or generating backtraces, and should not be relied upon
... a side effect of the current implementation means that effects
of shift @_ can normally be undone (but not pop @_ or other splicing,
and not if a reference to @_ has been taken, and subject to the caveat
about reallocated elements), so @DB::args is actually a hybrid of the
current state and initial state of @_ . Buyer beware.
That is, the displayed value of @_
inside a subroutine may be corrupted. Different versions of Perl may have different behavior.
grep EXPR,LIST
and map EXPR,LIST
statements
grep EXPR,LIST
and map EXPR,LIST
constructions are evaluated a single time, after the entier LIST
has been evaluated, and this module does not let you drill down to how each element of the list was evaluated with the given EXPR
. The constructions grep BLOCK LIST
and map BLOCK LIST
, however, will display the BLOCK
evaluation for each element of the LIST
.
Basic parser limitations
This distribution ships with a PPI-based parser and a more basic parser that will be used if PPI
is not available (or if you explicitly request to use the basic parser). This parser is quite crude compared to the PPI-based parser, and suffers from these additional known issues:
Multiple lines for one statement
$a = ($b + $c # ==> oops, all this module sees is
+ $d + $e); # $a = ($b + $c
Only the first line of code in an expression is evaluated.
String literals that contain variable names
print STDERR "\$x is $x\n"; # ==> print STDERR "\4 is 4\n";
$email = 'mob@cpan.org'; # ==> $email = 'mob().org'
The parser is not sophisticated enough to tell whether a sigil is inside non-interpolated quotes.
Implicit $_
, @_
It would be nice if this parser could detect when Perl was implicitly using some variables and display the implicit variable.
/expression/; # actually $_ =~ /expression/
my $self = shift; # actually my $self = shift(@_);
That is not currently a capability of this module.
Special Perl variables are not recognized
$a = join $/, 'foo', 'bar'; # ==> $a = join $/, 'foo', 'bar'
Special variables with pure alphanumeric names like @ARGV
, $_
, and $1
will still be interpolated. Do see "caller" in perlfunc for some important caveats about how @_
is represented by this module.
For some of these limitations, there are easy workarounds (break up chained assignments, put all statements on separate lines, etc.) if you think the extra information provided by this module is worth the effort to make your code more friendly for this module.
Other bugs or feature requests
Please report any other bugs or feature requests to bug-Devel-DumpTrace at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Devel-DumpTrace. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Devel::DumpTrace
You can also look for information at:
RT: CPAN's request tracker
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
SEE ALSO
dumpvar.pl, as used by the Perl debugger.
Devel::DumpTrace::PPI is part of this distribution and provides similar functionality using PPI to parse the source code.
Devel::TraceVars is a very similar effort to Devel::DumpTrace
, but this module handles arrays, hashes, references, objects, lexical our
variables, and addresses more edge cases.
Tie::Trace provides facilities to watch the values of specific variables, including stack trace information about where and how the variables values were changed.
Ideas from the Devel::GlobalDestruction module were used to manage output during the end game of the traced script.
AUTHOR
Marty O'Brien, <mob at cpan.org>
LICENSE AND COPYRIGHT
Copyright 2010-2016 Marty O'Brien.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.