[Jifty-commit] r4632 - in jifty/trunk: lib/Jifty/Plugin lib/Jifty/Plugin/Queries

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Thu Dec 6 19:20:54 EST 2007


Author: sartak
Date: Thu Dec  6 19:20:53 2007
New Revision: 4632

Added:
   jifty/trunk/lib/Jifty/Plugin/Queries/
   jifty/trunk/lib/Jifty/Plugin/Queries.pm
   jifty/trunk/lib/Jifty/Plugin/Queries/Dispatcher.pm
   jifty/trunk/lib/Jifty/Plugin/Queries/View.pm
Modified:
   jifty/trunk/   (props changed)

Log:
 r48738 at onn:  sartak | 2007-12-06 19:20:22 -0500
 Add a Queries plugin for examining the db queries made by your app


Added: jifty/trunk/lib/Jifty/Plugin/Queries.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Queries.pm	Thu Dec  6 19:20:53 2007
@@ -0,0 +1,133 @@
+#!/usr/bin/env perl
+package Jifty::Plugin::Queries;
+use base qw/Jifty::Plugin/;
+use strict;
+use warnings;
+
+our @requests;
+
+=head1 NAME
+
+Jifty::Plugin::Queries
+
+=head1 DESCRIPTION
+
+Query logging and reporting for your Jifty app
+
+=head1 USAGE
+
+Add the following to your site_config.yml
+
+ framework:
+   Plugins:
+     - Queries: {}
+
+This makes the following URLs available:
+
+View the top-level query report (how many queries each request had)
+
+    http://your.app/queries
+
+View the top-level query report, including zero-query requests
+
+    http://your.app/queries/all
+
+View an individual request's detailed query report (which queries were made,
+where, how long they took, etc)
+
+    http://your.app/queries/3
+
+=head2 init
+
+This makes sure that each request is wrapped with query logging.
+
+=cut
+
+sub init {
+    my $self = shift;
+    return if $self->_pre_init;
+
+    Jifty->add_trigger(
+        post_init => \&post_init
+    );
+
+    Jifty::Handler->add_trigger(
+        before_request => \&before_request
+    );
+
+    Jifty::Handler->add_trigger(
+        after_request  => \&after_request
+    );
+}
+
+=head2 post_init
+
+This sets up L<Jifty::DBI>'s query logging, and is called at the end of
+C<< Jifty->new >>
+
+=cut
+
+sub post_init {
+    Jifty->handle or return;
+
+    require Carp;
+
+    Jifty->handle->log_sql_statements(1);
+    Jifty->handle->log_sql_hook(QueryPlugin => sub { Carp::longmess });
+}
+
+=head2 before_request
+
+Clears the SQL log so you only get the request's queries
+
+=cut
+
+sub before_request {
+    Jifty->handle or return;
+
+    Jifty->handle->clear_sql_statement_log();
+}
+
+=head2 after_request
+
+Logs the queries made (at level DEBUG)
+
+=cut
+
+sub after_request {
+    Jifty->handle or return;
+
+    my $handler = shift;
+    my $cgi = shift;
+
+    my $total_time = 0;
+    my @log = Jifty->handle->sql_statement_log();
+    for (@log) {
+        my ($time, $statement, $bindings, $duration, $results) = @$_;
+
+        Jifty->log->debug(sprintf 'Query (%.3fs): "%s", with bindings: %s',
+                            $duration,
+                            $statement,
+                            join ', ', @$bindings);
+        $total_time += $duration;
+    }
+
+    push @requests, {
+        id => 1 + @requests,
+        duration => $total_time,
+        url => $cgi->url(-absolute=>1,-path_info=>1),
+        time => scalar gmtime,
+        queries => \@log,
+    };
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+

Added: jifty/trunk/lib/Jifty/Plugin/Queries/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Queries/Dispatcher.pm	Thu Dec  6 19:20:53 2007
@@ -0,0 +1,48 @@
+package Jifty::Plugin::Queries::Dispatcher;
+use warnings;
+use strict;
+
+use Jifty::Dispatcher -base;
+
+# http://your.app/queries -- display full query report
+on '/queries' => run {
+    set 'skip_zero' => 1;
+    show "/queries/all";
+};
+
+# http://your.app/queries/all -- full query report with non-query requests
+on '/queries/all' => run {
+    set 'skip_zero' => 0;
+    show "/queries/all";
+};
+
+# http://your.app/queries/clear -- clear query log
+on '/queries/clear' => run {
+    @Jifty::Plugin::Queries::requests = ();
+    set 'skip_zero' => 1;
+    redirect "/queries";
+};
+
+# http://your.app/queries/xxx -- display query report for request ID xxx
+on '/queries/#' => run {
+    abort(404) if $1 < 1;
+    my $query = $Jifty::Plugin::Queries::requests[$1 - 1]
+        or abort(404);
+    set query => $query;
+    show "/queries/one";
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Queries>, L<Jifty::Plugin::Queries::View>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+

Added: jifty/trunk/lib/Jifty/Plugin/Queries/View.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Plugin/Queries/View.pm	Thu Dec  6 19:20:53 2007
@@ -0,0 +1,108 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Queries::View;
+use Jifty::View::Declare -base;
+use Scalar::Util 'blessed';
+
+=head1 NAME
+
+Jifty::Plugin::Queries::View - Views for database queries
+
+=head1 TEMPLATES
+
+template '/queries/all' => sub {
+    my $skip_zero = get 'skip_zero';
+
+    html {
+        body {
+            h1 { "Queries" }
+            p {
+                if ($skip_zero) {
+                    a { attr { href => "/queries/all" }
+                        "Show zero-query requests" }
+                }
+                else {
+                    a { attr { href => "/queries" }
+                        "Hide zero-query requests" }
+                }
+                a { attr { href => "/queries/clear" }
+                    "Clear query log" }
+            }
+            hr {}
+
+            table {
+                row {
+                    th { "ID" }
+                    th { "Queries" }
+                    th { "Time taken" }
+                    th { "URL" }
+                };
+
+                for (@Jifty::Plugin::Queries::requests)
+                {
+                    next if $skip_zero && @{ $_->{queries} } == 0;
+
+                    row {
+                        cell { a { attr { href => "/queries/$_->{id}" }
+                                   $_->{id} } }
+
+                        cell { scalar @{ $_->{queries} } }
+                        cell { $_->{duration} }
+                        cell { $_->{url} }
+                    };
+                }
+            }
+        }
+    }
+};
+
+template '/queries/one' => sub {
+    my $query = get 'query';
+
+    html {
+        body {
+            h1 { "Queries from Request $query->{id}" }
+            ul {
+                li { "URL: $query->{url}" }
+                li { "At: " . $query->{time} }
+                li { "Time taken: $query->{duration}" }
+                li { "Queries made: " . @{ $query->{queries} } }
+            }
+            p { a { attr { href => "/queries" } "Table of Contents" } };
+
+            for ( @{ $query->{queries} } ) {
+                my ($time, $statement, $bindings, $duration, $misc) = @$_;
+                hr {};
+                h4 { pre { $statement } };
+                ul {
+                    li { "At: " . gmtime($time) };
+                    li { "Time taken: $duration" };
+                }
+                h5 { "Bindings:" }
+                ol {
+                    li { $_ } for @$bindings;
+                }
+                h5 { "Stack trace:" }
+                pre {
+                    $misc->{QueryPlugin};
+                }
+            }
+        }
+    }
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Queries>, L<Jifty::Plugin::Queries::Dispatcher>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 Best Practical Solutions
+
+This is free software and may be modified and distributed under the same terms as Perl itself.
+
+=cut
+
+1;
+


More information about the Jifty-commit mailing list