アクセスログをfluent-plugin-prometheusで集計してGrafanaで表示する

アクセスログをfluent-plugin-prometheusで集計してgrafanaで表示するというのを試したのでメモがてら書いておきます。

現状fluent-agent-liteでアクセスログを収集してサンプリングや集計をして最終的にGrowthforecastで表示する仕組みが社内にあります。

イメージはこんな感じ
fluent-plugin-sampling-filter and fluent-plugin-datacounter released! #fluentd - たごもりすメモ

これはこれで問題なく動いているんですが、例えばhttp status 201がどれぐらいあるか知りたい!ってなった時はfluentdの設定を変えて再起動する必要があります。や、そんなユースケース今までなかったですけどw

その辺の柔軟性が欲しい場合は別の仕組みが必要だろうと思っていて、一つの手段としてはNorikraに集計を任せるというのがあります。

別のやり方としてPrometheusでクエリ書いてGrafanaで表示する手があると思ったので試してみました。

fluentdクラスタがすでにあるので、fluent-plugin-prometheusを使えば簡単にPrometheus化できるかもと思ってこのプラグインを試しました。

使い方は下記にあります。
GitHub - fluent/fluent-plugin-prometheus: A fluent plugin that collects metrics and exposes for Prometheus.
fluent-plugin-prometheusをリリースしました

試そうとしてわかったことはこのプラグインはfluentdの非公開APIを使っているので普通に使おうとしてもエラーになると思います。詳細は下記参照
Fluentd dies when executing example · Issue #2 · fluent/fluent-plugin-prometheus · GitHub

fluentd 0.12.19もしくはfluentd v0.14.0.pre.1なら動きます。

僕は最終的にはfluentd 0.12.19で動かしました。

fluentdの設定はこんな感じ。
これでhttp://host:24231/metricsをprometheus serverからpullするようにします。

<source>
    type prometheus
  </source>
  <filter accesslog.**>
    type prometheus
    <labels>
      tag ${tag}
      host ${hostname}
      method ${method}
      status ${status}
    </labels>
    <metric>
      name accesslog_counts
      type counter
      desc the number of emited record
    </metric>
  </filter>
  <match accesslog.**>
    type null
  </match>

Prometheusにはメトリクスのタイプがcounter, gauge, histogram, summaryとあります。
Metric types | Prometheus

Prometheusのruby clientだとhistogram実装が無いので使えるのはcounter, gauge, summaryです。

http response timeのところでsummaryを使おうとしたんですけど、そうするとCPU使用率が100%になるのでやめました。

この状態でaccesslog_countsというクエリをPrometheusで実行すると下記のようになります。

accesslog_counts{host="...",instance="...:24231",job="...",method="GET",status="200",tag="..."}
...

http status code別の1秒間の件数を1分のwindowで見たい場合のクエリは下記の通り。これで合っているはず。。。

sum(rate(accesslog_counts{tag="..."}[1m])) by (status)

これをGrafanaに登録してグラフ化すると下記のようになります。

さらに割合も見たいのでクエリを下記のようにします。

sum(rate(accesslog_counts{tag="..."}[1m])) by (status, job) / on(job) group_left(status) sum(rate(accesslog_counts{tag="..."}[1m])) by (job)

この辺難しくてOperators | PrometheusとかHow To Query Prometheus on Ubuntu 14.04 Part 1 | DigitalOceanを読んでなんとか書きました。これで合っているはず。。。

これをGrafanaに登録してグラフ化すると下記のようになります。

レスポンスタイム別の結果をグラフ化するのはこの仕組みだと難しい気がしますが、単純なカウントならこれでもいけるかなというところです。