ほわいとぼーど

ぷろぐらまのメモ帳

Kibana4 + dstat の話

あらまし

以前に、『dstatをkibanaで可視化+3.0.0milestone5新機能』という エントリでKibana3+dstatを使った可視化について書いたのですが、この中で構築の肝としてfluent-plugin-mapがありました。 Kibana3だと同一グラフ内に同一レコードの複数のfieldを含めることが出来なかったので、 fluent-plugin-mapを使って同一@timestamp+各fieldという別々のレコードとして分割登録しました。 このやり方は@kazeburoさんも記事にされたことにより 同様の方法を利用する人が意外といるようなのですが、 Kibana4では同一グラフ内に同一レコードの複数fieldを含めることが出来るのでレコード分割する必要がありません。 性能はわかりませんがdocument数や容量は分割する場合と比べると減ると思います。 ただしfluent-plugin-dstatはネストしたjsonを返すので平らにしてあげる必要があってfluent-plugin-flatten-hashを使います。

設定とか

fluentdの設定は以下。

<source>
  @type dstat
  tag dstat
  option  -ams
  delay 5
</source>

<match dstat>
  @type flatten_hash
  add_tag_prefix flattened.
  separator _
</match>

<match flattened.dstat>
  @type elasticsearch
  type_name       dstat
  host            localhost
  port            9200
  logstash_format true
  logstash_prefix dstat
  flush_interval  3s
</match

それからMapping template

$ vi template_dstat.json
{
  "template": "dstat-*",
  "mappings": {
    "dstat": {
      "properties": {
        "@timestamp" : {
          "type" : "date",
          "format" : "dateOptionalTime"
        },
        "dstat_dsk/total_read" : { "type" : "double" },
        "dstat_dsk/total_writ" : { "type" : "double" },
        "dstat_memory_usage_buff" : { "type" : "double" },
        "dstat_memory_usage_cach" : { "type" : "double" },
        "dstat_memory_usage_free" : { "type" : "double" },
        "dstat_memory_usage_used" : { "type" : "double" },
        "dstat_net/total_recv" : { "type" : "double" },
        "dstat_net/total_send" : { "type" : "double" },
        "dstat_paging_in" : { "type" : "double" },
        "dstat_paging_out" : { "type" : "double" },
        "dstat_swap_free" : { "type" : "double" },
        "dstat_swap_used" : { "type" : "double" },
        "dstat_system_csw" : { "type" : "double" },
        "dstat_system_int" : { "type" : "double" },
        "dstat_total_cpu_usage_hiq" : { "type" : "double" },
        "dstat_total_cpu_usage_idl" : { "type" : "double" },
        "dstat_total_cpu_usage_siq" : { "type" : "double" },
        "dstat_total_cpu_usage_sys" : { "type" : "double" },
        "dstat_total_cpu_usage_usr" : { "type" : "double" },
        "dstat_total_cpu_usage_wai" : { "type" : "double" },
        "hostname" : { "type" : "string", "index" : "not_analyzed" }
      }
    }
  }
}

$ curl -XPUT 'localhost:9200/_template/tmptelate_dstat' -d @template_dstat.json

templateは特定のパスに置いておくと自動的に読まれるのですが、 再起動が必要になるので最近はtemplate APIを呼ぶようにしてます。 変更結果を確認もできますし。
(既存のindex mappingが即時変更されるわけではありません)

mappingでなくfluent-plugin-typecastを使って先に型を定義してしまう方法もあります。
私はmappingでdoc_valuesやStringにnot_analyzedを設定することが多いのでElasticsearchでは共通的にmapping作成するようにしてます。 mappingを作るにはまず一旦設定なしでデータを入れてみてできたmappingを見て変更するとわりと簡単にできます。

curl localhost:9200/<index>?pretty

Kibana4の設定

Visualize Line chartの設定画面です。

f:id:a3no:20150823224924p:plain

add metricsでY軸を複数設定できます。

