statsd exporterの使い方

statsd exporterの使い方

statsd_exporterはStatsD形式のメトリクスを受け取ってPrometheusメトリクスを出力する。

概要

With StatsD

既存のStatsD環境からPrometheusにメトリクスを送信するには、StatsDリピーターバックエンドが受信したメトリクスを全てstatsd_exporterプロセスに再送信するように設定する。 このexporterは、マッピングルールの設定に従って、StatsDメトリクスをPrometheusメトリクスに変換する。

+----------+                         +-------------------+                        +--------------+
|  StatsD  |---(UDP/TCP repeater)--->|  statsd_exporter  |<---(scrape /metrics)---|  Prometheus  |
+----------+                         +-------------------+                        +--------------+

Without StatsD

StatsD exporterは、StatsD自体と同じ行プロトコルを利用するので、アプリケーションがStatsDメトリクスをexporterに直接送信するように設定することもできる。 そのような場合には、StatsDサーバーを運用する必要がなくなる。

この方法は中間的な解決策としてだけ推奨され、長期的にはPrometheusメトリクスを直接実装するように切り替えることを推奨する。

DogStatsD extensions

このexporterは、DogStatsD形式のタグをPrometheusのラベルに変換する。 この概念の説明についてはDogStatsDドキュメントのTagsを、 仕様についてはDatagram Formatを参照すること。 要約すると、通常のStatsDフォーマットに|#tag:value,another_tag:another_valueを追加する。 値のないタグ#some_tagは、サポートされていない。

ビルドと実行

バージョン0.7.0で、kingpinフラグライブラリを使うようになった。 この変更でフラグの挙動は、以下のようにPOSIX的になった。

  • ロングフラグは2つのダッシュで始まる(--version
  • 複数のショートフラグはまとめられる(ただし現状では1つしかない)
  • フラグ処理は最初の--で終了する
$ go build
$ ./statsd_exporter --help
usage: statsd_exporter [<flags>]

Flags:
    -h, --help               Show context-sensitive help (also try --help-long and --help-man).
        --web.listen-address=":9102"
                            The address on which to expose the web interface and generated Prometheus metrics.
        --web.telemetry-path="/metrics"
                            Path under which to expose metrics.
        --statsd.listen-udp=":9125"
                            The UDP address on which to receive statsd metric lines. "" disables it.
        --statsd.listen-tcp=":9125"
                            The TCP address on which to receive statsd metric lines. "" disables it.
        --statsd.listen-unixgram=""
                            The Unixgram socket path to receive statsd metric lines in datagram. "" disables it.
        --statsd.unixsocket-mode="755"
                            The permission mode of the unix socket.
        --statsd.mapping-config=STATSD.MAPPING-CONFIG
                            Metric mapping configuration file name.
        --statsd.read-buffer=STATSD.READ-BUFFER
                            Size (in bytes) of the operating system's transmit read buffer associated with the UDP or Unixgram connection. Please make sure the kernel parameters net.core.rmem_max is set to a value greater than the value specified.
        --debug.dump-fsm=""  The path to dump internal FSM generated for glob matching as Dot file.
        --log.level="info"   Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]
        --log.format="logger:stderr"
                            Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"
        --version            Show application version.

Tests

$ go test

メトリクスのマッピングと設定

statsd_exporterは、簡単なマッピング言語を用いて、ドット区切りのStatsDメトリクスをPrometheusのラベル付きのメトリクスに変換するように設定できる。 設定ファイルの変更は監視されていて、自動的に再読み込みされる。

マッピングの定義は、対象とするStatsDメトリックにマッチングする行で始まる。 *は、ドット区切りのメトリックの要素に対するワイルドカードのように作用する。 マッチング式に続く行はそれぞれ、label="value"の組みを1つ含まなければならない。 また、少なくともメトリック名(ラベル名name)を定義しなければならない。 こうしてこれらのラベルからPrometheusメトリクスが構成される。 ラベル値の$n形式の参照は、マッチング行のn番目(1始まり)のワイルドカードのマッチで置き換えられる。 複数のマッチング定義は、1つ以上の空行で分けられる。 マッチした最初のマッピングルールが採用される。

設定ファイルのどのマッピングにもマッチしないメトリクスは、ラベルなしで、英数字出ない文字を除いたPrometheusメトリクスに変換される。ピリオドはアンダースコアに変換される。

一般的に、各種メトリック型は、以下のように変換される。

StatsD gauge   -> Prometheus gauge

StatsD counter -> Prometheus counter

StatsD timer   -> Prometheus summary                    <-- indicates timer quantiles
               -> Prometheus counter (suffix `_total`)  <-- indicates total time spent
               -> Prometheus counter (suffix `_count`)  <-- indicates total number of timer events

マッピングの設定のサンプルを以下に示す。

mappings:
- match: test.dispatcher.*.*.*
  name: "dispatcher_events_total"
  labels:
    processor: "$1"
    action: "$2"
    outcome: "$3"
    job: "test_dispatcher"
- match: *.signup.*.*
  name: "signup_events_total"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server"

この設定は、以下のように、StatsDメトリクスをPrometheusメトリクスに変換する。

test.dispatcher.FooProcessor.send.success
 => dispatcher_events_total{processor="FooProcessor", action="send", outcome="success", job="test_dispatcher"}

foo_product.signup.facebook.failure
 => signup_events_total{provider="facebook", outcome="failure", job="foo_product_server"}

test.web-server.foo.bar
 => test_web_server_foo_bar{}

設定ファイルの各マッピングは、メトリックに対してnameを1つ定義しなければいけない。 メトリック名は、マッチングの行のn番目のワイルドカードにマッチした部分を$n形式の参照を含むことができる。 それによって、以下のような動的な書き換えが可能になる。

mappings:
- match: test.*.*.counter
  name: "${2}_total"
  labels:
    provider: "$1"

メトリック名は、正規表現マッチへの参照を含むこともできる。 上記のマッピングは、以下のように書くこともできる。

mappings:
- match: test\.(\w+)\.(\w+)\.counter
  match_type: regex
  name: "${2}_total"
  labels:
    provider: "$1"

同じ名前のメトリクスは同じラベル名の集合を持たなければならないことに注意すること。

デフォルトのヘルプテキストが自分の要件に不十分な場合は、各マッピングに対して独自のヘルプテキストを指定するためのYAML設定を利用することができる。

mappings:
- match: http.request.*
  help: "Total number of http requests"
  name: "http_requests_total"
  labels:
    code: "$1"

StatsD timers

statsd timerは、デフォルトで、Prometheusのサマリーとして表される。 分位数と許容誤差を設定することも出来る。

mappings:
- match: test.timing.*.*.*
  timer_type: summary
  name: "my_timer"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server"
  quantiles:
    - quantile: 0.99
      error: 0.001
    - quantile: 0.95
      error: 0.01
    - quantile: 0.9
      error: 0.05
    - quantile: 0.5
      error: 0.005

デフォルトの分位数は、0.99、0.9、0.5である。

この設定では、timerをヒストグラムにすることもできる。 The default is "summary" as in the plain text configuration format. 例えば、timerを1つのメトリックにするには、以下のようにする。

mappings:
- match: test.timing.*.*.*
  timer_type: histogram
  buckets: [ 0.01, 0.025, 0.05, 0.1 ]
  name: "my_timer"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server"

Regular expression matching

YAML設定を利用する際のもう一つの機能は、デフォルトのグロブ形式のマッチングの代わりに、正規表現を利用したマッチングの定義である。 これによって、名前の付け方の悪いStatsDメトリクスから構造化されたデータを引き出すことができ、より細やかなマッチングルールのターゲティングが可能になる。 パラメーターmatch_typeが指定されていない場合、デフォルト値globだと仮定される。

mappings:
- match: (.*)\.(.*)--(.*)\.status\.(.*)\.count
  match_type: regex
  name: "request_total"
  labels:
    hostname: "$1"
    exec: "$2"
    protocol: "$3"
    code: "$4"

ヒストグラムバケットも指定することが可能である。 指定されていない場合は、デフォルトのPrometheusクライアントの値[.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10]が利用される。 +Infは自動的に追加される。

timer_typeは、StatsDメトリック型がtimerの時にだけ利用される。 bucketsは、StatsDメトリック型がtimerでtimer_typeが"histogram"に指定された時にだけ利用される。

Global defaults

timer type、buckets、quantiles、match_typeに対してデフォルトを指定することもできる。 それらのデフォルト値は、その値が定義されなかったマッピング全てにおいて利用される。

defaults内でのみ設定出来る項目は、glob_disable_orderingである。 これは、省略されるとfalseとなる。 trueに設定すると、マッピングルールファイル内でのルールの出現順を守らなくなり、*を通常の文字列よりも常に低い優先順で扱うようになる。

