Featured image of post 第3回-IPアドレスでフィルタリングしよう - PerlとMooで学ぶDecorator

第3回-IPアドレスでフィルタリングしよう - PerlとMooで学ぶDecorator

LogParserを継承してフィルタリング機能を追加する継承アプローチを紹介。特定IPのみ抽出するIPFilteredLogParserを実装します。

@nqounetです。

前回は LogParser クラスを作成し、ログをハッシュとして扱えるようにしました。

今回は、このクラスを機能拡張して、「特定のIPアドレスからのアクセスだけを抽出するフィルター機能」を追加してみましょう。

オブジェクト指向プログラミングの教科書通り、「継承」を使って実現してみます。

今回のゴール:IPFilteredLogParserクラス

LogParser を継承し、指定したIPアドレスにマッチするログが見つかるまで読み込み続ける IPFilteredLogParser クラスを作ります。

コード例1: IPFilteredLogParser.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
package IPFilteredLogParser;
use Moo;
use strict;
use warnings;
use experimental qw(signatures);
use namespace::clean;

# LogParserを継承
extends 'LogParser';

# 抽出したいIPアドレス
has target_ip => (
    is       => 'ro',
    required => 1,
);

# 親クラスのnext_logをオーバーライド(上書き)
sub next_log ($self) {
    # 親クラスのnext_logを呼び出して、ログがある限りループ
    while (defined(my $log = $self->SUPER::next_log)) {
        # IPが一致したらそれを返す
        if ($log->{ip} eq $self->target_ip) {
            return $log;
        }
        # 一致しない場合はループ継続(次の行を読みに行く)
    }
    # 完全に読み終わったらundef
    return undef;
}

1;

ポイント解説

  1. extends 'LogParser': これで LogParser の機能(および LogReader の機能)をすべて受け継ぎます。
  2. has target_ip: フィルタリング条件となるIPアドレスを保持する新しいアトリビュートです。
  3. sub next_log: 親クラスにあるメソッドを同名で再定義(オーバーライド)しています。
  4. $self->SUPER::next_log: 親クラス(LogParser)の next_log を呼び出しています。これを使わないと、自分自身(IPFilteredLogParser)の next_log を再帰呼び出しして無限ループになってしまいます。

コード例2: 使用するスクリプト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
use strict;
use warnings;
use lib '.';
use IPFilteredLogParser;

# 127.0.0.1 のログだけを抽出したい
my $parser = IPFilteredLogParser->new(
    filename  => 'access.log',
    target_ip => '127.0.0.1',
);

while (defined(my $log = $parser->next_log)) {
    print "Found target access: Path: $log->{path}\n";
}

これで、特定のIPアドレスのログだけを簡単に抽出できるようになりました!

もし別の条件(例えばステータスコード)でフィルタリングしたい場合は、同様に StatusFilteredLogParser を作れば良さそうですね。

忍び寄る「継承の影」

今のところ、継承アプローチはとても順調に見えます。

しかし、もし以下のような要望が出たらどうなるでしょうか?

  • 「IPアドレスでフィルタリングしたい」
  • かつ、ステータスコードが404のものだけ欲しい」

あるいは、

  • 「ステータスコードでフィルタリングしたい」
  • かつ、IPアドレスは関係ない」

このように条件の組み合わせが増えてきた時、継承アプローチは突如として破綻します。

次回は、その「破綻の瞬間」を見てみましょう。

第4回: 404エラーを検出しよう(継承の限界)

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