f:id:a3no:20150823224927p:plain

複数表示できましたね。

f:id:a3no:20150823224929p:plain

cpuやmemory, swapはArea chartの方がいいかもしれませんね。
設定方法は一緒です。

f:id:a3no:20150823224932p:plain

Vertical bar chartなんてのも。

f:id:a3no:20150823224934p:plain

レコード分割せずに複数のfieldを同一グラフに表示できました。

結論

dstat + fluentd + kibana4(Elasticsearh)ではレコード分割する必要がない。
(ただし構成上の話で性能はわかりません)

sample

github.com ansible-hands-onを再利用して構築検証用Vagrantfile作りました。

番外

grafana + influxdbの場合はレコード分割が必要(?自力では調べてない)なので その場合はwinebarrelさんの記事を参考にするといいと思います。

dstatをkibanaで可視化+3.0.0milestone5新機能

開発中の負荷試験をモニタリングしたくてdstat+Kibanaで組んでみました。
通常モニタリングは専用のツール(muninとか)で行うと思いますが、
今回はfluentdとKibanaの組み合わせにdstatを絡めてみます。

監視対象にはdstatとtd-agent、fluent-plugin-dstatを入れます。
インストール方法や細かい設定は割愛。
今回はdstat -ams 5相当を実施する設定とします。

fluent-plugin-dstatが出力する内容(1レコード)は以下になります。

2014-02-12T07:25:18+00:00	dstat	{
	"hostname":"large0000.example.com",
	"dstat":{
		"total cpu usage":{"usr":"0.400","sys":"0.500","idl":"99.0","wai":"0.100","hiq":"0.0","siq":"0.0"},
		"dsk/total":{"read":"0.0","writ":"18022.400"},
		"net/total":{"recv":"8389.600","send":"192767.200"},
		"paging":{"in":"0.0","out":"0.0"},
		"system":{"int":"170.200","csw":"119.600"},
		"memory usage":{"used":"562212864.0","buff":"394461184.0","cach":"6345080832.0","free":"510849024.0"},
		"swap":{"used":"0.0","free":"0.0"}
	}
}

改行は私が適宜入れてるので本来1行です。
dstat pluginはhostnameというパラメータを追加してくれるので
fluentdのタグを駆使してデータに格納したりする必要が無いです、便利。
3段目の"dstat"以下が実際にdstatで出力される内容に相当します。


モニタリング可視サーバ側にはtd-agentとElasticsearch、Kibanaを入れます。
使用したfluent-pluginはmap、elasticsearchです。
fluentdの設定は以下、

<source>
  type        forward
</source>

<match dstat>
  type copy
  <store>
    type map
    tag  "map.dstat.cpu-usr"
    time time
    record {"value" => record["dstat"]["total cpu usage"]["usr"], "stat" => "cpu-usr", "hostname" => record["hostname"]}
  </store>
  <store>
    type map
    tag  "map.dstat.dsk-read"
    time time
    record {"value" => record["dstat"]["dsk/total"]["read"], "stat" => "dsk-read", "hostname" => record["hostname"]}
  </store>
</match>

<match map.dstat.*>
  type elasticsearch
  type_name       dstat
  host            localhost
  port            9200
  logstash_format true
  logstash_prefix dstat
  flush_interval  3s
</match>

ここで重要なのはmapの部分になります。
"total cpu usage"とか"memory usage"のような同じグループの内容を同一グラフに表示したくなると思いますが、
dstatの結果を1レコードのまま格納してしまうとkibanaでは複合グラフにできません。
そこで1レコードをパラメータ数分だけ分割して同時刻の複数レコードに変換しています。

timestamp hostname:host a:1 b:2 c:3

timestamp hostname:host stat:a value:1
timestamp hostname:host stat:b value:2
timestamp hostname:host stat:c value:3

前述のfluentの設定はサンプルなのでmap2つしか書いてませんが、
実際にはElasticsearchに取り込みたいパラメータ分copyしてmapを書く必要があります。
今回のdstat設定であれば20パラメータですね。
map pluginにはmultiという1行で複数レコード作れる設定方法もあるのですが、
折り返して書くことが出来ず1行が長くなるので敢えてパラメータ毎に分けてます。
recordディレクティブを複数書くことが出来たらなーと思ったりはする。



これで準備は整いました。
ここからはKibanaの説明に移るのですが、
つい先日、Elasticsearchの1.0.0と併せてKibanaも3.0.0milestone5になっていますので、
一部、新機能の説明もしてみようと思います。
ではKibanaの画面を見てみます。

f:id:a3no:20140216130956j:plain

Histogramでvalueフィールドの平均値を表示しています。
"total cpu usage"と"memory usage"をそれぞれ1つのグラフにしてみました。

Elasticsearchには複数hostのdstatのデータを登録してあるのですが、
上記のグラフでは実は1台分だけにフィルタリングしてあります。
自在にフィルタリングを作成する機能もmilestone5の新機能です。

f:id:a3no:20140216130958j:plain

"FILTERING"一覧の右に出ている+を押すと、
こんな感じで入力画面が出るので、1台を特定可能なqueryを指定しています。



ここまでは1台のリソースを詳細にモニタリングしたい場合でした。
でも複数台を同時に見たい場合も当然ありますよね。
そこでmileston5の新機能であるtopNを使います。

f:id:a3no:20140216130959j:plain

query窓の●の部分をクリックして表示される画面で最初の選択肢をluceneからtopNに変更。
Fieldの所に組み合わせたいパラメータを入れます。今回はhostnameを指定。
Countは上位何個を表示したいかです。

f:id:a3no:20140216131000j:plain

hostname毎にグラフが描画されました。
指定fieldをterms facetした結果を掛け合わせてグラフを作ってくれます。
並び順を変えたり表示する対象を細かく指定したりは難しいのですが、
非常に使い道がある機能です。
例えば「アクセスを国別に」とか、「売り上げを製品毎に」とかしたいときに、
わざわざqueryで1国ずつ、1製品ずつ入力しなくても良くなるわけです。


新しい機能でsparklinesというのがあります。

f:id:a3no:20140216145834j:plain
f:id:a3no:20140216131002j:plain

query設定はHistogramの時と一緒(topN併用)です。
複数のものを形(要するに傾向)でざっと見たい場合に便利。
例えば前出のHistogramではsmall0001-0003はたいした負荷じゃないために
0付近でつぶれてしまっているのですが、
実際には何となく変動していることが見えたりします。(形が他と異なる3つ)
サービスを跨いだアクセス数とか、異なるインスタンスサイズのメモリ動向とかを
まとめて表示して傾向の変化を判断するのに使えると思います。
詳細はもっと別のグラフで見としても、対象数が増えてきた時に便利そう。


もう一つ、新しい機能terms_statsmode

f:id:a3no:20140216131003j:plain
f:id:a3no:20140216131004j:plain

terms facetをcountだけじゃなくてaggregationvalueとれるようにしたもの?
設定は色々できそうなんですがまだ把握してないので1例だけ。
色々な量を項目別に比較できます。
モニタリングというよりはデータ解析向きかも。

他にもまだ機能があったり細かく色々進化していたりしますが、今回はこんなところで。
もっと役立つユースケースとか出せるといいのですが、
まだ全然使いこなせてませんね。修行が足りない・・・

第3回elasticsearch勉強会 [2014/02/07(Fri.)]に参加してきました

http://elasticsearch.doorkeeper.jp/events/7491

メモって即UP満々な気で行って英語で挫折して何もメモらなかったので、
記憶を頼りに感想を書きます。


①「Geohashing with Elasticsearch」Florian Schilling, Elasticsearch Inc,

GeoHashという単語を始めて知ったほどに情弱でしたが、
場所検索をどうやって行っているか、ということは何となくわかったような。
マイクトラブルはありましたが楽しく話してもらえたので
また何か話に来てもらえるといいですね。
どれだけ聞き取れたか、、、という意味では皆無に近いかも。

