Marty O'Brien > Devel-DumpTrace-0.17 > Devel::DumpTrace

Download:
Devel-DumpTrace-0.17.tar.gz

Dependencies

Annotate this POD

CPAN RT

New  1
Open  0
View/Report Bugs
Module Version: 0.17   Source   Latest Release: Devel-DumpTrace-0.18

NAME ^

Devel::DumpTrace - Evaluate and print out each line before it is executed.

VERSION ^

0.17

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. 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

    # fails if PPI 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

There is also a Devel::DumpTrace::PPI module in this distribution which relies on PPI to understand the source code.

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 xtrace-output.txt
       if ($INC{'Devel/DumpTrace.pm'}) {
          open $Devel::DumpTrace::DUMPTRACE_FH, '>', '/path/xtrace-output.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". The DUMPTRACE_NOPPI variable can be set to force this module to use the basic code parser and to ignore the PPI-based version.

This is an incompatible change from v0.06, which recognized the vars XTRACE_FH and XTRACE_LEVEL.

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).

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. DUMPTRACE_TIME and DUMPTRACE_PID may both be used at the same time.

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

INCOMPATIBILITIES ^

None known.

EXPORT ^

Nothing is or can be exported from this module.

DIAGNOSTICS ^

All output from this program is for diagnostics.

DEPENDENCIES ^

Devel::DumpTrace requires the PadWalker and Scalar::Util modules.

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.

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:

SEE ALSO ^

dumpvar.pl, as used by the Perl debugger.

Devel::Trace, PadWalker.

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.

AUTHOR ^

Marty O'Brien, <mob at cpan.org>

LICENSE AND COPYRIGHT ^

Copyright 2010-2012 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.

syntax highlighting: