DBIx::Class::QueryLog - Log queries for later analysis.


DBIx-Class-QueryLog documentation Contained in the DBIx-Class-QueryLog distribution.

Index


Code Index:

NAME

Top

DBIx::Class::QueryLog - Log queries for later analysis.

SYNOPSIS

Top

DBIx::Class::QueryLog 'logs' each transaction and query executed so you can analyze what happened in the 'session'. It must be installed as the debugobj in DBIx::Class:

    use DBIx::Class::QueryLog;
    use DBIx::Class::QueryLog::Analyzer;

    my $schema = ... # Get your schema!
    my $ql = DBIx::Class::QueryLog->new;
    $schema->storage->debugobj($ql);
    $schema->storage->debug(1);
      ... # do some stuff!
    my $ana = DBIx::Class::QueryLog::Analyzer->new({ querylog => $ql });
    my @queries = $ana->get_sorted_queries;

Every transaction and query executed will have a corresponding Transaction and Query object stored in order of execution, like so:

    Query
    Query
    Transaction
    Query

This array can be retrieved with the log method. Queries executed inside a transaction are stored inside their Transaction object, not inside the QueryLog directly.

See DBIx::Class::QueryLog::Analyzer for options on digesting the results of a QueryLog session.

If you wish to have the QueryLog collecting results, and the normal trace output of SQL queries from DBIx::Class, then set passthrough to 1

  $ql->passthrough(1);

BUCKETS

Top

Sometimes you want to break your analysis down into stages. To segregate the queries and transactions, simply set the bucket and run some queries:

  $ql->bucket('selects');
  $schema->resultset('Foo')->find(..);
  # Some queries
  $ql->bucket('updates');
  $foo->update({ name => 'Gorch' });
  $ql->bucket('something else);
  ...

Any time a query or transaction is completed the QueryLog's current bucket will be copied into it so that the Analyzer can later use it. See the get_totaled_queries method and it's optional parameter.

METHODS

Top

new

Create a new DBIx::Class::QueryLog.

bucket

Set the current bucket for this QueryLog. This bucket will be copied to any transactions or queries that finish.

time_elapsed

Returns the total time elapsed for ALL transactions and queries in this log.

count

Returns the number of queries executed in this QueryLog

reset

Reset this QueryLog by removing all transcations and queries.

add_to_log

Add this provided Transaction or Query to the log.

txn_begin

Called by DBIx::Class when a transaction is begun.

txn_commit

Called by DBIx::Class when a transaction is committed.

txn_rollback

Called by DBIx::Class when a transaction is rolled back.

query_start

Called by DBIx::Class when a query is begun.

query_end

Called by DBIx::Class when a query is completed.

AUTHOR

Top

Cory G Watson, <gphat at cpan.org>

COPYRIGHT & LICENSE

Top


DBIx-Class-QueryLog documentation Contained in the DBIx-Class-QueryLog distribution.
package DBIx::Class::QueryLog;
use Moose;

has bucket => (
    is => 'rw',
    isa => 'Str',
    default => sub { 'default' }
);

has current_query => (
    is => 'rw',
    isa => 'Maybe[DBIx::Class::QueryLog::Query]'
);

has current_transaction => (
    is => 'rw',
    isa => 'Maybe[DBIx::Class::QueryLog::Transaction]'
);

has log => (
    traits => [qw(Array)],
    is => 'rw',
    isa => 'ArrayRef',
    default => sub { [] },
    handles => {
        add_to_log => 'push',
        reset => 'clear'
    }
);

has passthrough => (
    is => 'rw',
    isa => 'Bool',
    default => 0
);

before 'add_to_log' => sub {
    my ($self, $thing) = @_;

    $thing->bucket($self->bucket);
};

use base qw(DBIx::Class::Storage::Statistics);

use Time::HiRes;

use DBIx::Class::QueryLog::Query;
use DBIx::Class::QueryLog::Transaction;

our $VERSION = '1.3.0';

sub time_elapsed {
    my $self = shift;

    my $total = 0;
    foreach my $t (@{ $self->log }) {
        $total += $t->time_elapsed;
    }

    return $total;
}

sub count {
    my $self = shift;

    my $total = 0;
    foreach my $t (@{ $self->log }) {
        $total += $t->count;
    }

    return $total;
}

sub txn_begin {
    my $self = shift;

    $self->next::method(@_) if $self->passthrough;
    $self->current_transaction(
        DBIx::Class::QueryLog::Transaction->new({
            start_time => Time::HiRes::time
        })
    );
}

sub txn_commit {
    my $self = shift;

    $self->next::method(@_) if $self->passthrough;
    if(defined($self->current_transaction)) {
        my $txn = $self->current_transaction;
        $txn->end_time(Time::HiRes::time);
        $txn->committed(1);
        $txn->rolledback(0);
        $self->add_to_log($txn);
        $self->current_transaction(undef);
    } else {
        warn('Unknown transaction committed.')
    }
}

sub txn_rollback {
    my $self = shift;

    $self->next::method(@_) if $self->passthrough;
    if(defined($self->current_transaction)) {
        my $txn = $self->current_transaction;
        $txn->end_time(Time::HiRes::time);
        $txn->committed(0);
        $txn->rolledback(1);
        $self->add_to_log($txn);
        $self->current_transaction(undef);
    } else {
        warn('Unknown transaction committed.')
    }
}

sub query_start {
    my $self = shift;
    my $sql = shift;
    my @params = @_;

    $self->next::method($sql, @params) if $self->passthrough;
    $self->current_query(
        DBIx::Class::QueryLog::Query->new({
            start_time  => Time::HiRes::time,
            sql         => $sql,
            params      => \@params,
        })
    );
}

sub query_end {
    my $self = shift;

    $self->next::method(@_) if $self->passthrough;
    if(defined($self->current_query)) {
        my $q = $self->current_query;
        $q->end_time(Time::HiRes::time);
        $q->bucket($self->bucket);
        if(defined($self->current_transaction)) {
            $self->current_transaction->add_to_queries($q);
        } else {
            $self->add_to_log($q)
        }
        $self->current_query(undef);
    } else {
        warn('Completed unknown query.');
    }
}

1;