CGI-Application-Plugin-DBIProfile
view release on metacpan or search on metacpan
lib/CGI/Application/Plugin/DBIProfile.pm view on Meta::CPAN
package CGI::Application::Plugin::DBIProfile;
use strict;
use CGI::Application::Plugin::DBIProfile::Driver;
# DBI::ProfileData doesn't support reading from filehandles.
#use DBI::ProfileData;
use CGI::Application::Plugin::DBIProfile::Data;
use IO::Scalar;
use HTML::Template;
use Data::JavaScript;
use vars qw($VERSION);
our $VERSION = '0.07';
sub import
{
my $c = scalar caller;
if ($ENV{CAP_DBIPROFILE_EXEC})
{
$c->add_callback( 'prerun', \&_start );
# use devpopup if installed, or do our own thing.
if ($c->can('devpopup') && $ENV{'CAP_DEVPOPUP_EXEC'})
{
$c->add_callback( 'devpopup_report', \&_devpopup_stop);
} else {
$c->add_callback( 'postrun', \&_stop);
}
}
}
# _start : clear anything that is currently stored (incase stuff ran without us)
sub _start
{
my $self = shift;
_empty_profile();
}
# _stop : standalone report output, called in postrun hook.
sub _stop
{
my ($self, $output) = @_;
# header handling borrowed from CAP::DevPopup
return unless $self->header_type eq 'header'; # don't operate on redirects or 'none'
my %props = $self->header_props;
my ($type) = grep /type/i, keys %props;
return if defined $type and # no type defaults to html, so we have work to do.
$props{$type} !~ /html/i; # else skip any other types.
our $TEMPLATE2;
my $template = HTML::Template->new(scalarref => \$TEMPLATE2 );
$template->param(page_body => _build_content($self) );
my $content = $template->output();
_open_window($self, $content, $output);
_empty_profile();
}
# _devpopup_stop : similar to _stop, but compatable with CAP:DevPopup
sub _devpopup_stop
{
my $self = shift;
my $output = shift;
my $content = _build_content($self);
$self->devpopup->add_report(
title => 'DBI Profile',
summary => 'DBI statement profiling',
report => qq(
<style type="text/css">
tr.even{background-color:#eee}
</style>
<table><tbody> $content </tbody></table>
)
);
_empty_profile();
}
# clear profile if running in per-request (unless running in per-process)
sub _empty_profile
{
unless ($ENV{CAP_DBIPROFILE_PERPROCESS}) {
CGI::Application::Plugin::DBIProfile::Driver->empty();
}
}
# main content builder. Builds datasets, and pushs to template.
sub _build_content
{
my $self = shift;
my %opts = (
number => $self->param('__DBIProfile_number') || 10,
);
my @pages;
# for each sort type, add a graph in a hidden div
foreach my $sort (qw(total count shortest longest))
{
my $page = {};
my ($nodes, $data) = _get_nodes($self, (%opts, sort => $sort) );
my @legends = map { $nodes->[$_][7] } (0 .. $#$nodes);
my $count = 1;
$$page{sort} = $sort;
$$page{legend_loop} = [ map { { number => $count++, legend => $_ } } @legends];
$$page{profile_title} = _page_title($self, (%opts, sort => $sort) );
$$page{profile_text} = join("\n\n", map { $data->format($nodes->[$_]) } (0 .. $#$nodes));
$$page{profile_graph} = _dbiprof_graph($self, (%opts, sort => $sort, nodes => $nodes) );
push(@pages, $page);
}
our $TEMPLATE;
my $template = HTML::Template->new(scalarref => \$TEMPLATE,
loop_context_vars => 1, );
$template->param(profile_pages => \@pages);
# add full text only dump of all data (well, last 1000 queries)
my ($nodes, $data) = _get_nodes($self, number => 1000, sort => 'count');
$template->param('profile_full_text', join("\n\n", map { $data->format($nodes->[$_]) } (0 .. $#$nodes)) );
lib/CGI/Application/Plugin/DBIProfile.pm view on Meta::CPAN
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td valign="top">
<h2 onclick="swap('#DBIPS_t_<tmpl_var sort>', '#DBIPR_t_<tmpl_var sort>');">Full Text Profile Dump</h2>
<div id="#DBIPS_t_<tmpl_var sort>" class="report_summary"></div>
<div id="#DBIPR_t_<tmpl_var sort>" class="report_full" style="display:none">
<span style="white-space: pre;"><tmpl_var profile_text></span>
</div>
</td>
</tr>
</table>
</div>
</tmpl_loop>
<!-- full dump of log -->
<h2 onclick="swap('#DBIPS_full', '#DBIPR_full');">Full Text Dump By Runtime</h2>
<div id="#DBIPS_full" class="report_summary"></div>
<div id="#DBIPR_full" class="report_full" style="display:none">
<span style="white-space: pre;"><tmpl_var profile_full_text></span>
</div>
</td>
</tr></table>
END
1;
__END__
=head1 NAME
CGI::Application::Plugin::DBIProfile - DBI profiling plugin
=head1 SYNOPSIS
# Set env in apache or in perl.
$ENV{DBI_PROFILE} = '2/CGI::Application::Plugin::DBIProfile::Driver';
use CGI::Application::Plugin::DevPopup;
use CGI::Application::Plugin::DBIProfile;
The rest of your application follows
...
=head1 INSTALLATION
To install this module, run the following commands:
perl Makefile.PL
make
make test
make install
=head1 DESCRIPTION
CGI::Application::Plugin::DBIProfile provides popup (using CAP::DevPopup if available) holding DBI Profile information (see L<DBI::Profile>, L<DBI::ProfileDumper>). It will output both graphed output and a DBI::ProfileDumper report.
=head1 CONFIGURATION
To enable, set the DBI_PROFILE environment variables. For example
=over
=item in apache config for cgi
SetVar DBI_PROFILE 2/CGI::Application::Plugin::DBIProfile::Driver
SetVar CAP_DBIPROFILE_EXEC 1
=item in apache config for mod_perl
PerlSetVar DBI_PROFILE 2/CGI::Application::Plugin::DBIProfile::Driver
PerlSetVar CAP_DBIPROFILE_EXEC 1
=item in your CAP module
BEGIN {
$ENV{DBI_PROFILE} = '2/CGI::Application::Plugin::DBIProfile::Driver';
$ENV{CAP_DBIPROFILE_EXEC} = 1;
}
=back
If you disable it, be sure to unset the DBI_PROFILE env var, as it will continue to accumulate stats regardless of the setting of CAP_DBIPROFILE_EXEC, you just won't see them.
=head2 MODES OF OPERATION
It has two modes of opperation; per-request or per-process. In a CGI environment, there is no difference.
=over
=item per-request - this is the default.
=item per-process - set the following env var to a true value.
CAP_DBIPROFILE_PERPROCESS 1
=back
Under mod_perl, the per-request setup will show the DBI Profile specific to each page hit.
The per-process setup will show the DBI Profile that has accumulated for the life of the apache process you are hitting.
Please note, running under the per-process setting can cause your memory usage to grow significantly, as the profile data is never cleared.
=head2 GRAPHING PLUGINS
The default graphing module is L<CGI::Application::Plugin::DBIProfile::Graph::HTML>, which generates a minimal inline HTML graph. To change which graphing plugin is used, it's just another environment variable (no need to set this if you like the def...
CAP_DBIPROFILE_GRAPHMODULE Your::Graph::Module::Name
Please see L<CGI::Application::Plugin::DBIProfile::Graph::HTML> for information on writing new graph modules.
=head1 TODO
Tests. None exist at this time.
Other graphing plugins (Plotr, Open Flash Chart, GraphML using Graph::Easy).
( run in 0.668 second using v1.01-cache-2.11-cpan-364913b4093 )