②「AWSで構築するsharding」株式会社イプロス 外山 寛さん @toyama0919
http://toyama0919.bitbucket.org/elasticsearch.html#/

実際にProductionで使ってみて、という話。
相野谷さんもですが、AWS上での事例が出てくるのありがたいですね。
ec2pluginを使えば簡単とのこと。
Indexingにlogstash formatを使うかどうかという議論があって、
routingの特性も含めてIndexは1つにした方が良いのでは?という話でした。
データは100GBということでしたが、データ量がもっと多くなった場合にどうなるかですね。
pixivさんのsolrの事例で高速化のためにIndex分割する話があったので、
いずれ再Indexing必要になるのなら最初はlogstash formatで
後で適宜統合、、とか妄想したけど私は検索扱った事無いので妄想止まり

③「テスト駆動検索のススメ」株式会社じげん 多田 雅斗さん @tady_jp

検索でもTDDしような話
検索の仕様を最初からちゃんと設計できるのか?みたいなのもありますが、
仕様変わったら再Indexingになる可能性を考えても、
少なくとも現状を明示して検証できるのは非常に有効そうです。
検索も色々種類あるんだなーってわかって面白かったです。

④「MySQLユーザ視点での、小さく始めるElasticsearch」株式会社リブセンス 吉田 健太郎さん @yoshi_ken

MySQLからElasticsearchにデータレプリケーションするYamabiko中心の話。
検索用なんかでデータを入れるときに、
最初から分岐して平行で入れてる(絵がそうだけかもしれないが)例をよく見る気がするけど、
YamabikoだとMySQLに入った結果から連携する形になるので、
運用面でどういう違いがあるのかなーとか思ったり。
思っただけどまり。
単純にサービスにもよるのかもしれないですが。

⑤「nodeJS+DynamoDB+Elasticsearchで全社基盤を作った話」株式会社リクルートテクノロジーズ 相野谷 直樹さん @naokiainoya

スマホアプリに各種条件でPUSH通知するための全社基盤を作った話。
条件検索でPUSH対象のデバイスを一覧で返す。使い方が割りと独特。
ただこれってGeoHash検索に通じるような所が実はある気がする。
スキーマレスな部分を多様な条件登録に使っているということでした。
いろんな種類のユーザを全社共通でもっているリクルートさんならでは。
scanというAPIは正直知らなかった情弱です。
MultiAZでAutoScalingしているってのは興味深いです。
メインはあくまでDynamoなのでということでしたが、
今後、障害対策や運用系の知見が出てくるといいなぁと思いました。
あとキュー使うのもポイントなのかなーと思ったりも。


自分はKibanaとしてしか使ってないので今回はかなり検索メインでしたが、
クラスタ運用面なんかは実例が多数出てくると参考になりますね。
第4回は4/21だそうです。

Kibana向けFluentd設定例①アクセスログ可視化

どちらかというとFluentdの設定の話なのですが、
Kibana上でデータを扱うことも考慮して、くらいの感じで。

アクセスログの可視化はよくあるやつなので細かい所は飛ばします。

1段目:ログ収集先からの転送設定

<source>
  type     tail
  path     /path/to/apache_access.log
  format   /(?<message>.*)/
  pos_file /var/log/td-agent/apache_access.pos
  tag      apache.access.HOSTNAME
</source>

<match **>
  type           forward
  flush_interval 1s
  <server>
    host         FORWARD_HOST
  </server>
</match>

以前の記事ではin_tailにパースを書いていましたが、
パラメータが増減するのに毎回対応したり、パースするための負荷がかかることを考えると、
ログ収集ホスト上のin_tail正規表現をゴリゴリ書くのはあまり得策じゃない気がしています。
そこで1行を1メッセージとして送るような設定にしています。
fluentdが0.10.39以降であればformat noneとすることで同様のことが出来ます。
収集ログに日付が付与する場合はin_tailの変わりにfluent-plugin-tail-exを使うといいですね。


2段目:ログ受信側パース

<source>
  type forward
</source>

<match apache.access.**>
  type        parser
  add_prefix  parsed
  format      /(正規表現)/
  time_format %d/%b/%Y:%H:%M:%S %z
  key_name    message
</match>

ここからはログ解析サーバ上です。
forwardされたイベントをfluent-plugin-parserでパースします。
key_nameには解析したいフィールド名、ここではmessageになります。
formatには正規表現を書きますが、ログフォーマット側でLTSVにしておけば
format ltsvするだけでよくて楽ですね。


3段目:データ加工

<match parsed.apache.access.**>
  type         record_reformer
  output_tag   reformed.${tags[1]}.${tags[2]}
  
  ip           ${forwardedfor[/([^,]*),*/,1]}
  method       ${req[/^([^ ]*) .*$/,1]}
  uri          ${req[/^[^ ]* ([^ ]*) .*$/,1]}
  sessionId    ${req[/^[^ ]* \/path\/to\/api\?sessinId\=(.*?)(\&param\=[^ ]*)? .*$/,1]}
  log_host     ${tags[3]}
</match>

2段目の時点で生のデータを扱う分には十分なのですが、
時にはデータ加工したい場合があり、fluent-plugin-record-reformerが便利です。
整形したデータを生のレコードに+αしてくれるのが良いです。
しかも複数項目書けます。
例えば「req (referer情報)」に「GET /path/to/api?sessionId=10000001&param=1 HTTP/1.0」
という情報が入っているとして、1つ目をmethod、2つ目の部分をuriとして取り出しています。
あるいはuri全体ではなく、getパラメータに入っているsessionIdを取り出したりします。
またforwardedforにはproxyを通すとカンマ区切りで複数のアドレスが入っているので、
1番先頭だけを取り出して続くgeoipの判定に使います。
整形は${フィールド名[/(正規表現)/,n]}のように書いて取り出したい部分をグループ化して
nで何番目のグループを取り出したいかを指定します。
この辺りはruby正規表現のとり扱いになるので、
rubyのコンソールとかで少し試してみればすぐわかると思います。

log_hostは以前の記事fluent-plugin-elasticsearch上でtag_key @log_nameで行っていた
収集元ホストの登録をここで行うように変更したものです。
fluent-plugin-elasticsearchtag_keyだとtagをかなりうまいこと編集する必要がありましたが、
tags使うと簡単に必要な部分だけ取り出せますね。
${tags[3]}はtagをカンマで分割した4番目を取得しています。
なお、fluent-plugin-record-reformer 0.1.1からはfluent-plugin-forestと表記を合わせて
tag_partsが使えるようになります。

今回の記事のポイントはほぼ3段目に集約されます。
methodやuriはログフォーマットで直接指定すれば加工しなくても済みますが、
既に運用されているような場合に出力元に変更を加えるのが簡単じゃない場合も多いし、
そういう場合に受け取った先で簡単に加工できるという例です。


4段目:

<match reformed.**>
  type                    geoip
  geoip_lookup_key        ip
  enable_key_country_code geoip_country
  add_tag_prefix          es.
</match>

fluent-plugin-geoip用の設定。
pluginとは別にライブラリのインストールが必要なので注意してください。

ここまで見てきてplugin毎にtagの扱い方が異なるので若干混乱しますね。


5段目:

<match es.reformed.**>
  type              forest
  subtype           elasticsearch
  remove_prefix     es.reformed
  <template>
    type_name       ${tag}
    host            localhost
    port            9200
    logstash_format true
    logstash_prefix logstash
    flush_interval  10s
  </template>
</match>

fluent-plugin-elasticsearchはplaceholderに対応してないのでfluent-plugin-forest推奨。
fluent-plugin-record-reformerでのoutput_tagとの組み合わせにより
type_nameに入る値は今回の例では「apache.access」となります。
以前はtype_name、host名なんかを登録するのにtag操作が結構大変でしたが、
tagのplaceholderが便利になったお陰でかなり楽になりました。


fluentdではこんな感じでログ出力をいい感じに加工してデータストアに投入できます。
Kibana関係ないじゃないかって言われそうですが、Kibanaで表示する内容を考えた結果、
fluent-plugin-record-reformerで途中で加工するのが便利っていう話です。
Kibanaで解析するときにユーザIDやセッションIDみたいなのをfacet集計したい事例はよくあると思うので、
切り出しておいてmappingをnot_analyzedで用意するとランキング集計しやすいですね。
Kibana上ではtermsパネルで対象項目を指定するだけで表示できます。
デフォルトで5項目になってるけど数字を増やせばもっと表示可能。
(1000くらいにはしたことある)

f:id:a3no:20131215090919j:plain
参考例。本当はもっとランキングぽいの出したかったけど手元に出せるデータがなく。


3つ例を書くつもりだったけど、調査修正して動確してたらハマって時間かかってしまった。
record_reformerは前に設定書いた時点ではtag_parts使えてたんだけど、
手元で実施したら0.1.1ではなく0.1.0が入ってしまって使えなかったり、
Elasticsearch-1.0.0.Beta2を使ったら0.90.7で動いてたmapping templateが動かなかった。
記事は書いたものの色々と調査するものが増えてしまった・・・

fluentd-plugin-elasticsearchでのログ時刻の扱い

これまでの自分のElasticsearch関連の記事では"request_time"という
独自に定義したラベルを用いて登録を行っていました。
一方、fluentdは"time"というラベルを用いるとログの時刻をfluentd内で扱うイベントタイムとみなします。
"time"とした場合と、それ以外でfluentd-plugin-elasticsearchの動作に
違いが見られたのでメモしておきます。

ところで"request_time"としたのには理由があったのですが、
その理由は本筋ではないので最後に書くことにします。


①ログ時刻を通常のラベルを用いて登録する場合

この場合はラベル名を"time"以外にしてパースします。
つまりこれまでの場合は"request_time"としていました。
この時点では他の項目と同じJSON(MessagePack)の一項目なので文字列です。
そしてそのラベルに対してElasticsearchのフィールドを日付型としてMappingをします。
これによりElasticsearch内で"request_time"は日付型フィールドとして扱われるようになりました。
後はこの"request_time"フィールドをKibana3でtime fieldとして設定します。
例えばtimepickerの設定画面では以下になります。

f:id:a3no:20130916234322j:plain

index作成にlogstash形式を指定していた場合(logstash_format true)
logstash形式indexの日付はログをimportしたfluentdで読み込んだ日付になります。

ところで上記画像のtime fieldにはデフォルトでは"@timestamp"が設定されています。
@timestampフィールドはどうやったら使えるのでしょうか?


②fluentdで"time"ラベルを使う

その答えはfluentdの"time"ラベルにありました。
fluentdのパースを以下のように設定したとします。

format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
time_format %d/%b/%Y:%H:%M:%S %z

この場合、記事の冒頭でも書きましたがログ時刻はfluentdのイベントタイムとして扱われます。
詳しくは書きませんがJSONボディ部とは異なる扱いになります。

そしてfluentd-plugin-elasticsearchでlogstash形式に設定すると、
"time"が"@timestamp"フィールドに登録されます。
更にこの場合、logstash形式index名もログ日付に追随します。
つまり、ログ日付と同じ日付でlostash-YYYY.MM.DDなindexが作成されます。

fluentdのパースの時点でちゃんと設定しておけば、
自動的にログの内容にあった登録がされるということですね。


なお、logstash形式ではなく自分でindex名を指定した場合は
"@timestamp"フィールドは出来ませんでした。
ただ以前に試した時はログ登録時刻で設定されてた気もするのでココは怪しいです。
(追記)確認しました。logstash_format trueなら@timestampフィールドが作られるが、
そうでない場合は@timestampフィールドは作られない、です。

