warn() で吐かれるログを捕まえて投げる

Perl では $SIG{__WARN__} という疑似シグナルハンドラを使って、warn() で出力されようとする内容をトラップして処理することができます。

package MyWorker;

my $logger = Fluent::Logger->new;

sub work {
    my $job = shift;

    local $SIG{__WARN__} = sub {
        my $msg = shift;   # warn() で出力される文字列が渡ってくるので logger で送る
        $logger->post(
            "job" => {
                 jobid   => $job->jobid,   # jobid で検索できるように
                 message => $msg,
             },
        );
    };

    # job の処理
    # warn("Error!")
}

最初からログを何らかのオブジェクトに渡す仕組みを入れて作っていればよかったのですが、経緯としては以下のような歴史がありまして…

  • 昔とある job 処理をする worker がおり
  • そいつは全くログを吐いておらず
  • つまり処理途中で何がおきて失敗したのか分からず
  • 手っ取り早く warn() で処理の途中経過を吐き出すように修正
  • 結果、そこから呼び出されるコードのあちこちに warn() が埋め込まれてしまい

あとから $logger オブジェクトを渡そうにも、そのようなインターフェースがないという状態に。

仕方ないのでこのような手法をとった次第。