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 )