読者です 読者をやめる 読者になる 読者になる

XMLRPC::Transport::HTTP のロギング

perl

XMLRPC::Transport::HTTP::Daemonでサーバ作っってたらログの取り方でとても困った。小汚い方法でなんとかなったけども、もっとスマートな方法を誰か教えてくれないかなーと淡い期待をこめて晒しておく。

SOAP::Liteを継承したモジュールでログを取ろうと思ったら、SOAP::Traceを使うのが常套手段な訳だけど、実はこいつに用意されてるイベント(フックポイント)のいくつかはXMLRPC::Transport::* では使えない。これはenvelopeメソッドをXMLRPC::Liteでオーバーライドしてるからだと思う。
僕はどうしてもfaultログを取りたかったんだけど、こんなことをしておいてもなーんにも記録されない。

use XMLRPC::Transport::HTTP;
use Sys::Syslog qw(:DEFAULT setlogsock);
setlogsock 'unix';
openlog($0, 'cons,pid', 'local0');

SOAP::Lite->import( +trace => [
	fault => sub {
		syslog('err', sprintf('Fault code:%s, string:%s', @_));
	},
]);

my $server = XMLRPC::Transport::HTTP::Daemon->new(
	〜〜省略〜〜
$server->handle;

今畜生め。そこで僕の取った方法は XMLRPC::Transport::HTTP::Daemon::make_fault を上書きして、フックポイントをねじこむ。

{
    no warnings 'redefine';
    my $org = XMLRPC::Transport::HTTP::Daemon->can("make_fault");

    *XMLRPC::Transport::HTTP::Daemon::make_fault = sub {
        my @save = @_; # syslog()に何故か@_が破壊されるので、保全しておく。
        SOAP::Trace::fault(@_[1, 2]); # callback関数に渡す。
        $org->(@save);
    };
}

追記:tokuhiromさんとこで見たやり方だと。忘れないようにメモっておく。これでもいいんだー。シンボルテーブルを参照するのね。

my $org = *XMLRPC::Transport::HTTP::Daemon::make_fault{CODE};

こうしておけばリクエストがfaultしたときに、ログが取れるようになる。
が、どうなんだろうこれ。普通にパブリックなインターフェースを通してログとれないのかな。

他にもリクエストのメソッド名とかパラメーターとかもログとってるんだけど、れそぞれの取得方法に一貫性がない…。使わせて頂いておいてあれなんだが、ちょっと疑問を感じるインターフェースなきがした。あと、peer_addrはどうしても取れなかった。