それから、なぜ最初から"time"を使わず"request_time"にしてたのかですが、
fluentdの正規表現を書くのに@tagomorisさんのサイトを参考にテストしていたのですが、
「require 'time'」を見落として設定してなかったばっかりに
いくらやっても"time"としてパースするのに失敗したので
諦めて文字列なフィールドとして取得するようにしちゃったというオチでした。
間抜けすぎてどうしようもないですね。。。

Elasticsearchを触ってみた話の続き

「Kibana3+Elasticsearchを触ってみた話」の続き。
前回は設定周り飛ばしたのでその辺とか書くつもりだったのですが、
分割して色々書いたのでまとめっぽい。


・環境
Vagrant+VirtualBox+Ubuntu12.04で試して
1週間くらい前からテスト環境のAWS上で動いている。
ものすごく残念なことにSmallだけど。性能の話はしない!


・インストール
こちらの方を参考にしました、でフィニッシュです。
debやrpmのパッケージも既に用意されているようですね。
最近色んな人が記事あげてるのですぐ見つかると思います。


・Plugin×Proxy
各種Proxy設定頑張ってもダメで、たしかエラーからはgit://~とか見えたので
gitにProxy設定かとgit config --systemとか適当にやってダメだと思ってたら、
大谷さんが割りと最近に書いてた。大層捗りました。