defaults:
  timer_type: histogram
  buckets: [.005, .01, .025, .05, .1, .25, .5, 1, 2.5 ]
  match_type: glob
  glob_disable_ordering: false
  ttl: 0 # metrics do not expire
mappings:
# This will be a histogram using the buckets set in `defaults`.
- match: test.timing.*.*.*
  name: "my_timer"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server"
# This will be a summary timer.
- match: other.timing.*.*.*
  timer_type: summary
  name: "other_timer"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server_other"

match typeとしてglobかregexの選択

globマッチングは、マッピングとラベルのフォーマットで正規表現を利用するような柔軟性に欠けてはいるが、ある種のユースケースregexよりもパフォーマンスがよい。 端的に言うと、ルールの量が少なくなく、1つのルールでのキャプチャー(*の使用)があまり多くないなら、グロブが最善のパフォーマンスになる。 一般的なユースケースでは、glob_disable_orderingを変更しても、注目に値するほどのパフォーマンスへの効果はない。 ただし、以下のようなエッジケースでは、glob_disable_orderingをtrueにすると効果がある。

a.*.*.*.*
a.b.*.*.*
a.b.c.*.*
a.b.c.d.*

理由は、キャプチャー(*の使用)のリストへの割り当て操作がグロブの中で最もコストが高いからである。 出現順を守ると、10回ものリストへの割り当てをすることになるが、出現順を守らないなら、多くても4回だけになる。

詳細は、pkg/mapper/fsm/README.mdを参照すること。 ディレクトpkg/mappergo test -bench .を実行すると、この2つのマッチタイプの詳細な比較が生成される。

drop action

マッチに対してdropアクションを指定することで、メトリクスを削除することもできる。

mappings:
# This metric would match as normal.
- match: test.timing.*.*.*
  name: "my_timer"
  labels:
    provider: "$2"
    outcome: "$3"
    job: "${1}_server"
# Any metric not matched will be dropped because "." matches all metrics.
- match: .
  match_type: regex
  action: drop
  name: "dropped"

通常のmatchの構文を利用して、どんなメトリックでも削除することができる。 デフォルトのactionはmapであり、通常のメトリクスのマッピングを行う。

明示的なメトリック型のマッピング

StatsDは、同じメトリック名で異なるメトリック型を送信することができるが、Prometheusクライアントライブラリは、それらをまとめることはできない。 このようなユースケースでは、どちらのメトリック型にマッチするかをマッピング定義で指定することができる。

mappings:
- match: test.foo.*
  name: "test_foo"
  match_metric_type: counter
  labels:
    provider: "$1"

match_metric_typeで利用可能な値は、gaugecountertimerである。

時系列の有効期限

パラメーターttlは、古くなったメトリクスが無効になるまでの時間を定義するために利用できる。 値は、時間間隔と有効な単位("ns"、"us"(つまり"µs")"ms"、"s"、"m"、"h")である。 例えば、ttl: 1m20sとする。値に0を使うことで、時間切れしないメトリクスを表す。

TTLの設定は、マップされたそれぞれのメトリック名/ラベルの組み合わせに対して、サンプルが受信されるたびに保存される。 これは、マッピングの設定を変えただけですぐにメトリクスを無効にできないことを意味する。 更新されたマッピングが効果を得るためには、少なくとも1つのサンプルを受信する必要がある。

Using Docker

Dockerイメージprom/statsd-exporterを使ってこのexporterをデプロイすることができる。

docker pull prom/statsd-exporter

docker run -d -p 9102:9102 -p 9125:9125 -p 9125:9125/udp \
        -v $PWD/statsd_mapping.yml:/tmp/statsd_mapping.yml \
        prom/statsd-exporter --statsd.mapping-config=/tmp/statsd_mapping.yml

おすすめ書籍

入門 Prometheus ―インフラとアプリケーションのパフォーマンスモニタリング

入門 Prometheus ―インフラとアプリケーションのパフォーマンスモニタリング

入門 監視 ―モダンなモニタリングのためのデザインパターン

入門 監視 ―モダンなモニタリングのためのデザインパターン

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

和訳活動の支援

Prometheusドキュメント和訳が役に立った方は、以下QRコードからPayPayで活動を支援して頂けるとありがたいです。

PayPayによる支援用QRコード
上のQRコードからPayPayによる支援