はじめに
- 前回の続き
- ログを
elasticsearch
に投げる部分をfluentd
でやってみることにする(厳密にはtd-agent
)
参考
準備
fluentd のプラグインインストール
fluent-plugin-elasticsearch
elasticsearch
にログを投げる為に...
/usr/lib/fluent/ruby/bin/fluent-gem install fluent-plugin-elasticsearch --no-ri --no-rdoc -V
fluent-plugin-typecast
elasticsearch
に送るデータの型を変換する為に...理由は後述。
/usr/lib/fluent/ruby/bin/fluent-gem install fluent-plugin-typecast --no-ri --no-rdoc -V
ちなみに一連のセットアップについてはこちらに cookbook 化した(テストはまだ!)。
正規表現を頑張る
siege
が出力するログを正規化する為に慣れない正規表現を頑張ってみた。尚、siege
が出力するログは以下のようなフォーマット。
Date & Time, Trans, Elap Time, Data Trans, Resp Time, Trans Rate, Throughput, Concurrent, OKAY, Failed 2013-11-16 07:51:06, 25, 0.94, 0, 0.16, 26.60, 0.00, 4.21, 25, 0 2013-11-16 07:58:56, 25, 0.74, 0, 0.14, 33.78, 0.00, 4.74, 25, 0 2013-11-16 07:59:39, 25, 0.75, 0, 0.14, 33.33, 0.00, 4.65, 25, 0 2013-11-16 08:00:16, 25, 0.67, 0, 0.13, 37.31, 0.00, 4.69, 25, 0 2013-11-16 08:00:31, 25, 0.76, 0, 0.14, 32.89, 0.00, 4.67, 25, 0 2013-11-16 08:05:52, 25, 0.86, 0, 0.16, 29.07, 0.00, 4.60, 25, 0
デバッグに際してはこちらやこちらを参考にさせて頂いて以下のようなスクリプトでデバッグを行った。
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'time' require 'fluent/log' require 'fluent/config' require 'fluent/engine' require 'fluent/parser' $log ||= Fluent::Log.new # debug log = '2013-11-17 07:18:02, 25, 0.76, 0, 0.14, 32.89, 0.00, 4.54, 25, 0' format = /^(?<date>(\d{4})-(\d{2})-(\d{2}) (\d{2}:)(\d{2}):(\d{2})),\s{1,}(?<Trans>\d+(\.\d+)?),\s{1,}(?<Elap_Time>\d+(\.\d+)?),\s{1,}(?<Data_Trans>\d+(\.\d+)?),\s{1,}(?<Resp_Time>\d+(\.\d+)?),\s{1,}(?<Trans_Rate>\d+(\.\d+)?),\s{1,}(?<Throughput>\d+(\.\d+)?),\s{1,}(?<Concurrent>\d+(\.\d+)?),\s{1,}(?<OKAY>\d+),\s{1,}(?<Failed>\d+)$/ time_format = '' parser = Fluent::TextParser::RegexpParser.new(format, 'time_format' => time_format) puts parser.call(log)
もっと良い方法があれば教えて欲しいよー...
siege を叩くシェルを修正
たったコレだけ!
#!/bin/bash /usr/bin/siege -b -i -r 3 -c 3 http://hoge.huga.com/ --log=/tmp/test_log
工夫して複数の Web サイトで調査出来るようになるかも。
ハマった
現状
kibana
でレスポンスタイムのデータをヒストグラムで見ようとしたら以下のようなエラーとなってしまった。
ClassCastException[org.elasticsearch.index.fielddata.plain.PagedBytesIndexFieldData cannot be cast to org.elasticsearch.index.fielddata.IndexNumericFieldData]
原因
シェルスクリプトから elasticsearch
に突っ込んだら type: double
なっていたがfluentd(fluent-plugin-elasticsearch)
経由で elasticsearch
に突っ込んだら type:string
となっていた。
参考にさせて頂いているブログ記事を引用させて頂くと...
type apache2
のparser
では size 等にはto_i
の処理が施されている(ApacheParser
が利用されている)- format を自作した場合には
RegexpParser
が利用されてtime
以外が文字列として処理される
とのことなので独自に format
を書いた場合には全てのフィールドを string
型で処理するらしい。
対応
fluent-plugin-typecast を利用することでフィールドの型を変換してしまう。
<match siege.access> type typecast item_types Trans:integer,Elap_Time:float,Data_Trans:integer,Resp_Time:float,Trans_Rate:float,Throughput:float,Concurrent:float,OKAY:integer,Failed:integer tag filtered.siege.access </match>
fluent-plugin-typecast
で扱えるタイプは以下の通り。
- integer
- float
- string
- time
- bool
- array
fluent-plugin-typecast
でパースして elasticsearch
に投げると以下のようなデータ型でデータが登録されていた。
elasticsearch
側でデータのタイプを自動判断してくれているようだ。
最終的に...
td-agent.conf
以下のような td-agent.conf
となった。
<source> type tail path /tmp/test_log pos_file /tmp/test.pos tag siege.access format /^(?<date>(\d{4})-(\d{2})-(\d{2}) (\d{2}:)(\d{2}):(\d{2})),\s{1,}(?<Trans>\d+(\.\d+)?),\s{1,}(?<Elap_Time>\d+(\.\d+)?),\s{1,}(?<Data_Trans>\d+(\.\d+)?),\s{1,}(?<Resp_Time>\d+(\.\d+)?),\s{1,}(?<Trans_Rate>\d+(\.\d+)?),\s{1,}(?<Throughput>\d+(\.\d+)?),\s{1,}(?<Concurrent>\d+(\.\d+)?),\s{1,}(?<OKAY>\d+),\s{1,}(?<Failed>\d+)$/ </source> <match siege.access> type typecast item_types Trans:integer,Elap_Time:float,Data_Trans:integer,Resp_Time:float,Trans_Rate:float,Throughput:float,Concurrent:float,OKAY:integer,Failed:integer tag filtered.siege.access </match> <match filtered.siege.access> type elasticsearch include_tag_key true tag_key @log_name host 127.0.0.1 port 9200 logstash_format true flush_interval 10s </match>
kibana で確認
ログの中から Resp_Time
から Elap_Time
をヒストグラムで表示させてみた。
もう少しデータ集めたいところ。
最後に
- 正規表現勉強になった
fluentd
でオレオレ format を作った時にはデータ型には注意するelasticsearch
でデータを突っ込んだ時にデータ型は自動判別してくれる(みたい)elasticsearch-head
があると手軽にelasticsearch
のデータが確認出来るのが素晴らしい!