App-plstrace
view release on metacpan or search on metacpan
lib/Debug/LTrace/plstrace.pm view on Meta::CPAN
shift;
$import_params{ ${ \scalar caller } } = [@_];
}
# External constructor
sub new {
return unless defined wantarray;
my $self = shift->_new( scalar caller, @_ );
$self;
}
# Internal constructor
sub _new {
my ( $class, $trace_package, @params ) = @_;
my $self;
# Parse input parameters
foreach my $p (@params) {
if ($p =~ /^(-\w+)(?:=(.*))?/) {
# option
if ($1 eq '-time0') {
$time0 = $2;
} else {
$self->{$1} = defined($2) ? $2 : 1;
}
next;
}
#process sub
$p = $trace_package . '::' . $p unless $p =~ m/::/;
push @{ $self->{subs} }, (
$p =~ /^(.+)::\*(\*?)$/
? Devel::Symdump ->${ \( $2 ? 'rnew' : 'new' ) }($1)->functions()
: $p
);
}
bless $self, $class;
$self->_start_trace();
#use DD; dd $self;
$self;
}
my $prevtime;
# Bind all hooks for tracing
sub _start_trace {
my ($self) = @_;
return unless ref $self;
$self->{wrappers} = {};
my @messages;
foreach my $sub ( @{ $self->{subs} } ) {
next if $self->{wrappers}{$sub}; # Skip already wrapped
$self->{wrappers}{$sub} = Hook::LexWrap::wrap(
$sub,
pre => sub {
pop();
#my ( $pkg, $file, $line ) = caller(0);
#my ($caller_sub) = ( caller(1) )[3];
my $args = join(", ", map {$self->_esc($_)} @_);
my $entry_time = time();
my $msg = "> $sub($args)";
$msg = $self->_fmttime($entry_time) . " $msg" if $self->{-show_time};
if ($self->{-show_time}) {
warn "$msg\n";
$prevtime = $entry_time;
}
unshift @messages, [ "$sub($args)", $entry_time ];
},
post => sub {
my $exit_time = time();
my $wantarray = ( caller(0) )[5];
my $call_data = shift(@messages);
my $res = defined($wantarray) ? " = ".$self->_esc($wantarray ? pop : [pop]) : '';
my $msg = "< $call_data->[0]$res";
$msg = $self->_fmttime($exit_time) . " $msg" if $self->{-show_time};
$msg .= sprintf(" <%.6f>", $exit_time - $call_data->[1] ) if $self->{-show_spent_time};
if ($self->{-show_exit}) {
warn "$msg\n";
$prevtime = $exit_time;
}
} );
}
# defaults
$self->{-strsize} //= 32;
$self->{-show_entry} //= 1;
$self->{-show_exit} //= 1;
$self;
}
sub _esc {
my ($self, $data) = @_;
if (!defined($data)) {
"undef";
} elsif (ref $data) {
"$data";
} elsif (length($data) > $self->{-strsize}) {
double_quote(substr($data,0,$self->{-strsize}))."...";
} else {
double_quote($data);
}
}
sub _fmttime {
my ($self, $time) = @_;
my @lt = localtime($time);
my $t = $self->{-show_time};
if ($t > 3) {
# we try to remove this module's effect on relative time
# but this is negligible (all below 1ms)
my $reltime = ($time - $time0) - ($time2-$time1) - ($time4-$time3);
sprintf "%010.6f", ($t < 5 || !$prevtime ? $reltime : $time-$prevtime);
} elsif ($t > 2) {
sprintf "%.6f", $time;
} elsif ($t > 1) {
my $frac = ($time - int($time)) * 1000_000;
sprintf "%02d:%02d:%02d.%06d", $lt[2], $lt[1], $lt[0], $frac;
} else {
sprintf "%02d:%02d:%02d", $lt[2], $lt[1], $lt[0];
}
}
INIT {
$time3 = time(); # time3 = start of wrapping
while ( my ( $package, $params ) = each %import_params ) {
push @permanent_objects, __PACKAGE__->_new( $package, @$params ) if @$params;
}
( run in 1.201 second using v1.01-cache-2.11-cpan-437f7b0c052 )