Message::Passing是Suretec公司为自己的VoIP业务开发的logstash山寨版。这几个月更新还是比较快的。比之前我刚关注它时改变很大。比如Message::Passing::Output::ElasticSearch已经出来了,还有专门的Message::Passing::Filter::ToLogstash,连命令行方式Message::Passing::Role::Script都采用了MooX::Options构建,相当的OO了。

不过可能是运用环境的区别吧,作者一直在filter方面没有什么动静,可怜巴巴的null/all/key/tologstash这么几个,比起input和output的列表差太远了。而且像logstash里的jls-grok这么最有力的工具没有山寨。

今天有空,稍微写了个例子,可以比较方便的定义类似grok_pattern的方式完成对accesslog的json序列化。不过配置方式比Grok还是麻烦不少,以后真用的话,再考虑config的办法吧,这里主要是为了展示Message::Passing::Filter::XXX的编写:

    #!/usr/bin/perl
    package Message::Passing::Filter::GrokLike;
    use Moo;
    use MooX::Types::MooseLike::Base qw/ ArrayRef Str /;
    use List::MoreUtils qw/ uniq /;
    use DateTime;
    use Regexp::Log::Nginx;
    use namespace::clean -except => 'meta';
    with 'Message::Passing::Role::Filter';
    has format => (
        is => 'ro',
        isa => Str,
        default => sub { '%date %status %remotehost %domain %request %originhost %responsetime %upstreamtime %bytes %referer %useragent %xforwarderfor' },
    );
    has capture => (
        is => 'ro',
        isa => ArrayRef,
        default => sub { [ 'ts', 'status', 'remotehost', 'url', 'oh', 'responsetime', 'upstreamtime', 'bytes' ] },
    );
    has _grok => (
        is => 'ro',
        lazy => 1,
        builder => '_build_grok',
    );
    sub _build_grok {
        my $self = shift;
        my $rln = Regexp::Log::Nginx->new(
            format  => $self->format,
            capture => $self->capture,
        );
        return $rln;
    };
    sub filter {
        my ($self, $message) = @_;
        my @fields = $self->_grok->capture;
        my $re = $self->_grok->regexp;
        my %data;
        @data{@fields} = $message->{'@message'} =~ m/$re/;
        $message->{'@fields'} = {
            %data,
            responsetime => $data{'responsetime'} + 0,
            upstreamtime => $data{'upstreamtime'} + 0,
            bytes        => $data{'bytes'}        + 0,
        };
        $message;
    };
    true;

2012 年 12 月 30 日附注:

前两天已经把这个模块正规化后上传到 CPAN 上了。把捕获定义成 .ini 文件,同时还加入了类似 logstash 里的 mutate filter 的功能。模块叫 Message::Passing::Filter::Regexp。同时上传了一个 Message::Passing::Output::PocketIO 模块,可以打开一个网页时时接收output。