Elasticsearchで日別のユニークユーザ数を取得する「elasticsearch-timefacets-plugin」

# はじめに

[Elasticsearch](http://www.elasticsearch.org/)にアプリケーションのイベントログを突っ込んで、[Kibana3](http://www.elasticsearch.org/overview/kibana/)でいじるということをしています。
イベントログを見ているとやはりGoogle Analytics、Mixpanel、SLASH-7のようにユニークユーザ数を見たくなります。
ですが、Elasticsearchではdistinctした値のcountを時系列に取得することができません。
[Date Histogram Facet](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-date-histogram-facet.html#search-facets-date-histogram-facet)は近いけど、件数を取るか、指定したフィールドの合計を取るかしかできません。

# elasticsearch-timefacets-plugin

[elasticsearch-timefacets-plugin](https://github.com/crate/elasticsearch-timefacets-plugin)というElasticsearchのプラグインを使うと上記のことが実現できます。
他にもいくつか同等のプラグインがありますが、唯一これだけがElasticsearchのバージョン追随をがんばっています。
2013年11月9日現在ElasticSearchは0.90.6ですが、elasticsearch-timefacets-pluginは0.90.5までサポートしています。0.90.6は11月4日リリースなので仕方ないでしょう。

なお、0.90.6に入れてみたらElasticsearchが起動しなくなりました。。。シビアです。。。

# インストール手順

## 前提

- Elasticsearch 0.90.5をインストール済み
- Mavenをインストール済み

## ソースダウンロード

```
$ git clone git@github.com:crate/elasticsearch-timefacets-plugin.git
```

0.10.0のタグがElasticsearch 0.90.5と互換があるので、タグをチェックアウトします。

```
$ cd elasticsearch-timefacets-plugin
$ git checkout -b 0.10.0 0.10.0
```

## コンパイル

```
$ mvn clean package -DskipTests=true
```

## プラグインをインストール

UbuntuにdebパッケージのElasticsearchを入れたら、Elasticsearchは/usr/share/elasticsearch/に入りました。適時変更して下さい。

```
$ /usr/share/elasticsearch/bin/plugin -install elasticsearch-timefacets-plugin -url file:///<カレントディレクトリのフルパス>/target/elasticsearch-timefacets-plugin-0.10.0.jar
```

Elasticsearchを再起動

```
$ sudo service elasticsearch restart
```

# 試してみる

以下のようなlogstashフォーマットのデータが既に入っているとします。
2013年10月30日13時50分にuser999さんがloginをしたイベントログのイメージです。

```
{
  "_index": "logstash-2013.10.30",
  "_type": "logstash",
  "_id": "999999WmQkeDmokM9AIfud",
  "_score": null,
  "_source": {
    "@log_name": "co-meeting.event",
    "@timestamp": "2013-10-30T13:50:53+09:00",
    "user_id": "user999",
    "event": "login"
  },
  "sort": [
    1383108999000
  ]
}
```

Distinct Date Histogram Facetを使って、10月19日から21日の日毎のユニークユーザ数を取得してみましょう。

```
$ curl -XPOST 'http://localhost:9200/logstash-2013.10.19,logstash-2013.10.20,logstash-2013.10.21/_search?pretty' -d '{
    "query" : {
        "match_all" : {}
    },
    "facets" : {
        "0" : {
            "distinct_date_histogram" : {
                "field" : "@timestamp",
                "value_field" : "user_id",
                "interval" : "day"
            }
        }
    }
}
'
```

するとこんな結果が返ってきて、19日に297人、20日に322人、21日に754人のユニークユーザがアクセスしたことがわかります。

```
{
  "took" : 232,
  "timed_out" : false,
  "_shards" : {
    "total" : 15,
    "successful" : 15,
    "failed" : 0
  },
  "hits" : {
    "total" : 105334,
    "max_score" : 1.0,
    "hits" : [ 
      ...(中略)...
    ]
  },
  "facets" : {
    "0" : {
      "_type" : "distinct_date_histogram",
      "entries" : [{
        "time" : 1382140800000,
        "count" : 297
      }, {
        "time" : 1382227200000,
        "count" : 322
      }, {
        "time" : 1382313600000,
        "count" : 754
      } ],
      "count" : 924
    }
  }
}
```

他にも例えば以下のようにすると、10月19日にログインをした1時間毎のユニークユーザ数を取得できます。

```
$ curl -XPOST 'http://localhost:9200/logstash-2013.10.19/_search?pretty' -d '{
    "query" : {
        "match_all" : {}
    },
    "facets" : {
        "0" : {
            "distinct_date_histogram" : {
                "field" : "@timestamp",
                "value_field" : "user_id",
                "interval" : "1h"
            },
           "facet_filter": {
             "term": { "event" : "login" }
           }
        }
    }
}
'
```

便利ですね。

でも、これをKibana3で表示するには、Kibana3をいじらないといけないんですよね。。。