カタカタブログ

SIerで働くITエンジニアがカタカタした記録を残す技術ブログ。Java, Oracle Database, Linuxが中心です。たまに数学やデータ分析なども。

Fluentd + Elasticsearch + Kibanaで遊んでみた(その2) 〜家計簿データのFluentdによるElasticsearchデータ登録まで〜

前回の記事で、仮想マシンのCent OS 7にFluentd (td-agent 2.3.0) + Elasticsearch 2.1.1 + Kibana 4.3.1 を構築して、それぞれ単体で動作するところまでを見た。

今回はその続きとしてより実践的に、Fluentdでログを検知し、Elasticsearchに自動転送した後、それをKibanaで可視化するところまでをやったみたい。

可視化するデータ

ログ解析基盤として有名なため、Apacheログなどを可視化するケースの説明が多いが、今回はあえてより家庭的に、我が家の家計簿データを可視化してみたいと思う。そもそもElasticsearchは全文検索システムであり、Kibanaはそれを可視化するのみ、またFluentdはログ転送を謳っているが、本質的にはファイルやデータ転送ミドルウェアであって、それがログファイルである必要はない。
また、家計簿データならZaimで貯めこんでているし、シンプルでわかりやすい可視化ができそう。

  • Zaim公式

http://zaim.net/

  • 過去に書いたZaim-APIを検証した記事

Zaimから家計簿データを取得する。ただし今回は可視化まで一通り使ってみることが目的なので、APIを使ったリアルタイム連携といった複雑なことはせず、いったんデータをぬきとって加工したファイルがある状態から進めることにする。

ということで、Zaimからデータを取り出すところは省略するが、以下のようなJSONフォーマットの3000件ほどの家計簿データをmoney.jsonというファイルに出力した。

