LoginSignup
14
13

More than 5 years have passed since last update.

Elasticsearch で percentile 計算

Posted at

Elasticsearch 1.3 が出たと聞いて、そういえば percentile に対応するらしいって前に聞いたのを思い出してググったら 1.1 (2014年3月) で既に対応済みでした。(Experimental ですけどね)

Percentiles Aggregation

ということなので早速試してみます。

データは Kibana 用にインデックス済みなのでこいつを使います。ウェブサービスのレスポンタイムのパーセンタイル値欲しいですよね。

まずは上記のドキュメントに書いてあるサンプルをひとつ。だたし、対象となったドキュメントの内容は不要なので size: 0 を指定しています。

query1.json
{
  "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
response
{
  "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 フィルターで時間を絞りましょう。

query2.json
{
  "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 に限定したいとか、画像などの静的ファイルは除外したいとかありますね。

query3.json
{
  "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 が入っているものとします。

便利です。

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13