Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get trace output from only the main package of a Perl program

Tags:

debugging

perl

I would like to trace my Perl script, but only code in the main package, and redirect output to a file.

When starting the script with perl -d script.pl it goes into interactive mode.

I have tried

perl -d:Trace perl_05.pl 2&> output.log

But this also traces all subroutines and modules which I do not want.

I am looking for something like the bash set -o xtrace or sh -x.

like image 654
averlon Avatar asked May 03 '16 06:05

averlon


People also ask

What is trace output?

Most trace sources generate packetized data that might be further formatted by the trace infrastructure. This means that the captured trace data is not in a human-readable format. The trace data must go through extraction, decompression, decode, and processing stages to become human-readable.


2 Answers

The article Trace your Perl programs addresses your concerns regarding the amount of traces and shows you a way to tune the output so you just trace what you want.

You can create your own throw-away module to trace exactly what you want. Since the current directory is usually already in @INC, you can create a Devel/MyTrace.pm.

Read it completely to see how the author modifies the default behavior of the trace function to output first the traces to a file, then to STDERR too and finally limits the output to just trace the primary file.

You can go one step further to exclude all code except for the primary file:

use v5.10;
use autodie;

BEGIN {

my $trace_file = $ENV{TRACE_FILE} // "mytrace.$$";
print STDERR "Saving trace to $trace_file\n";

my $fh = do {
     if( $trace_file eq '-'      ) { \*STDOUT }
  elsif( $trace_file eq 'STDERR' ) { \*STDERR }
  else { 
      open my $fh, '>>', $trace_file;
      $fh;
      }
  };

sub DB::DB {
  my( $package, $file, $line ) = caller;
  return unless $file eq $0;
  my $code = \@{"::_<$file"};
  print $fh "[@{[time]}] $file $l $code->[$line]";
  }
}

1;

That last chunk of code is the one that is specially interesting for you. It does exactly what you want.

like image 135
LaintalAy Avatar answered Sep 18 '22 16:09

LaintalAy


Using perl with Devel::DumpTrace is a lot like using bash -x. Like bash -x, Devel::DumpTrace expands and outputs variable values to give you an idea of what your script was doing, not just where it is doing it.

It also has the feature you are looking for: to enable and disable tracing on specific packages. For your use case, you would run it like

perl -d:DumpTrace=-.*,+main my_script.pl

or

perl -d:DumpTrace=-.* my_script.pl

-.* means "exclude all packages that match /^.*$/ from tracing", which is to say, all packages. +main means "include package main in tracing".

The default output can be fairly verbose. If you want less output than that, you can specify quiet mode:

perl -d:DumpTrace=quiet,-.*,+main my_script.pl

(I am the author of Devel::DumpTrace)

like image 27
mob Avatar answered Sep 20 '22 16:09

mob