AWS ELB(最近Classic Load Balancersに名前変更になりましたね)のログをFluentd+Solr+Bananaで可視化してみました。
基本はこちらの記事の構成ですが、Solrだけバージョン上がってSolrの6.2を利用しています。
Fluentdプラグイン
ELBからのログ取得はこちらのプラグインを使わせていただいています。 github.com
Solrとの連携させると time
の項目がうまく扱えませんでした。
どうもiso8601の中でもZで終わる形式で有る必要があるようです。
1995-12-31T23:59:59Z 1995-12-31T23:59:59.9Z 1995-12-31T23:59:59.99Z 1995-12-31T23:59:59.999Z
ということで手っ取り早く以下だけ修正して使っています。
"time" => line_match[:time].gsub(/Z/, "+0000")
↓
"time" => line_match[:time]
# snip old items elb_timestamp_unixtime = Time.parse(matches[:elb_timestamp]).to_i
↓
# snip old items elb_timestamp_unixtime = Time.at(content.last_modified).to_i
Fluentdの設定
td-agent.confの設定は以下のような感じです。
このまま実行するとS3の過去のELBログファイルを全てダウンロードしてくることになるので、初回実行時はかなりの時間がかかります。直近のものだけが必要な場合は timestamp_file
で設定したファイルにUNIXTime形式で時間保存しておくと、設定した時間以降のELBログだけを取得できます。
<source> @type elb_log region ap-northeast-1 s3_bucketname mybucketname s3_prefix path/to/elb_log-log timestamp_file /var/tmp/elb_last_at.dat buf_file /var/tmp/elb_log.tmp refresh_interval 300 tag elb_log.myelb access_key_id acccess_key secret_access_key secret_key </source> <match elb_log.**> type solr host localhost port 8983 core elb_log utc include_tag_key true tag_key tag flush_interval 60s buffer_type file buffer_path /var/tmp/elb_log_solr_out.buf buffer_queue_limit 20480 buffer_chunk_limit 100m num_threads 8 queued_chunk_flush_interval 20s </match>
Solr Schema設定
以下のように設定してみました。
solrconfig.xml
に以下の設定にして、schema.xml
でスキーマ管理するようにします。
<schemaFactory class="ClassicIndexSchemaFactory"/>
その schema.xml
の中身はこちらです。
<?xml version="1.0" encoding="UTF-8" ?> <schema name="testfluentd-schema" version="1.5"> <field name="id" type="string" indexed="true" stored="true" required="true"/> <field name="region" type="string" indexed="true" stored="true" required="true"/> <field name="prefix" type="string" indexed="true" stored="true" required="true"/> <field name="tag" type="string" indexed="true" stored="true" required="true"/> <field name="received_bytes" type="long" indexed="true" stored="true" required="true"/> <field name="sent_bytes" type="long" indexed="true" stored="true" required="true"/> <field name="account_id" type="string" indexed="true" stored="true"/> <field name="backend" type="string" indexed="true" stored="true"/> <field name="backend_port" type="string" indexed="true" stored="true"/> <field name="backend_processing_time" type="double" indexed="true" stored="true"/> <field name="backend_status_code" type="string" indexed="true" stored="true"/> <field name="request_processing_time" type="double" indexed="true" stored="true"/> <field name="request_uri" type="string" indexed="true" stored="true"/> <field name="request_method" type="string" indexed="true" stored="true"/> <field name="request_protocol" type="string" indexed="true" stored="true"/> <field name="response_processing_time" type="double" indexed="true" stored="true"/> <field name="client" type="string" indexed="true" stored="true"/> <field name="client_port" type="string" indexed="true" stored="true"/> <field name="elb" type="string" indexed="true" stored="true"/> <field name="elb_ip_address" type="string" indexed="true" stored="true"/> <field name="elb_status_code" type="string" indexed="true" stored="true"/> <field name="elb_timestamp" type="string" indexed="true" stored="true"/> <field name="elb_timestamp_unixtime" type="double" indexed="true" stored="true"/> <field name="key" type="string" indexed="true" stored="true"/> <field name="logfile_date" type="string" indexed="true" stored="true"/> <field name="logfile_elb_name" type="string" indexed="true" stored="true"/> <field name="logfile_hash" type="string" indexed="true" stored="true"/> <field name="user_agent" type="string" indexed="true" stored="true"/> <field name="ssl_cipher" type="string" indexed="true" stored="true"/> <field name="ssl_protocol" type="string" indexed="true" stored="true"/> <field name="time" type="tdate" indexed="true" stored="true"/> <field name="timestamp" type="tdate" indexed="true" stored="true"/> <field name="event_timestamp" type="tdate" indexed="true" stored="true"/> <field name="message" type="string" indexed="true" stored="true"/> <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/> <fieldType name="double" class="solr.TrieDoubleField" /> <fieldType name="uuid" class="solr.UUIDField" indexed="true" /> <fieldType name="string" class="solr.StrField" sortMissingLast="true" /> <fieldType name="tdate" class="solr.TrieDateField" /> <uniqueKey>id</uniqueKey> </schema>
画面イメージ
こんな感じでログが取得できます。
ELBで取得できる情報はこちら、ダッシュボードの組み方次第で、色々分析できます。 docs.aws.amazon.com
定期処理
たぶん調査不足ですが、AutoCommitがうまくいかず、以下のようにcronで処理回しています。
データは一ヶ月程度で削除するようにしています。
$ cat /etc/cron.d/solr MAILTO="" */10 * * * * root curl http://localhost:8983/solr/elb_log/update?commit=true 32 */12 * * * root curl http://localhost:8983/solr/elb_log/update?optimize=true 05 07 * * * root curl -s --globoff "http://localhost:8983/solr/elb_log/update?stream.body=\%3Cdelete\%3E\%3Cquery\%3Etime:[*\%20TO\%20NOW-32DAYS]\%3C/query\%3E\%3C/delete\%3E&commit=true"
補足(取得項目の追加)
fluent-plugin-elb-log
の取得項目を追加するには以下の部分に追記するとできます。
例えばリクエストURL内のホスト名を追加してみます。
record = { "time" => line_match[:time].gsub(/Z/, "+0000"), "elb" => line_match[:elb], <省略> "domain" => line_match[:request_uri].match(/^[httpsfile]+:\/{2,3}([0-9a-z\.\-:]+?):?[0-9]*?\//i)[1], <省略> "ssl_protocol" => line_match[:ssl_protocol], "option3" => line_match[:option3], }
schema.xml
にも項目追加しておきます。
<field name="domain" type="string" indexed="true" stored="true"/>
関連情報
Bananaのダッシュボード定義のSolrへの保存方法 yomon.hatenablog.com
Solr連携に利用させていただきているFluentdのプラグイン github.com