Catalyst-Controller-LeakTracker
view release on metacpan or search on metacpan
lib/Catalyst/Controller/LeakTracker.pm view on Meta::CPAN
#!/usr/bin/perl
package Catalyst::Controller::LeakTracker;
use parent qw(Catalyst::Controller);
use Moose;
our $VERSION = "0.08";
use Data::Dumper ();
use Devel::Cycle ();
use Devel::Size ();
use Tie::RefHash::Weak ();
use YAML::XS ();
use Scalar::Util qw(weaken);
use namespace::clean -except => "meta";
{
package Catalyst::Controller::LeakTracker::Template;
use Template::Declare::Tags 'HTML'; # conflicts with Moose
}
my $size_of_empty_array = Devel::Size::total_size([]);
sub end : Private { } # don't get Root's one
sub order_by {
my ( $self, $objects, $field, $mode ) = @_;
return () unless @$objects;
my $order_by_meth = {
num => sub {
sort { $a->{$field} <=> $b->{$field} } @{$_[0]}
},
num_desc => sub {
sort { $b->{$field} <=> $a->{$field} } @{$_[0]}
},
lex => sub {
sort { $a->{$field} cmp $b->{$field} } @{$_[0]}
},
lex_desc => sub {
sort { $b->{$field} cmp $a->{$field} } @{$_[0]}
},
};
my $order_by_map;
if ( $mode && $mode eq 'desc' ) {
$order_by_map = {
( map {
$_ => $order_by_meth->{'num_desc'}
} qw/id time leaks size/ ),
( map {
$_ => $order_by_meth->{'lex_desc'}
} qw/action uri class/ ),
};
}
else {
$order_by_map = {
( map {
$_ => $order_by_meth->{'num'}
} qw/id time leaks size/ ),
( map {
$_ => $order_by_meth->{'lex'}
} qw/action uri class/ ),
};
}
if ( my $meth = $order_by_map->{$field} ) {
return $meth->($objects);
}
else {
return @$objects;
}
}
lib/Catalyst/Controller/LeakTracker.pm view on Meta::CPAN
};
a {
attr {
href => $c->req->uri_with({
order_by => $_,
order_by_desc => $desc,
})
} $_
};
}
} @fields
};
foreach my $leak ( @leaks ) {
row {
foreach my $field ( @fields ) {
my $formatter = $fmt{$field};
cell {
attr { style => "padding: 0.2em" }
$formatter->($leak->{$field});
}
}
}
}
}
};
$c->res->content_type("text/html");
$c->res->body( "" . do { package Catalyst::Controller::LeakTracker::Template;
html {
head { }
body {
h1 { "Leaks" }
pre { $leaks->() }
$log ? (
h1 { "Events" }
pre { $log_output }
) : ()
}
}
});
}
sub make_leak : Chained {
my ( $self, $c, $n ) = @_;
$n ||= 1;
$n = 300 if $n > 300;
for ( 1 .. $n ) {
my $object = bless {}, "class::a";
$object->{foo}{self} = $object;
}
my $object2 = bless {}, "class::b";
$object2->{foo}{self} = $object2;
weaken($object2->{foo}{self});
my $object3 = bless [], "class::c";
push @$object3, $object3, map { [ 1 .. $n ] } 1 .. $n;
$c->res->body("it leaks " . ( $n + 1 ) . " objects");
}
__PACKAGE__;
__END__
=pod
=head1 NAME
Catalyst::Controller::LeakTracker - Inspect leaks found by L<Catalyst::Plugin::LeakTracker>
=head1 SYNOPSIS
# in MyApp.pm
package MyApp;
use Catalyst qw(
LeakTracker
);
#### in SomeController.pm
package MyApp::Controller::Leaks;
use Moose;
use parent qw(Catalyst::Controller::LeakTracker);
sub index :Path :Args(0) {
my ( $self, $c ) = @_;
$c->forward("list_requests"); # redirect to request listing view
}
=head1 DESCRIPTION
This controller uses L<Catalyst::Controller::LeakTracker> to display leak info
on a per request basis.
=head1 ACTIONS
=over 4
=item list_requests
List the leaking requests this process has handled so far.
If the C<all> parameter is set to a true value, then all requests (even non
leaking ones) are listed.
=item request $request_id
Detail the leaks for a given request, and also dump the event log for that request.
=item object $request_id $event_id
( run in 2.193 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )