[Catalyst-commits] r7038 - in Catalyst-Runtime/5.80/trunk: . lib
lib/Catalyst t t/lib
ningu at dev.catalyst.perl.org
ningu at dev.catalyst.perl.org
Mon Oct 22 03:40:24 GMT 2007
Author: ningu
Date: 2007-10-22 03:40:24 +0100 (Mon, 22 Oct 2007)
New Revision: 7038
Added:
Catalyst-Runtime/5.80/trunk/lib/Catalyst/Stats.pm
Catalyst-Runtime/5.80/trunk/t/lib/TestAppStats.pm
Catalyst-Runtime/5.80/trunk/t/live_stats.t
Catalyst-Runtime/5.80/trunk/t/unit_stats.t
Modified:
Catalyst-Runtime/5.80/trunk/
Catalyst-Runtime/5.80/trunk/Changes
Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm
Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine.pm
Catalyst-Runtime/5.80/trunk/lib/Catalyst/Request.pm
Catalyst-Runtime/5.80/trunk/t/live_engine_request_uri.t
Log:
r27508 at haferschleim (orig r7022): andyg | 2007-10-17 08:46:11 -0700
Revert Engine.pm change from yesterday
r27509 at haferschleim (orig r7023): jrockway | 2007-10-17 12:10:22 -0700
update changelog crediting theorbtwo++ for the better error message in ensure_class_loaded
r27510 at haferschleim (orig r7024): ash | 2007-10-18 03:51:16 -0700
Test to ensure that %2B is escaped to a '+' in the output (SYBER)
r27511 at haferschleim (orig r7025): ash | 2007-10-18 03:52:55 -0700
Giving extra credit
r27512 at haferschleim (orig r7026): ash | 2007-10-18 04:11:28 -0700
Back out tests since miyagawa already added them else where.
r27513 at haferschleim (orig r7027): jrockway | 2007-10-18 21:26:34 -0700
merge the stats patch against .10 into trunk
r27552 at haferschleim (orig r7028): jrockway | 2007-10-18 22:00:40 -0700
resolve conflict in the correct direction this time :)
r27553 at haferschleim (orig r7029): jrockway | 2007-10-18 22:00:50 -0700
remove tabs that stats patch added
r27554 at haferschleim (orig r7030): jrockway | 2007-10-18 22:00:58 -0700
note in the docs that query_params is an alias for query_paramaters (fixes 03podcoverage)
Property changes on: Catalyst-Runtime/5.80/trunk
___________________________________________________________________
Name: svk:merge
- 1c72fc7c-9ce4-42af-bf25-3bfe470ff1e8:/local/Catalyst/trunk/Catalyst-Runtime:9763
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/trunk:7020
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-ChildOf:4443
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-Runtime-jrockway:5857
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-component-setup:4320
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-docs:4325
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/current/Catalyst-Runtime:5142
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst:4483
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst-Runtime:6165
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime:8339
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime-jrockway:8342
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime:6511
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime-current:10442
+ 1c72fc7c-9ce4-42af-bf25-3bfe470ff1e8:/local/Catalyst/trunk/Catalyst-Runtime:9763
4ad37cd2-5fec-0310-835f-b3785c72a374:/Catalyst-Runtime/5.70/trunk:7030
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-ChildOf:4443
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-Runtime-jrockway:5857
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-component-setup:4320
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/Catalyst-docs:4325
4ad37cd2-5fec-0310-835f-b3785c72a374:/branches/current/Catalyst-Runtime:5142
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst:4483
4ad37cd2-5fec-0310-835f-b3785c72a374:/trunk/Catalyst-Runtime:6165
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime:8339
d7608cd0-831c-0410-93c0-e5b306c3c028:/local/Catalyst/Catalyst-Runtime-jrockway:8342
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime:6511
e56d974f-7718-0410-8b1c-b347a71765b2:/local/Catalyst-Runtime-current:10442
Modified: Catalyst-Runtime/5.80/trunk/Changes
===================================================================
--- Catalyst-Runtime/5.80/trunk/Changes 2007-10-19 21:42:40 UTC (rev 7037)
+++ Catalyst-Runtime/5.80/trunk/Changes 2007-10-22 02:40:24 UTC (rev 7038)
@@ -10,11 +10,13 @@
- Fixed bug in HTTP engine where writes could fail with
'Resource temporarily unavailable'.
- Fixed bug where %2b in query parameter is doubly decoded to ' ', instead of '+'
- (Gavin Henry, Tatsuhiko Miyagawa)
+ (Gavin Henry, Tatsuhiko Miyagawa, Oleg Pronin)
- Fixed bug where req->base and req->uri would include a port number when running
in SSL mode.
- Removed unnecessary sprintf in debug mode that caused warnings on locales where
commas are used for decimal markers.
+ - Improved error message for case when server picks up editor save
+ files as module names. (James Mastros)
5.7010 2007-08-22 07:41:00
- Resource forks in 5.7009
Modified: Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine.pm 2007-10-19 21:42:40 UTC (rev 7037)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst/Engine.pm 2007-10-22 02:40:24 UTC (rev 7038)
@@ -4,10 +4,10 @@
use base 'Class::Accessor::Fast';
use CGI::Simple::Cookie;
use Data::Dump qw/dump/;
+use Errno 'EWOULDBLOCK';
use HTML::Entities;
use HTTP::Body;
use HTTP::Headers;
-use IO::Select ();
use URI::QueryParam;
use Scalar::Util ();
@@ -622,29 +622,30 @@
$self->{_prepared_write} = 1;
}
- my $wrote;
- my $len = length($buffer);
+ my $len = length($buffer);
+ my $wrote = syswrite STDOUT, $buffer;
- my $sel = IO::Select->new();
- $sel->add( \*STDOUT );
+ if ( !defined $wrote && $! == EWOULDBLOCK ) {
+ # Unable to write on the first try, will retry in the loop below
+ $wrote = 0;
+ }
- while ( $sel->can_write() ) {
- $wrote ||= 0;
-
- my $ret = syswrite STDOUT, $buffer, $CHUNKSIZE, $wrote;
- if ( defined $ret ) {
- $wrote += $ret;
+ if ( defined $wrote && $wrote < $len ) {
+ # We didn't write the whole buffer
+ while (1) {
+ my $ret = syswrite STDOUT, $buffer, $CHUNKSIZE, $wrote;
+ if ( defined $ret ) {
+ $wrote += $ret;
+ }
+ else {
+ next if $! == EWOULDBLOCK;
+ return;
+ }
+
+ last if $wrote >= $len;
}
- else {
- # Write error
- return;
- }
-
- last if $wrote >= $len;
}
- $sel->remove( \*STDOUT );
-
return $wrote;
}
Modified: Catalyst-Runtime/5.80/trunk/lib/Catalyst/Request.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst/Request.pm 2007-10-19 21:42:40 UTC (rev 7037)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst/Request.pm 2007-10-22 02:40:24 UTC (rev 7038)
@@ -403,6 +403,8 @@
=head2 $req->query_parameters
+=head2 $req->query_params
+
Returns a reference to a hash containing query string (GET) parameters. Values can
be either a scalar or an arrayref containing scalars.
Added: Catalyst-Runtime/5.80/trunk/lib/Catalyst/Stats.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst/Stats.pm (rev 0)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst/Stats.pm 2007-10-22 02:40:24 UTC (rev 7038)
@@ -0,0 +1,312 @@
+package Catalyst::Stats;
+
+use strict;
+use warnings;
+use Time::HiRes qw/gettimeofday tv_interval/;
+use Text::SimpleTable ();
+use Tree::Simple qw/use_weak_refs/;
+use Tree::Simple::Visitor::FindByUID;
+
+sub new {
+ my $class = shift;
+
+ my $root = Tree::Simple->new({t => [gettimeofday]});
+ bless {
+ enabled => 1,
+ stack => [ $root ],
+ tree => $root,
+ }, ref $class || $class;
+}
+
+sub enable {
+ my ($self, $enable) = @_;
+
+ $self->{enabled} = $enable;
+}
+
+sub profile {
+ my $self = shift;
+
+ return unless $self->{enabled};
+
+ my %params;
+ if (@_ <= 1) {
+ $params{comment} = shift || "";
+ }
+ elsif (@_ % 2 != 0) {
+ die "profile() requires a single comment parameter or a list of name-value pairs; found "
+ . (scalar @_) . " values: " . join(", ", @_);
+ }
+ else {
+ (%params) = @_;
+ $params{comment} ||= "";
+ }
+
+ my $parent;
+ my $prev;
+ 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
+ }
+ if ($params{parent}) {
+ # parent is explicitly defined
+ $prev = $parent = $self->_get_uid($params{parent}) or return undef;
+ }
+ 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;
+ }
+
+ my $node = Tree::Simple->new({
+ action => $params{begin} || "",
+ t => $t,
+ elapsed => tv_interval($prev->getNodeValue->{t}, $t),
+ comment => $params{comment},
+ });
+ $node->setUID($params{uid}) if $params{uid};
+
+ $parent->addChild($node);
+ push(@{$self->{stack}}, $node) if $params{begin};
+
+ return $node->getUID;
+}
+
+sub elapsed {
+ return tv_interval(shift->{tree}->getNodeValue->{t});
+}
+
+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 @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);
+ }
+ );
+ return wantarray ? @results : $t->draw;
+}
+
+sub _get_uid {
+ my ($self, $uid) = @_;
+
+ my $visitor = Tree::Simple::Visitor::FindByUID->new;
+ $visitor->searchForUID($uid);
+ $self->{tree}->accept($visitor);
+ return $visitor->getResult;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Catalyst::Stats - Catalyst Timing Statistics Class
+
+=head1 SYNOPSIS
+
+ $stats = $c->stats;
+ $stats->enable(1);
+ $stats->profile($comment);
+ $stats->profile(begin => $block_name, comment =>$comment);
+ $stats->profile(end => $block_name);
+ $elapsed = $stats->elapsed;
+ $report = $stats->report;
+
+See L<Catalyst>.
+
+=head1 DESCRIPTION
+
+This module provides the default, simple timing stats collection functionality for Catalyst.
+If you want something different set C<< MyApp->stats_class >> in your application module,
+e.g.:
+
+ __PACKAGE__->stats_class( "My::Stats" );
+
+If you write your own, your stats object is expected to provide the interface described here.
+
+Catalyst uses this class to report timings of component actions. You can add
+profiling points into your own code to get deeper insight. Typical usage might
+be like this:
+
+ sub mysub {
+ my ($c, ...) = @_;
+ $c->stats->profile(begin => "mysub");
+ # code goes here
+ ...
+ $c->stats->profile("starting critical bit");
+ # code here too
+ ...
+ $c->stats->profile("completed first part of critical bit");
+ # more code
+ ...
+ $c->stats->profile("completed second part of critical bit");
+ # more code
+ ...
+ $c->stats->profile(end => "mysub");
+ }
+
+Supposing mysub was called from the action "process" inside a Catalyst
+Controller called "service", then the reported timings for the above example
+might look something like this:
+
+ .----------------------------------------------------------------+-----------.
+ | Action | Time |
+ +----------------------------------------------------------------+-----------+
+ | /service/process | 1.327702s |
+ | mysub | 0.555555s |
+ | - starting critical bit | 0.111111s |
+ | - completed first part of critical bit | 0.333333s |
+ | - completed second part of critical bit | 0.111000s |
+ | /end | 0.000160s |
+ '----------------------------------------------------------------+-----------'
+
+which means mysub took 0.555555s overall, it took 0.111111s to reach the
+critical bit, the first part of the critical bit took 0.333333s, and the second
+part 0.111s.
+
+
+=head1 METHODS
+
+=head2 new
+
+Constructor.
+
+ $stats = Catalyst::Stats->new;
+
+=head2 enable
+
+ $stats->enable(0);
+ $stats->enable(1);
+
+Enable or disable stats collection. By default, stats are enabled after object creation.
+
+=head2 profile
+
+ $stats->profile($comment);
+ $stats->profile(begin => $block_name, comment =>$comment);
+ $stats->profile(end => $block_name);
+
+Marks a profiling point. These can appear in pairs, to time the block of code
+between the begin/end pairs, or by themselves, in which case the time of
+execution to the previous profiling point will be reported.
+
+The argument may be either a single comment string or a list of name-value
+pairs. Thus the following are equivalent:
+
+ $stats->profile($comment);
+ $stats->profile(comment => $comment);
+
+The following key names/values may be used:
+
+=over 4
+
+=item * begin => ACTION
+
+Marks the beginning of a block. The value is used in the description in the
+timing report.
+
+=item * end => ACTION
+
+Marks the end of the block. The name given must match a previous 'begin'.
+Correct nesting is recommended, although this module is tolerant of blocks that
+are not correctly nested, and the reported timings should accurately reflect the
+time taken to execute the block whether properly nested or not.
+
+=item * comment => COMMENT
+
+Comment string; use this to describe the profiling point. It is combined with
+the block action (if any) in the timing report description field.
+
+=item * uid => UID
+
+Assign a predefined unique ID. This is useful if, for whatever reason, you wish
+to relate a profiling point to a different parent than in the natural execution
+sequence.
+
+=item * parent => UID
+
+Explicitly relate the profiling point back to the parent with the specified UID.
+The profiling point will be ignored if the UID has not been previously defined.
+
+=back
+
+Returns the UID of the current point in the profile tree. The UID is
+automatically assigned if not explicitly given.
+
+=head2 elapsed
+
+ $elapsed = $stats->elapsed
+
+Get the total elapsed time (in seconds) since the object was created.
+
+=head2 report
+
+ print $stats->report ."\n";
+ $report = $stats->report;
+ @report = $stats->report;
+
+In scalar context, generates a textual report. In array context, returns the
+array of results where each row comprises:
+
+ [ depth, description, time, rollup ]
+
+The depth is the calling stack level of the profiling point.
+
+The description is a combination of the block name and comment.
+
+The time reported for each block is the total execution time for the block, and
+the time associated with each intermediate profiling point is the elapsed time
+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 SEE ALSO
+
+L<Catalyst>.
+
+=head1 AUTHOR
+
+Jon Schutz
+
+=head1 COPYRIGHT
+
+This program is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
Modified: Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm 2007-10-19 21:42:40 UTC (rev 7037)
+++ Catalyst-Runtime/5.80/trunk/lib/Catalyst.pm 2007-10-22 02:40:24 UTC (rev 7038)
@@ -54,12 +54,14 @@
__PACKAGE__->mk_classdata($_)
for qw/components arguments dispatcher engine log dispatcher_class
- engine_class context_class request_class response_class setup_finished/;
+ engine_class context_class request_class response_class stats_class
+ setup_finished/;
__PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
__PACKAGE__->engine_class('Catalyst::Engine::CGI');
__PACKAGE__->request_class('Catalyst::Request');
__PACKAGE__->response_class('Catalyst::Response');
+__PACKAGE__->stats_class('Catalyst::Stats');
# Remember to update this in Catalyst::Runtime as well!
@@ -240,6 +242,17 @@
Specifies log level.
+=head2 -Stats
+
+Enables statistics collection and reporting. You can also force this setting
+from the system environment with CATALYST_STATS or <MYAPP>_STATS. The
+environment settings override the application, with <MYAPP>_STATS having the
+highest priority.
+
+e.g.
+
+ use Catalyst qw/-Stats=1/
+
=head1 METHODS
=head2 INFORMATION ABOUT THE CURRENT REQUEST
@@ -813,6 +826,7 @@
$class->setup_plugins( delete $flags->{plugins} );
$class->setup_dispatcher( delete $flags->{dispatcher} );
$class->setup_engine( delete $flags->{engine} );
+ $class->setup_stats( delete $flags->{stats} );
for my $flag ( sort keys %{$flags} ) {
@@ -1198,13 +1212,13 @@
return $c->state;
}
- my $stats_info = $c->_stats_start_execute( $code ) if $c->debug;
+ my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
push( @{ $c->stack }, $code );
eval { $c->state( &$code( $class, $c, @{ $c->req->args } ) || 0 ) };
- $c->_stats_finish_execute( $stats_info ) if $c->debug and $stats_info;
+ $c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
my $last = pop( @{ $c->stack } );
@@ -1252,51 +1266,32 @@
}
}
- my $node = Tree::Simple->new(
- {
- action => $action,
- elapsed => undef, # to be filled in later
- comment => "",
- }
- );
- $node->setUID( "$code" . $c->counter->{"$code"} );
-
# is this a root-level call or a forwarded call?
if ( $callsub =~ /forward$/ ) {
# forward, locate the caller
if ( my $parent = $c->stack->[-1] ) {
- my $visitor = Tree::Simple::Visitor::FindByUID->new;
- $visitor->searchForUID(
- "$parent" . $c->counter->{"$parent"} );
- $c->stats->accept($visitor);
- if ( my $result = $visitor->getResult ) {
- $result->addChild($node);
- }
+ $c->stats->profile(begin => $action,
+ parent => "$parent" . $c->counter->{"$parent"});
}
else {
# forward with no caller may come from a plugin
- $c->stats->addChild($node);
+ $c->stats->profile(begin => $action);
}
}
else {
-
+
# root-level call
- $c->stats->addChild($node);
+ $c->stats->profile(begin => $action);
}
+ return $action;
- return {
- start => [gettimeofday],
- node => $node,
- };
}
sub _stats_finish_execute {
my ( $c, $info ) = @_;
- my $elapsed = tv_interval $info->{start};
- my $value = $info->{node}->getNodeValue;
- $value->{elapsed} = sprintf( '%fs', $elapsed );
+ $c->stats->profile(end => $info);
}
=head2 $c->_localize_fields( sub { }, \%keys );
@@ -1352,22 +1347,11 @@
$c->finalize_body;
}
- if ($c->debug) {
- my $elapsed = tv_interval($c->stats->getNodeValue);
+ if ($c->use_stats) {
+ my $elapsed = sprintf '%f', $c->stats->elapsed;
my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
-
- my $t = Text::SimpleTable->new( [ 62, 'Action' ], [ 9, 'Time' ] );
- $c->stats->traverse(
- sub {
- my $action = shift;
- my $stat = $action->getNodeValue;
- $t->row( ( q{ } x $action->getDepth ) . $stat->{action} . $stat->{comment},
- $stat->{elapsed} || '??' );
- }
- );
-
$c->log->info(
- "Request took ${elapsed}s ($av/s)\n" . $t->draw . "\n" );
+ "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
}
return $c->response->status;
@@ -1567,8 +1551,8 @@
}
);
+ $c->stats($class->stats_class->new)->enable($c->use_stats);
if ( $c->debug ) {
- $c->stats(Tree::Simple->new([gettimeofday]));
$c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
}
@@ -2125,6 +2109,26 @@
=cut
+=head2 $c->setup_stats
+
+Sets up timing statistics class.
+
+=cut
+
+sub setup_stats {
+ my ( $class, $stats ) = @_;
+
+ Catalyst::Utils::ensure_class_loaded($class->stats_class);
+
+ my $env = Catalyst::Utils::env_value( $class, 'STATS' );
+ if ( defined($env) ? $env : ($stats || $class->debug ) ) {
+ no strict 'refs';
+ *{"$class\::use_stats"} = sub { 1 };
+ $class->log->debug('Statistics enabled');
+ }
+}
+
+
=head2 $c->registered_plugins
Returns a sorted list of the plugins which have either been stated in the
@@ -2188,6 +2192,24 @@
Returns an arrayref of the internal execution stack (actions that are
currently executing).
+=head2 $c->stats_class
+
+Returns or sets the stats (timing statistics) class.
+
+=head2 $c->use_stats
+
+Returns 1 when stats collection is enabled. Stats collection is enabled
+when the -Stats options is set, debug is on or when the <MYAPP>_STATS
+environment variable is set.
+
+Note that this is a static method, not an accessor and should be overloaded
+by declaring "sub use_stats { 1 }" in your MyApp.pm, not by calling $c->use_stats(1).
+
+=cut
+
+sub use_stats { 0 }
+
+
=head2 $c->write( $data )
Writes $data to the output stream. When using this method directly, you
Added: Catalyst-Runtime/5.80/trunk/t/lib/TestAppStats.pm
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/lib/TestAppStats.pm (rev 0)
+++ Catalyst-Runtime/5.80/trunk/t/lib/TestAppStats.pm 2007-10-22 02:40:24 UTC (rev 7038)
@@ -0,0 +1,31 @@
+use strict;
+use warnings;
+
+package TestAppStats;
+
+use Catalyst qw/
+ -Stats=1
+/;
+
+our $VERSION = '0.01';
+our @log_messages;
+
+__PACKAGE__->config( name => 'TestAppStats', root => '/some/dir' );
+
+__PACKAGE__->log(TestAppStats::Log->new);
+
+__PACKAGE__->setup;
+
+# Return log messages from previous request
+sub default : Private {
+ my ( $self, $c ) = @_;
+ $c->stats->profile("test");
+ $c->res->body(join("\n", @log_messages));
+ @log_messages = ();
+}
+
+package TestAppStats::Log;
+use base qw/Catalyst::Log/;
+
+sub info { push(@log_messages, @_); }
+sub debug { push(@log_messages, @_); }
Modified: Catalyst-Runtime/5.80/trunk/t/live_engine_request_uri.t
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/live_engine_request_uri.t 2007-10-19 21:42:40 UTC (rev 7037)
+++ Catalyst-Runtime/5.80/trunk/t/live_engine_request_uri.t 2007-10-22 02:40:24 UTC (rev 7038)
@@ -119,3 +119,4 @@
ok( $response->is_success, 'Response Successful 2xx' );
is( $response->header( 'X-Catalyst-warnings' ), 0, 'no warnings emitted' );
}
+
Added: Catalyst-Runtime/5.80/trunk/t/live_stats.t
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/live_stats.t (rev 0)
+++ Catalyst-Runtime/5.80/trunk/t/live_stats.t 2007-10-22 02:40:24 UTC (rev 7038)
@@ -0,0 +1,22 @@
+#!perl
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use Test::More tests => 5;
+use Catalyst::Test 'TestAppStats';
+
+{
+ ok( my $response = request('http://localhost/'), 'Request' );
+ ok( $response->is_success, 'Response Successful 2xx' );
+}
+{
+ ok( my $response = request('http://localhost/'), 'Request' );
+ ok( $response->is_success, 'Response Successful 2xx' );
+ ok( $response->content =~ m/\/default.*?[\d.]+s.*- test.*[\d.]+s/s, 'Stats report');
+
+}
+
Added: Catalyst-Runtime/5.80/trunk/t/unit_stats.t
===================================================================
--- Catalyst-Runtime/5.80/trunk/t/unit_stats.t (rev 0)
+++ Catalyst-Runtime/5.80/trunk/t/unit_stats.t 2007-10-22 02:40:24 UTC (rev 7038)
@@ -0,0 +1,88 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 6;
+use Time::HiRes qw/gettimeofday/;
+
+my @fudge_t = ( 0, 0 );
+BEGIN {
+ no warnings;
+ *Time::HiRes::gettimeofday = sub () { return @fudge_t };
+}
+
+BEGIN { use_ok("Catalyst::Stats") };
+
+
+my $stats = Catalyst::Stats->new;
+is (ref($stats), "Catalyst::Stats", "new");
+
+my @expected; # level, string, time
+
+$fudge_t[0] = 1;
+ok($stats->profile("single comment arg"), "profile");
+push(@expected, [ 0, "- single comment arg", 1, 0 ]);
+
+$fudge_t[0] = 3;
+$stats->profile(comment => "hash comment arg");
+push(@expected, [ 0, "- hash comment arg", 2, 0 ]);
+
+$fudge_t[0] = 10;
+$stats->profile(begin => "block", comment => "start block");
+push(@expected, [ 0, "block - start block", 4, 1 ]);
+
+
+$fudge_t[0] = 11;
+$stats->profile("inside block");
+push(@expected, [ 1, "- inside block", 1, 0 ]);
+
+$fudge_t[1] = 100000;
+my $uid = $stats->profile(begin => "nested block", uid => "boo");
+push(@expected, [ 1, "nested block", 0.7, 1 ]);
+is ($uid, "boo", "set UID");
+
+$stats->enable(0);
+$fudge_t[1] = 150000;
+$stats->profile("this shouldn't appear");
+$stats->enable(1);
+
+$fudge_t[1] = 200000;
+$stats->profile(begin => "double nested block 1");
+push(@expected, [ 2, "double nested block 1", 0.2, 1 ]);
+
+$stats->profile(comment => "attach to uid", parent => $uid);
+
+$fudge_t[1] = 250000;
+$stats->profile(begin => "badly nested block 1");
+push(@expected, [ 3, "badly nested block 1", 0.35, 1 ]);
+
+$fudge_t[1] = 300000;
+$stats->profile(comment => "interleave 1");
+push(@expected, [ 4, "- interleave 1", 0.05, 0 ]);
+
+$fudge_t[1] = 400000; # end double nested block time
+$stats->profile(end => "double nested block 1");
+
+$fudge_t[1] = 500000;
+$stats->profile(comment => "interleave 2");
+push(@expected, [ 4, "- interleave 2", 0.2, 0 ]);
+
+$fudge_t[1] = 600000; # end badly nested block time
+$stats->profile(end => "badly nested block 1");
+
+$fudge_t[1] = 800000; # end nested block time
+$stats->profile(end => "nested block");
+
+$fudge_t[0] = 14; # end block time
+$fudge_t[1] = 0;
+$stats->profile(end => "block", comment => "end block");
+
+push(@expected, [ 2, "- attach to uid", 0.1, 0 ]);
+
+
+my @report = $stats->report;
+is_deeply(\@report, \@expected, "report");
+
+is ($stats->elapsed, 14, "elapsed");
+
More information about the Catalyst-commits
mailing list