X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FStats.pm;h=b22ad04dd40d86ba684237cd4ccefac88bc1d864;hb=e16a6c4e6c4d49e73b5286b3186616af14f3f554;hp=e47954fdc4bf097cd4eb2be3400843dc74c3da01;hpb=dc5f035ee51a9833b5340e3ee597f5722263042f;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Stats.pm b/lib/Catalyst/Stats.pm index e47954f..b22ad04 100644 --- a/lib/Catalyst/Stats.pm +++ b/lib/Catalyst/Stats.pm @@ -4,6 +4,7 @@ use strict; use warnings; use Time::HiRes qw/gettimeofday tv_interval/; use Text::SimpleTable (); +use Catalyst::Utils; use Tree::Simple qw/use_weak_refs/; use Tree::Simple::Visitor::FindByUID; @@ -12,9 +13,9 @@ sub new { my $root = Tree::Simple->new({t => [gettimeofday]}); bless { - enabled => 1, - stack => [ $root ], - tree => $root, + enabled => 1, + stack => [ $root ], + tree => $root, }, ref $class || $class; } @@ -31,15 +32,15 @@ sub profile { my %params; if (@_ <= 1) { - $params{comment} = shift || ""; + $params{comment} = shift || ""; } elsif (@_ % 2 != 0) { - die "profile() requires a single comment parameter or a list of name-value pairs; found " - . (scalar @_) . " values: " . join(", ", @_); + die "profile() requires a single comment parameter or a list of name-value pairs; found " + . (scalar @_) . " values: " . join(", ", @_); } else { - (%params) = @_; - $params{comment} ||= ""; + (%params) = @_; + $params{comment} ||= ""; } my $parent; @@ -47,35 +48,35 @@ sub profile { my $t = [ gettimeofday ]; if ($params{end}) { - # parent is on stack; search for matching block and splice out - for (my $i = $#{$self->{stack}}; $i > 0; $i--) { - if ($self->{stack}->[$i]->getNodeValue->{action} eq $params{end}) { - my $node = $self->{stack}->[$i]; - splice(@{$self->{stack}}, $i, 1); - # Adjust elapsed on partner node - my $v = $node->getNodeValue; - $v->{elapsed} = tv_interval($v->{t}, $t); - return $node->getUID; - } - } - # if partner not found, fall through to treat as non-closing call + # parent is on stack; search for matching block and splice out + for (my $i = $#{$self->{stack}}; $i > 0; $i--) { + if ($self->{stack}->[$i]->getNodeValue->{action} eq $params{end}) { + my $node = $self->{stack}->[$i]; + splice(@{$self->{stack}}, $i, 1); + # Adjust elapsed on partner node + my $v = $node->getNodeValue; + $v->{elapsed} = tv_interval($v->{t}, $t); + return $node->getUID; + } + } + # if partner not found, fall through to treat as non-closing call } if ($params{parent}) { - # parent is explicitly defined - $prev = $parent = $self->_get_uid($params{parent}) or return undef; + # parent is explicitly defined + $prev = $parent = $self->_get_uid($params{parent}); } if (!$parent) { - # Find previous node, which is either previous sibling or parent, for ref time. - $prev = $parent = $self->{stack}->[-1] or return undef; - my $n = $parent->getChildCount; - $prev = $parent->getChild($n - 1) if $n > 0; + # Find previous node, which is either previous sibling or parent, for ref time. + $prev = $parent = $self->{stack}->[-1] or return undef; + my $n = $parent->getChildCount; + $prev = $parent->getChild($n - 1) if $n > 0; } my $node = Tree::Simple->new({ - action => $params{begin} || "", - t => $t, - elapsed => tv_interval($prev->getNodeValue->{t}, $t), - comment => $params{comment}, + action => $params{begin} || "", + t => $t, + elapsed => tv_interval($prev->getNodeValue->{t}, $t), + comment => $params{comment}, }); $node->setUID($params{uid}) if $params{uid}; @@ -92,28 +93,24 @@ sub elapsed { sub report { my $self = shift; -# close any remaining open nodes - for (my $i = $#{$self->{stack}}; $i > 0; $i--) { - $self->profile(end => $self->{stack}->[$i]->getNodeValue->{action}); - } - - my $t = Text::SimpleTable->new( [ 62, 'Action' ], [ 9, 'Time' ] ); + my $column_width = Catalyst::Utils::term_width() - 9 - 13; + my $t = Text::SimpleTable->new( [ $column_width, 'Action' ], [ 9, 'Time' ] ); my @results; $self->{tree}->traverse( - sub { - my $action = shift; - my $stat = $action->getNodeValue; - my @r = ( $action->getDepth, - ($stat->{action} || "") . - ($stat->{action} && $stat->{comment} ? " " : "") . ($stat->{comment} ? '- ' . $stat->{comment} : ""), - $stat->{elapsed}, - $stat->{action} ? 1 : 0, - ); - $t->row( ( q{ } x $r[0] ) . $r[1], - defined $r[2] ? sprintf("%fs", $r[2]) : '??'); - push(@results, \@r); - } - ); + sub { + my $action = shift; + my $stat = $action->getNodeValue; + my @r = ( $action->getDepth, + ($stat->{action} || "") . + ($stat->{action} && $stat->{comment} ? " " : "") . ($stat->{comment} ? '- ' . $stat->{comment} : ""), + $stat->{elapsed}, + $stat->{action} ? 1 : 0, + ); + $t->row( ( q{ } x $r[0] ) . $r[1], + defined $r[2] ? sprintf("%fs", $r[2]) : '??'); + push(@results, \@r); + } + ); return wantarray ? @results : $t->draw; } @@ -126,6 +123,50 @@ sub _get_uid { return $visitor->getResult; } + +sub accept { + my $self = shift; + $self->{tree}->accept( @_ ); +} + +sub addChild { + my $self = shift; + my $node = $_[ 0 ]; + + my $stat = $node->getNodeValue; + + # do we need to fake $stat->{ t } ? + if( $stat->{ elapsed } ) { + # remove the "s" from elapsed time + $stat->{ elapsed } =~ s{s$}{}; + } + + $self->{tree}->addChild( @_ ); +} + +sub setNodeValue { + my $self = shift; + my $stat = $_[ 0 ]; + + # do we need to fake $stat->{ t } ? + if( $stat->{ elapsed } ) { + # remove the "s" from elapsed time + $stat->{ elapsed } =~ s{s$}{}; + } + + $self->{tree}->setNodeValue( @_ ); +} + +sub getNodeValue { + my $self = shift; + $self->{tree}->getNodeValue( @_ )->{ t }; +} + +sub traverse { + my $self = shift; + $self->{tree}->traverse( @_ ); +} + 1; __END__ @@ -293,14 +334,28 @@ from the previous profiling point. The 'rollup' flag indicates whether the reported time is the rolled up time for the block, or the elapsed time from the previous profiling point. +=head1 COMPATABILITY METHODS + +Some components might expect the stats object to be a regular Tree::Simple object. +We've added some compatability methods to handle this scenario: + +=head2 accept + +=head2 addChild + +=head2 setNodeValue + +=head2 getNodeValue + +=head2 traverse =head1 SEE ALSO -L. +L -=head1 AUTHOR +=head1 AUTHORS -Jon Schutz +Catalyst Contributors, see Catalyst.pm =head1 COPYRIGHT