NAME
App::Trace - Embedded debug statements, including call/return tracing
SYNOPSIS
In a program (such as the following one named "foo"), you can do the following...
#!/usr/bin/perl
use App::Option; # App::Trace was written to be used with App::Options
use App::Trace; # enable tracing support
use Foo;
&run();
sub run {
&App::sub_entry if ($App::trace); # trace subroutine entry
my $foo = Foo->new();
$foo->run();
&App::sub_exit() if ($App::trace); # trace subroutine exit
}
in a module (i.e. Foo.pm), you can do the following...
package Foo;
# new(): a generic object constructor
sub new {
&App::sub_entry if ($App::trace); # trace method entry
my ($this, @args) = @_;
my $class = ref($this) || $this;
my $self = { @args };
bless $self, $class;
&App::sub_exit($self) if ($App::trace); # trace method exit
return($self);
}
sub run {
&App::sub_entry if ($App::trace); # trace method entry
print "Expression: (1 + 2) * (7 - (2*2))\n";
my $value = $self->multiply(
$self->add(1, 2),
$self->subtract(7, $self->multiply(2, 2))
);
print "Value: $value\n";
&App::sub_exit() if ($App::trace); # trace method exit
}
sub add {
&App::sub_entry if ($App::trace); # trace method entry
my ($self, $operand1, $operand2) = @_;
my $value = $operand1 + $operand2;
&App::sub_exit($value) if ($App::trace); # trace method exit
return($value);
}
sub subtract {
&App::sub_entry if ($App::trace); # trace method entry
my ($self, $operand1, $operand2) = @_;
my $value = $operand1 - $operand2;
&App::sub_exit($value) if ($App::trace); # trace method exit
return($value);
}
sub multiply {
&App::sub_entry if ($App::trace); # trace method entry
my ($self, $operand1, $operand2) = @_;
my $value = $operand1 * $operand2;
&App::sub_exit($value) if ($App::trace); # trace method exit
return($value);
}
Then when you invoke the program normally, you get no debug output.
You only get the expected program output.
foo
However, when you invoke the program with something like the following...
foo --trace
you get trace output like the following.
...
Try the following options...
foo --trace --trace_width=0 # unlimited width (long lines wrap on screen)
foo --trace --trace_width=78 # set max width of output
foo --trace --trace_width=78 --trace_justify # right-justify package
foo --trace=main # only trace subs in "main" package
foo --trace=Foo # only trace subs in "Foo" package
foo --trace=Foo.multiply # only trace the multiply() method in the Foo package
foo --trace=main,Foo.run # trace a combo of full packages and specific methods
DESCRIPTION
App::Trace provides debug/tracing support for perl programs and modules.
The basic concept is that you put a special call at the beginning and end of each subroutine/method, and when tracing is enabled, you can see the flow of your program.
This module reflects my dislike of the perl debugger. I also dislike putting in print statements to debug, then commenting them out when I'm done. I would rather put debug statements in my code and leave them there. That way, when programs work their way into production, they can still be debugged by using appropriate command line options.
Perl modules which are written to be used with App::Trace can be debugged easily without entering the perl debugger. The output of tracing is a "program trace" which shows the entry and exit of every subroutine/method (and the arguments). This trace is printed in a format which allows you to follow the flow of the program.
Someday I might figure out how to do this at a language level so it will work on any module, not just ones which have been specially instrumented with &App::sub_entry() and &App::sub_exit() calls. In fact, I started work on this with the Aspect.pm module, but that was specific to perl version 5.6.x and didn't work with 5.8.x. That's when I decided I would write App::Trace which would work on any Perl (even back to 5.5.3, which I consider to be the first Perl 5 to support for deep backward compatibility).
The App-Trace distribution began life as a collection of routines pulled out of the App-Context distribution. I created App-Trace because these routines were very useful independent of the rest of the framework provided by App-Context.
App::Trace is dependent on App::Options. It is possible to use App::Trace without App::Options, but they share a common convention with regard to certain global variables in the "App" package/namespace.
It is expected that when App::Trace is mature, the routines included will be removed from App.pm module in the App-Context distribution. The App-Context distribution will then be dependent on App::Trace for these features.
Attributes, Constants, Global Variables, Class Variables
Global Variables
* Global Variable: %App::scope scope for debug or tracing output
* Global Variable: $App::scope_exclusive flag saying that the scope is exclusive (a list of things *not* to debug/trace)
* Global Variable: %App::trace trace level
* Global Variable: $App::DEBUG debug level
* Global Variable: $App::DEBUG_FILE file for debug output
sub_entry()
* Signature: &App::sub_entry;
* Signature: &App::sub_entry(@args);
* Param: @args any
* Return: void
* Throws: none
* Since: 0.01
This is called at the beginning of a subroutine or method (even before $self may be shifted off).
sub_exit()
* Signature: &App::sub_exit(@return);
* Param: @return any
* Return: void
* Throws: none
* Since: 0.01
This subroutine is called just before you return from a subroutine or method.
in_debug_scope()
* Signature: &App::in_debug_scope
* Signature: App->in_debug_scope
* Param: <no arg list supplied>
* Return: void
* Throws: none
* Since: 0.01
This is called within a subroutine or method in order to see if debug output should be produced.
if ($App::debug && &App::in_debug_scope) {
print "This is debug output\n";
}
Note: The App::in_debug_scope subroutine also checks $App::debug, but checking it in your code allows you to skip the subroutine call if you are not debugging.
if (&App::in_debug_scope) {
print "This is debug output\n";
}
debug_indent()
* Signature: &App::debug_indent()
* Signature: App->debug_indent()
* Param: void
* Return: $indent_str string
* Throws: none
* Since: 0.01
This subroutine returns the $indent_str string which should be printed before all debug lines if you wish to line the debug output up with the nested/indented trace output.
ACKNOWLEDGEMENTS
* Author: Stephen Adkins <spadkins@gmail.com>
* License: This is free software. It is licensed under the same terms as Perl itself.