読者です 読者をやめる 読者になる 読者になる

AWS ELBのログをFluentd+Solr+Bananaのダッシュボードで可視化してみた

Solr AWS

AWS ELB(最近Classic Load Balancersに名前変更になりましたね)のログをFluentd+Solr+Bananaで可視化してみました。

基本はこちらの記事の構成ですが、Solrだけバージョン上がってSolrの6.2を利用しています。

yomon.hatenablog.com

Fluentdプラグイン

ELBからのログ取得はこちらのプラグインを使わせていただいています。 github.com

Solrとの連携させると time の項目がうまく扱えませんでした。 どうもiso8601の中でもZで終わる形式で有る必要があるようです。

Solrの日付型 | CHAZINE.COM

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>

画面イメージ

こんな感じでログが取得できます。 f:id:yomon8:20160917221443p:plain

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