Fluentd+Solr5.3+BananaでJavaのGCログをグラフ化

[Fluentd+Solr5.3でJavaのGCログを収集](http://qiita.com/hashiwa/items/8424814c9888ac1bfff3)の続きです。前回、Fluentdで収集したGCログをSolrに流し込むということをやってみました。今回は、SolrのデータをBanana(Solr連携用のKibanaみたいなもの？)でグラフ化してみます。

本作業にあたっては、suganumaさんの[solr + banana 始め方](http://qiita.com/suganuma/items/b9fcc99bc5491cbb85e1)の記事を大変参考にさせていただきました。

# 環境
- CentOS 6.6 (32bit)
- Fluentd 0.12.15
    - プラグイン: fluent-plugin-out-solr 0.0.8
- Apache Solr 5.3.1
- Oracle JDK 8 Update 65
- Banana v1.5.0

# Banana

[Github](https://github.com/LucidWorks/banana/tree/v1.5.0)の[Download ZIP]をクリックしてzipをダウンロードし、解凍します。

```
$ unzip -q banana-1.5.0.zip

$ ls banana-1.5.0
CONTRIBUTING.md  LICENSE.md  README.md   build.xml   jetty-contexts  resources  test
Gruntfile.js     QUICKSTART  bower.json  index.html  package.json    src
```

warファイルにして(本当はwarにしなくても良いのですが)、Solrのサーバーディレクトリに配置します。
この手順の詳細は、BananaのGithubの[README](https://github.com/LucidWorks/banana)に記載されています。ただし、antコマンドを実行する前にbuildディレクトリを作っておく必要があった。

```
$ mkdir build

$ ant

$ ls build
banana-1.war

$ mkdir $SOLR_HOME/testfluentd_server/webapps

$ cp build/banana-1.war $SOLR_HOME/testfluentd_server/webapps/banana.war

$ ls $SOLR_HOME/testfluentd_server/webapps/
banana.war

$ cp jetty-contexts/banana-context.xml $SOLR_HOME/testfluentd_server/contexts/

$ ls $SOLR_HOME/testfluentd_server/contexts/
banana-context.xml  solr-jetty-context.xml
```

Solrを起動します。

```
$ cd $SOLR_HOME

$ bin/solr start -d testfluentd_server
```

http://localhost:8983/banana にブラウザでアクセスして、Bananaの画面が表示されたらOKです。

![img-01.jpg](https://qiita-image-store.s3.amazonaws.com/0/107431/7125f33c-df9d-fd14-6acb-cab8a8a8b6a8.jpeg)

# 前回からの変更点
FluentdとSolrの設定は基本的には[前回](http://qiita.com/hashiwa/items/8424814c9888ac1bfff3)と同じですが、グラフ化の良さがわかりやすいようにいくつか変更しています。

## 1. Fluentdの設定ファイル

Fluentdの設定ファイルを以下のようにしました。"gckind"と"timeSec"以外にも収集するフィールドを増やしています。

```txt:fluentd-02.conf
<source>
  type tail
  format /^\[(?<gckind>[^(]*)\((?<cause>[^)]*)\) *(?<beforeSpace>[^K]*)K\-\>(?<afterSpace>[^K]*).*, (?<timeSec>[0-9\.]*) secs\]$/
  path /home/hashiwa/fluentd/app/jvm.log
  tag gclog
</source>

<match gclog>
  type solr
  host localhost
  port 8983
  core collection1
  include_tag_key true
  tag_key tag
  time_field timestamp
#  utc # if you do not want to use localtime
#  commit true # if you want to commit explicitly

  flush_interval 3s
</match>
```

## 2. Solrの設定

Fluentdで収集されるフィールドに合わせて、schema.xmlにフィールドを追加します。

```xml:testfluentd_server/solr/collection1/conf/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="id"      type="uuid"   indexed="true" stored="true" required="true"/> -->

   <field name="time"        type="string"  indexed="true" stored="true"/>
   <field name="gckind"      type="string"  indexed="true" stored="true"/>
   <field name="cause"       type="string"  indexed="true" stored="true"/>
   <field name="beforeSpace" type="long"    indexed="true" stored="true"/>
   <field name="afterSpace"  type="long"    indexed="true" stored="true"/>
   <field name="timeSec"     type="double"  indexed="true" stored="true"/>
   <field name="tag"         type="string"  indexed="true" stored="true"/>
   <field name="timestamp"   type="tdate"   indexed="true" stored="true"/>

   <!-- _version_ field must exist in schema -->
   <field name="_version_" type="long" 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" />
   <!-- <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0"/> -->
   <fieldtype name="text_ws" class="solr.TextField" positionIncrementGap="100">
     <analyzer>
       <tokenizer class="solr.WhitespaceTokenizerFactory"/>
     </analyzer>
   </fieldtype>

   <!-- QueryElevationComponent requires the schema to have a uniqueKeyField. -->
   <uniqueKey>id</uniqueKey>

</schema>
```

これでOK。

# 実行

今回は、GC後のJavaヒープの使用容量である"afterSpace"をBananaで折れ線グラフ化します。

Solrを起動します。

```
$ bin/solr start -d testfluentd_server
```

Fluentdを実行します。

```
$ fluentd -c fluentd-02.conf
```

Javaアプリを実行します。

```
$ cat run.sh
java -XX:+UseParallelGC -verbose:gc -verbose:class A > jvm.log 2> server.log

$ bash run.sh
```

Bananaの画面をブラウザで開き、TIMEPICKERとHISTOGRAMの設定を行います。

TIMEPICKERの歯車(?)マークをクリックし、[Panel]タブを開いて、Default Modeをabsolute、Time Fieldをtimestampに設定します。TIME WINDOWの開始日時と終了日時は、解析対象のログのタイムスタンプに合わせます。

HISTOGRAMの歯車(?)マークをクリックし、[Panel]タブを開いて、Modeにvalues、Value FieldにafterSpaceを設定します。デフォルトでは棒グラフの設定になっているので、折れ線グラフにするためにChart SettingsのBarsを無効化し、LinesとSmoothを有効化します。

すると、

![img-03.jpg](https://qiita-image-store.s3.amazonaws.com/0/107431/ee70ce9e-53c4-5bfb-1ee6-2d21b2ef2a35.jpeg)

折れ線グラフが表示できました！

ついでに、TERMSも表示してみます。TERMSの歯車(?)マークをクリックし、[Panel]タブを開いて、Fieldにgckindを設定すると、GC種別の割合が円グラフで表示できました。

![img-04.jpg](https://qiita-image-store.s3.amazonaws.com/0/107431/d1229cdd-6588-1ec8-5d5a-5d9d466ea4e6.jpeg)

# まとめ

ところどころ詰まりながらでしたが、OSSの考え方を理解できてからは自分なりにカスタマイズして割と簡単にGCログをグラフ化することができました。

たぶん、Bananaが一番簡単でしたね。Fluentdは、GCログをパースするフォーマットを書くのが時間かかりました。([Fluentular](http://fluentular.herokuapp.com/)というFluentdのフォーマットを簡単に試せるページが超助かりました。) Solrが慣れるまでに一番時間がかかって、クラスタ構成やらschema.xmlを使わないスキーマ設定など、ほかにもまだまだ勉強する余地がありそうです。

実際に業務で使おうとすると、流量やデータサイズに合わせてチューニングしないといけなかったり、データ欠損が起きないように信頼性をどう担保するかという問題があると思います。ただ、インターネット上に情報がたくさんありますし、たくさんの便利な機能をとても簡単に利用できるので、引き続きウォッチしていきます。