とりあえずheadとbigdeskは入れておいたらいいと思います。
headは生データ見れるしindexもシャードも視覚確認できるし、
右クリメニューからindex削除とかmapping確認出来ちゃう、素敵plugin
元から同梱でもいいのではないだろうか。
(簡単に記事書きました。「Elasticsearchのhead plugin」
bigdeskはLoadAverageとかMemory使用量とかそういうの表示するやつですね。
JVMの中を監視するのは何かしら必要なので入れておきましょう。

その他、超大量のplugin一覧はこちら


・データを入れる前に
インストールして動いたら次は本体設定をします。
クラスタ周りとか色々な設定ありますが今のところデフォルトのまま。
mappingはtemplatesで設定しました。「Elasticsearchにmappingをtemplate設定してみた」
indexの話も少し書きました。「Elasticsearchのlogstash形式indexについて」


・データを入れる
リアルタイムに入れる場合、fluentd大先生にお願いしてフィニッシュです。
簡単に説明しました。「Elasticsearchにfluentdする設定とかlabelの話」

リアルタイムじゃない場合はbulk_importとかあるのですが、
データの整形がめんどうだったのでこれもfluentdしました。


・画面の設定周りとか
Kibana3はわりと感覚的に使えます。
大谷さんのブログ見ると更にわかりやすいです。
あと、y_310さんのブログのQuery制御周りは非常にためになりました。


・monit入れた話
Vagrant+Virtualboxで検証してる時に過去ログをfluentd経由で入れたら
結構な頻度でElasticsearchが落ちました。
bin/elasticsearch -fしてると画面上にkilledとか表示されて落ちます。
これは今思うとvagrantfileにMemory割り当てしてなかったのと、
過去ログをファイル単位でそのまま投入したので、
投入した瞬間に大量のログが流れ込んだせいだと思うのですが、
AWS上で起こると怖いのでmonitを入れて自動再起動するようにしました。
最初はsupervisordにしようと思ったのですが、
bin/elasticsearchは実は内部はただのシェルだったので、
supervisordの仕組み(プロセスをforkする?)ではうまく監視できずmonit(PID制御)にしました。
この辺は自分は詳しくないし小一時間程度の調査しかしてないのでやり方はあるのかも。


とりあえず数日頑張ったKibana3+Elasticsearchの記事は一通り。
書いてる間にも色んな人が書いてて今更感漂ったけどやりきった。
自分は触りだしてから1週間とかそこらしかたってないので
そういった面から見ても非常に使いやすいツール群だなと思います。

Elasticsearchにfluentdする設定とかlabelの話

といっても設定はさほど難しくないです。
収集箇所から直接送信する場合はコチラを参照するとよさそうな感じ。

自分の場合、収集箇所と集計サーバ両方にtd-agent入れてて、
収集箇所はtail_exとforward、集計サーバで集計してgrowthforecastに投げてたり、
今回の場合、後からElasticsearch設定追加したりしてます。
本番でgrowthforecastとElasticsearchを同じサーバに入れないと思うけど、
今はテスト環境ということで。


以下は送信側設定。

<source>
  type        tail_ex
  format      /(正規表現)/
  path        /path/to/apache.log.%Y%m%d
  tag         apache.${HOSTNAME}
  pos_file    /path/to/apache.pos
</source>

<match apache.*>
  type forward
  flush_interval 1s
  <server>
    host ${FORWARD_HOST}
  </server>
</match>

送信側はなんてことはない設定なんですが、ポイントはtagのHOSTNAMEなのかなと。
Elasticsearch内でhost毎に検索したい場合はtagからlog_nameに入れるか、
record-modifierで項目の一つとして入れてしまうかどっちかになると思います。
集計サーバみたいな構成の場合、tagについてるとmatchで対象を制御もできるのでよさげ。

なお、${HOSTNAME}と${FORWARD_HOST}はシェルとかChefで埋めてます。
tail_exの機能?で${hostname}ってtagに使えるのですが、
加工したhost名を使いたかったので設定時に埋めるようにしました。


集計サーバ側の設定は以下。

<source>
  type        forward
</source>

<match apache.**>
  type copy

  <store>
    type forest
    subtype elasticsearch
    remove_prefix apache
    <template>
      type_name apache
      include_tag_key true
      tag_key @log_name
      host localhost
      port 9200
      logstash_format true
      flush_interval 10s
    </template>
  </store>
</match>

実際にはstoreもっとあるけど、Elasticsearchに関係ないところは省略しました。

転送元からはtagが「apache.host」の形で流れてきて、
remove_prefixされて@log_nameには「host」の形で登録されます。
これによりElasticsearch上で「@log_name="host"」な検索ができます。
まぁ、ここまでしなくてもElasticsearchは全文検索エンジンなので、
apache.host」のままで登録されても「@log_name="host"」で絞り込み出来るはず。


こんな感じでfluentdで簡単にElasticsearchにデータ投入できます。
Elasticsearchにはbulk_importする方法も用意されているのですが、
JSONでindex指定やid付与した形に整形必要だったこともありやってません。
過去ログでもfluentd経由で入れてます。fluentd便利!
あとfluentd-plugin-elasticsearch書いてくれた人のおかげ。


ところで、Elasticsearchに関するブログ記事書いてる途中に気づいたんですけど、
自分のlabel名があまり標準的ではないものになってる気がする。
元々はfluentd公式のapache2の書式をベースに正規表現を書いてます。
http://docs.fluentd.org/ja/articles/in_tail の中ほどの「apache2」)
それに対して追加パラメータの一部の項目名が似たようなのがあった部分を装飾したり、
timeのパースをうまくいかないと誤解したためにrequest_timeにしたり。

ところが最近LTSVお勧めというのがあることを知りました。

比較してみますと、

apache2でのlog_format 自分のlabel fluentdサイトのlabel ltsv.orgのrecommended label
%t request_time time time
%>s code code status
%b res_size size size
%{User-agent}i agent agent ua
%l req_size - reqsize
%D response_time - reqtime_microsec
%T - - reqtime

特にrequest_timeが違う用途なのに被ってるのが泣きそう。
といっても急に変えられないのでスキーマの設定は気をつけましょう、
という残念なオチ。
私のElasticsearchの記事を見る際にはパラメータにはご注意を、、、

(追記)「fluentd-plugin-elasticsearchでのログ時刻の扱い」