お役立ちフリーCGI、Perl Module、Perl テクニックなど Perl ネタが中心

DBIx::Class で sql_maker が生成した SQL をロギングする方法

DBIC いろいろ使って検証を続けているのですが、O/R Mapper って当たり前だけど万能じゃぁないなぁ〜とすごく思う今日この頃。正直、リレーションとか張りまくってる場合、自前で JOIN とか View 定義して書いた方が遙かに効率の良い SQL が記述できる。

複雑な SQL を表現するには、O/R Mapper だと逆に見づらいなぁ〜と思ったり。

とはいえ、単純な SQL の場合はやはり便利。コードも見た目、OO っぽくてかっこいいし。

でも、どうにも解析できなかったことが一つ。DBIC しか見てないんですが、sql_maker が生成した SQL をロギングする方法がわかりません。なんかコードを深追いしていくと、

DBIx::Class::Storage->debugfh とか DBI_TRACE

に行き着いちゃいます。でもよけいなデバッグ情報多すぎで使い物にならないので、ちょっとした Hack で実現。

メンドウなので、モジュールにしてなくってとってつけたような感じで実現。たとえば、Catalyst だと MyApp.pm で

use UNIVERSAL::require;
our $REGISTER_FLG = 0;

〜中略〜

__PACKAGE__->setup;

&_register_dbi_logging() unless($REGISTER_FLG);

sub _register_dbi_logging {
    my $log_yaml = helpdesk->path_to('log.yml');
    no strict 'refs';
    my $superclass = DBIx::Class::Storage::DBI->can('_execute');
    *{"DBIx::Class::Storage::DBI::_execute"} = sub {
        my ($self, $op, $extra_bind, $ident, @args) = @_;
        my ($sql, @bind) = $self->sql_maker->$op($ident, @args);

        Log::Dispatch::Config->require or die $@;
        Log::Dispatch::Configurator::YAML->require or die $@;
        my $yaml = Log::Dispatch::Configurator::YAML->new($log_yaml);
        Log::Dispatch::Config->configure($yaml);
        my $log = Log::Dispatch::Config->instance;

        $sql = qq{"$sql ",};
        map { $sql .= qq{"$_",}; } @bind;
        $log->info($sql);

        &$superclass(@_);
    };

    $REGISTER_FLG = 1;
}

なんて感じで、実装しちゃいました。

ログ設定は、Log::Dispatch::Config と Log::Dispatch::Configurator::YAML 使って設定しています。
ロギングは DBIx::Class::Storage::DBI::_execute を上書きしてロギング機能を追加して、元々のメソッドを call するなんてよく使う?姑息なやり方です。

これで、SQL が execute される度に勝手にロギングされていくので、アプリ側でロギングについて考える必要は無くなります。何かあったときにログから調査。そんな考えが DBIC には抜けているようなので作ってみたところです。

この記事を読んでいる方は、以下の関連記事も読んでいます。よろしければ一緒にご覧ください!

2006年6月22日 | drk | コメント(0)  

コメントする

CONTACTご相談・お問い合わせ

drk7.jpでは、小規模な CGI 開発から技術支援まで幅広くご相談にのります。

ご相談・お問い合わせはこちら からお気軽にどうぞ。

ページのTOPへ

Copyright © drk7.jp, All Rights Reserved.