Featured image of post 第7回-アラート通知Decoratorを追加しよう - PerlとMooで学ぶDecorator

第7回-アラート通知Decoratorを追加しよう - PerlとMooで学ぶDecorator

「連続404エラー」などの異常条件を検知してアラートを出すAlertDecoratorを実装。Decoratorが副作用(Side Effect)を持つパターンを解説します。

@nqounetです。

前回は、ログの統計情報を集計する StatsAggregatorDecorator を作成しました。

今回は、もっと「ハッカー気分」になれる機能を追加します。ログをリアルタイム監視して、異常があったら警告を出す「アラート通知機能」です。

今回のゴール:AlertDecoratorクラス

以下の条件で警告(STDERR出力)を出す AlertDecorator を作ります。

  • 条件: 404 Not Found エラーが「連続して」指定回数以上発生した時

コード例1: AlertDecorator.pm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package AlertDecorator;
use Moo;
use experimental qw(signatures);

extends 'LogDecorator';

# アラートの閾値(デフォルトは3回連続)
has threshold => ( is => 'ro', default => 3 );

# 連続エラー回数を保持するプライベートアトリビュート
has _consecutive_404s => ( is => 'rw', default => 0 );

around next_log => sub ($orig, $self) {
    my $log = $self->$orig;

    if ($log) {
        if ($log->{status} eq '404') {
            # 404ならカウントアップ
            $self->_consecutive_404s( $self->_consecutive_404s + 1 );

            # 閾値を超えたらアラート!
            if ($self->_consecutive_404s >= $self->threshold) {
                warn "[ALERT] Too many 404s! Consecutive count: " . $self->_consecutive_404s . "\n";
                # ここでSlack通知などを送ることも可能
            }
        } else {
            # 404以外が来たらリセット
            $self->_consecutive_404s(0);
        }
    }

    return $log;
};

1;

ポイント解説

  1. 副作用(Side Effect): このDecoratorはログを変更せず、集計もしませんが、「警告を出す」という副作用を持っています。
  2. 状態のリセット: 正常なリクエスト(200 OKなど)が来たらカウンターをリセットしています。「連続」を判定するためのロジックです。
  3. 拡張性: warn の部分を Slack 通知やメール送信に置き換えれば、立派な監視ツールの出来上がりです。

コード例2: パイプラインに組み込む

前回の統計集計と組み合わせてみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use LogParser;
use StatsAggregatorDecorator;
use AlertDecorator;

# 1. 基本
my $parser = LogParser->new(filename => 'access.log');

# 2. アラート(閾値5回)
my $alert = AlertDecorator->new(
    wrapped   => $parser,
    threshold => 5,
);

# 3. 統計
my $stats = StatsAggregatorDecorator->new(
    wrapped => $alert,
);

# 実行
while (defined(my $log = $stats->next_log)) {
    # ログが流れるたびに、裏でアラート判定と統計集計が行われる
}

$stats->report();

パイプラインの完成

これで、私たちのログ解析パイプラインは以下の機能を持つようになりました。

  1. ファイル読み込み
  2. パース(正規表現)
  3. アラート検知(404連続)
  4. 統計集計

しかも、これらはすべて独立したクラスであり、自由に組み替えたり、取り外したりできます。

次回予告

いよいよ最終回です。

これまでPerlのコードで組み立てていたパイプラインを、「YAML設定ファイル」から動的に生成できるようにします。「コードを変更せずに仕様変更に対応する(OCP)」という、設計の最終地点を目指しましょう!

第8回: 設定ファイルでパイプラインを組み立てよう(完成)

comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。