{"@timestamp":"2014-01-14", "category_name":"食費", "genre_name":"昼ご飯", "place":"社食", "comment":"", "amount":500, "from_account_name”:”夫の財布"}
{"@timestamp":"2016-01-02", "category_name":"エンタメ", "genre_name":"書籍", "place":"技術評論社", "comment":"サーバ/インフラエンジニア養成読本 ログ収集〜可視化編", "amount":1980, "from_account_name”:"夫の財布"}
{"@timestamp":"2016-01-02", "category_name":"交通", "genre_name":"電車", "place":"新幹線", "comment":"帰省のため", "amount":13000, "from_account_name":"共有の財布"}
・・・

ファイルの構造は以下の通り。

  • @timestamp : 支出した日付を表す。@timestampという属性にしておくと、Elasticsearch側でも自動で日付データだと認識してくれる(もちろん、他の名前でも明示的に日付だと指定することもできる)
  • category_name : 食費、交通費、など支出のカテゴリを表す。
  • genre_name : カテゴリを更に細分化するジャンル名。例えば、食費カテゴリの中には、「食料品」「昼ご飯」「夜ご飯」といったジャンルがあり、公共料金カテゴリの中には、「水道料金」「電気料金」などのジャンルがある。
  • place : 支出した場所。通所はお店の名前が入る。
  • comment: 任意のコメント。本を買った時は書籍名を入れたり、交通費の場合は目的を書くようにしている。
  • amount : 支出の金額。単位は円。
  • from_account_name : 支出元の名前。我が家では、家族みんなの食事などは「共有の財布」から出し、夫のお小遣いは「夫の財布」から出しているので、そういった値が入る。

Fluentdで動作確認

前回はfluentd-catでしか動きを確認していないので、今回はファイルに追記された内容を動的に転送できるかをまずちゃんと確認する。設定ファイルは以下のように編集し、Fluentdを再起動する。

/etc/td-agent/td-agent.conf

<source>
  type tail
  format json
  path /tmp/money.json
  pos_file /tmp/money.json.pos
  tag zaim.money
</source>

<match *.*>
  type stdout
</match>

type tailpathで指定されたファイルに末尾追記された内容を検知する。matchはいったんtype stdoutとして、Fluentdのログに表示させるだけとする。

次にzaim-moneyインデックスを明示的に作成する。mappingsという設定を入れることで、各データ項目の型を指定できる。

ここで重要なのは、"index": “not_analyzed”設定である。Elasticsearchは全文検索システムなので、値を自動的に形態素解析してしまう。そのため、例えばジャンル名に「昼ご飯」という項目値があった場合に、「昼」「ご飯」に分けられてしまうようなことになる。そうなると、ジャンル別に集計するときに、「昼ご飯」という項目で集計できず、不都合があるので、そのような解析をしない項目を明示しておく。

mappingを明示してインデックスを作成するには以下のようなコマンドを実行する。

$ curl -XPUT http://vmdev:9200/zaim-money -d '
{
  "mappings": {
    "fluentd": {
      "properties": {
        "@timestamp": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        },
        "amount": {
          "type": "long"
        },
        "category_name": {
          "type": "string",
          "index": "not_analyzed"
        },
        "comment": {
          "type": "string"
        },
        "from_account_name": {
          "type": "string",
          "index": "not_analyzed"
        },
        "genre_name": {
          "type": "string",
          "index": "not_analyzed"
        },
        "place": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}
'

インデックスが作成できたので、money.jsonファイルを作成し、先ほどのJSONフォーマットのデータを追記してみる。

$ touch /tmp/money.json
$ echo '{"@timestamp":"2014-01-14", "category_name":"食費", "genre_name":"昼ご飯", "place":"社食", "comment":"", "amount":500, "from_account_name":"夫の財布"}' >> /tmp/money.json

Fluentdログファイルで動きを確認する。

$ tail /var/log/td-agent/td-agent.log
2016-01-03 11:44:44 -0500 [info]: following tail of /tmp/money.json
2016-01-03 11:46:36 -0500 zaim.money: {"@timestamp":"2014-01-14","category_name":"食費","genre_name":"昼ご飯","place":"社食","comment":"","amount":500,"from_account_name":"夫の財布"}

このログから、入力したパターンが正しく認識され、zaim.moneyというタグがつけられていることが確認できる。
もしパターンが間違っている場合は、以下のように警告が出る。

$ echo 'hoge fuga' >> /tmp/money.json
$ tail /var/log/td-agent/td-agent.log
2016-01-03 11:49:47 -0500 [warn]: pattern not match: "hoge fuga"

データファイルのフォーマットと、設定ファイルのsourceの書き方は問題なさそうなので、次はこのデータをElasticsearch側に転送する。

FluentdからElasticsearchに転送する

前回の記事で、FluentdからElasticsearchと連携するためのプラグインfluent-plugin-elasticsearchが導入済みなので、Elasticsearchに転送するにはmatch側でtype elasticsearchを指定すればよい。また、index_nameには、Elasticsearch側で取り込み後のインデックス名を指定できるので、今回はzaim-moneyとした。

/etc/td-agent/td-agent.conf

<match zaim.money>
  type elasticsearch
  host vmdev # elasticsearchのhost
  port 9200 # elasticsearchのport
  index_name zaim-money

</match>

#<match *.*>
#  type stdout


#</match>

編集後はFluentdの再起動を忘れずに。

さて、さきほどZaimから抽出して整形したJSONファイルがあるので、catして追記することにする。(※Fluentdはログファイルのローテーションを自動検知する仕組みがあるので、差し替えてもOKそうだが)。

$ cat money.json >> /tmp/money.json

確認のため、Elasticsearchのkopfにアクセスする。

http://vmdev:9200/_plugin/kopf

f:id:osn_th:20160107112401p:plain
zaim-moneyインデックスが登録されていることが分かる!無事にログファイルに追記したJSONをFluentdが自動検知してElasticsearch側に転送していることが分かる。

RESTメニューから、zaim-money/_searchリクエストをGETでSendすると、RESPONSEを確認することができる。データの件数や何件かの中身が見れるので、ここでも正しくデータが登録されていることを確認しておく。
f:id:osn_th:20160107112406p:plain

まとめ

これで、Elasticsearchに家計簿データを登録することができたので、後はKibanaで可視化するだけ!
長くなったので、Kibanaでの可視化は次回の記事にする。

続きです。

関連記事