Using Plack Middleware for Better Database Debugging

Overview

This is a short article that shows how one can use the new Plack based
Catalyst to integrate middleware components designed to assist developers
understand how your database is performing. We also will discuss how having
Plack as a core Catalyst technology can assist us in broadening our
software ecosystem and involve a larger developer base. An example of the
approach taken to port a Catalyst specific role to Plack middleware is
given.

Catalyst and Plack

One of the things that has been great about being a Catalyst developer is in
how the project has been both able to maintain long term backward compatibility
as well as adopt Perl / CPAN's latest and greatest. For example, a few years
ago we ported the Catalyst codebase to Moose. This gave us a solid base
not only for the core Catalyst code, but for people building websites on top
of it.

Recently we completed the project to port Catalyst to use Plack as a core
technology. I believe this will have a powerful impact on our future coding
goals, since it will allow us to concentrate our available programming talent
on the things that make Catalyst the most powerful and flexible MVC system
for Perl. Over time I foresee much of what lives in the Catalyst::Plugin
namespace become simple wrappers on top of Plack::Middleware This is a
total win - win situation since it means we have less code that is specific to
Catalyst (meaning even more time for core developers to spend on the most
unique aspect of Catalyst) and it also means that we can levage the concentrated
efforts of developers across the CPAN ecosystem. Not everyone is a Catalyst
developer, and even those of us that are don't always need the full power and
complexity of Catalyst. Having more code in Plack Middleware means that on
those projects where I want a more light weight approach (such as Web::Simple)
I have access to the same tools as I do with Catalyst for solving common
problems like authentication and sessioning.

Plack::Middleware::DBIC::QueryLog

Plack::DBIC::QueryLog is a simple bit of Plack middleware that places an
instance of DBIx::Class::QueryLog into your Plack$env under the key
plack.middleware.dbic.querylog. It also exposes some helper methods designed
to be a consistent interface for finding and creating that key. Here's how it
might look in your application:

passthrough is one of the more useful options, since it makes sure that the
querylog allows any database events it intercepts pass through down to whatever
logging you might be doing at your Catalyst application level. In many
cases when you are developing you might use the DBIC_TRACE environment
variable to help you understand what DBIx::Class is doing (in addition to
the Querylogger). Setting the passthrough option will allow you to do both.

Catalyst::TraitFor::Model::DBIC::Schema::QueryLog::AdoptPlack

Next, lets look at how to get this new querylog exposed to Catalyst. If
you are using DBIx::Class with Catalyst, you are probably using
Catalyst::Model::DBIC::Schema. This model gives you the basic functionality
to connect to a database and expose your DBIC classes to your Catalyst
application. It also has a clean interface for extending its functionality,
which is based on Moose and Moose::Role. Basically you can wrap traits
(which are just Moose::Roles) at setup on top of your Catalyst DBIC
model. Since this is a configuration option, this means that you can have
different traits applied in different environments. For example, in production
you might be using replication, and you'd apply the trait
Catalyst::TraitFor::Model::DBIC::Schema::Replicated. On the flip side, in
development you might want to use the querylogger to help developers understand
bottlenecks in their SQL. Here's an example:

Again, a trait is just a Moose::Role that gets applied at setup time, via
configuration, which will make it easy to have your debugging trait in development
but not in production. Please review the documentation for Catalyst::Plugin::ConfigLoader
if you need a refresher on how to use a configuration file and have different
configurations for different purposes.

Plack::Middleware::Debug::DBIC::QueryLog

You are now logging queries, but you have no reporting tools or way to see the
results of that logging. Luckily, Plack::Middleware::Debug offers us a
standard approach for adding debuggin panels to your web application. Building
on top of this system is straightforward. Here's how to take that querylog and
have it displayed as a nicely formated debugging panel:

Generally I only manually add Plack::Middleware::DBIC::QueryLog when I have
some sort of logging that lives outside the debugging panels. Additionally,
you might want to only add the debug panels when you are in debugging mode, and
you might wish to pass some arguments to the underlying DBIx::Class::QueryLog
Here's a complete example:

For More Information

The source code for the three CPAN distributions discussed contain detailed
examples and test cases, which are a great next step learning tool. I highly
recommend reviewing them.

Summary

Having Plack as a core technology in Catalyst broadens the available
software ecosystem you can access in order to do you job faster and better.
However this is a two way street, so next time you are thinking of writing some
Catalyst specific code, such as a plugin or a trait for some existing tool,
you should consider how that functionality could be brought down to the Plack
level. The code written to expose DBIx::Class::QueryLog via Plack
middleware can serve as a decent example of how to do this.

Author

John Napiorkowski <jjnapiork@cpan.org> or jnap on IRC.

Thanks to Shutterstock (http://www.shutterstock.com/jobs.mhtml) for giving me
a bit of time to review and craft this advent article.