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

Spread Toolkit で分散ログ (4) Spread::Session

ああ長かった。

上記設定を済ませて Apache, spread, spreadlogd を起動し Apache にアクセスすると、ログが loghost:/var/log/spread_log に出力されるはず。

spreadlogd.conf で

RewriteTimestamp = CommonLogFormat

とするとログのタイムスタンプ部分を spreadlogd の現在時刻で上書きしてくれるので、複数の時刻のずれた Apache からログを集約しても時系列が前後しません。

Apache2 では mod_log_spread が使えないので (mod-log-spread2 があるけど、alpha 版らしい)、外部プログラムをパイプ経由で起動することでログを spread に流します。

 CustomLog "| /path/to/spread_log.pl" combined

もちろん Apache1 でこの手を使っても OK.

mod_log_spread にも error_log_spread.pl というのが同梱されているのだけど、せっかくなので Spread::Session を使って書いてみた。

#!/usr/bin/perl

use strict;
use Spread::Session;

Log::Channel::disable('Spread::Session');

my $group             = 'apache';
my $retry_interval    = 3;
my $retry_max_attempt = 10;
my $session           = connect_to_spread();

while ( my $log = <> ) {
    eval {
        my $r = $session->publish( $group => $log );
    };
    if ( $@ ) {
        warn "$@ disconnect to spread.";
        undef $session;
        $session = connect_to_spread();
    }
}


sub connect_to_spread {
    my $retry_count = 0;
    while ( 1 ) {
        my $s = eval { Spread::Session->new() };
        return $s if $s;

        warn "$@ retry to connect after $retry_interval sec.\n";
        if ( ++$retry_count > $retry_max_attempt ) {
            die "Aborted.";
        }
        sleep $retry_interval;
    }
}

spread が落ちていた時にリトライするように、とかもやっているけど、流れとしては

  • Spread::Session を new() して
  • publish() でメッセージを送る

だけ。結構簡単。