Elasticsearch 1.3 が出たと聞いて、そういえば percentile に対応するらしいって前に聞いたのを思い出してググったら 1.1 (2014年3月) で既に対応済みでした。(Experimental ですけどね)
ということなので早速試してみます。
データは Kibana 用にインデックス済みなのでこいつを使います。ウェブサービスのレスポンタイムのパーセンタイル値欲しいですよね。
まずは上記のドキュメントに書いてあるサンプルをひとつ。だたし、対象となったドキュメントの内容は不要なので size: 0
を指定しています。
{
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "responseTime",
"percents": [
95,
99,
99.9
]
}
}
},
"size": 0
}
$ curl -s -X POST -d @query1.json \
http://elasticsearch:9200/accesslog-2014.07.25/_search?pretty
{
"took" : 121,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 390458,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"load_time_outlier" : {
"values" : {
"95.0" : 274762.7526741865,
"99.0" : 683982.277012403,
"99.9" : 2122798.5229873355
}
}
}
}
とっても簡単!!そして速い。でもこれだと、インデックス全体が対象となってしまうので5分単位、10分単位とか1時間単位で出したいですよね。
そこで、次のように range フィルターで時間を絞りましょう。
{
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "responseTime",
"percents": [
95,
99,
99.9
]
}
}
},
"filter": {
"range": {
"@timestamp": {
"to": 1406250000000,
"from": 1406246400000
}
}
},
"size": 0
}
1時間おきならこの結果を HRForecast に突っ込めばいつでも参照できますね(私はまだ使ったことないですけど)。5分とかなら InfluxDB でも PostgreSQL でも MySQL にでも突っ込んで好きな時に参照できるようにすると良いですね。
でもまだ HTTP の status code は 200 に限定したいとか、画像などの静的ファイルは除外したいとかありますね。
{
"aggs": {
"load_time_outlier": {
"percentiles": {
"field": "responseTime",
"percents": [
95,
99,
99.9
]
}
}
},
"query": {
"filtered": {
"query": {
"query_string": {
"query": "status:200 AND NOT uri:/.*\\.(png|gif|jpeg|jpg|css|js)/ AND NOT uri:/.*\\.(png|gif|jpeg|jpg|css|js)?.*/"
}
},
"filter": {
"range": {
"@timestamp": {
"to": 1406250000000,
"from": 1406246400000
}
}
}
}
},
"size": 0
}
こんな感じでしょうか。なんか美しくないけど...
uri
には Apache の LogConfig での %U%q
が入っているものとします。
便利です。