この記事は、Mackerel アドベントカレンダー(全部CRE)の17日目の記事です。今回も、『プラグイン読み解きシリーズ』でいきたいと思います。題材は、mackerel-plugin-gostats!
当記事が前提とするバージョン
この記事を書いている今の最新版である、mackerel-agent-plugins の v0.53.0 を前提としています。
Releases · mackerelio/mackerel-agent-plugins · GitHub
また、このプラグインが利用しているパッケージ、fukata/golang-stats-api-handlerのバージョンはv1.0.0を前提としています。
どんなプラグイン?
このプラグインは、Goで書かれたアプリケーションが消費しているCPUやメモリリソースの状況、GC回数、goroutineの起動数などの情報を取得し可視化するためのプラグインです。といっても、それらの情報を取得に関しては、fukata/golang-stats-api-handlerを利用していることを前提としています。
インストールと設定手順
mackerel-plugin-gostats プラグインは、プラグイン集として提供しているパッケージ、 mackerel-agent-plugins
に含まれています。以下のようなコマンドでインストールすることができます。
$ yum install mackerel-agent-plugins
$ apt-get install mackerel-agent-plugins
詳細は下記ヘルプページも参照してください。
インストール先は /usr/bin/mackerel-plugin-gostats
です(他のプラグインも同じ場所にインストールされています)。
プラグイン自体のインストールはこれだけでいいのですが、先述の通り、各種メトリックの取得にfukata/golang-stats-api-handlerを利用しているため、監視対象のアプリケーションにも少しコードを追加する必要があります。詳細はREADMEにも記載があるのですが、追加するコードのサンプルとしては以下のようなものになります。
import ( "net/http" "log" "github.com/fukata/golang-stats-api-handler" ) func main() { http.HandleFunc("/api/stats", stats_api.Handler) log.Fatal(http.ListenAndServe(":8080", nil)) }
/api/stats
から以下のようなレスポンスが得られるようになっていれば、パッケージの追加は問題ないです。
$ curl http://localhost:8080/api/stats {"time":1544756661431593124,"go_version":"go1.9.4","go_os":"linux","go_arch":"amd64","cpu_num":2,"goroutine_num":4,"gomaxprocs":2,"cgo_call_num":0,"memory_alloc":3888912,"memory_total_alloc":9742251744,"memory_sys":72845560,"memory_lookups":555080,"memory_mallocs":20806672,"memory_frees":20789933,"memory_stack":557056,"heap_alloc":3888912,"heap_sys":67600384,"heap_idle":62078976,"heap_inuse":5521408,"heap_released":61718528,"heap_objects":16739,"gc_next":7712576,"gc_last":1544756580235402219,"gc_num":20495,"gc_per_second":0,"gc_pause_per_second":0,"gc_pause":[]}
この状態で、mackerel-plugin-gostats を手動実行してみましょう。このプラグインに限らず、Mackerelのプラグインは要はコマンドですので、手動でも実行する事ができます。
$ mackerel-plugin-gostats gostats.runtime.goroutine_num 4 1544756156 gostats.runtime.cgo_call_num 0 1544756156 gostats.memory.memory_alloc 3919360 1544756156 gostats.memory.memory_sys 72845560 1544756156 gostats.memory.memory_stack 557056 1544756156 gostats.operation.memory_lookups 40 1544756156 gostats.operation.memory_mallocs 1040 1544756156 gostats.operation.memory_frees 40 1544756156 gostats.heap.heap_sys 67600384 1544756156 gostats.heap.heap_idle 62062592 1544756156 gostats.heap.heap_inuse 5537792 1544756156 gostats.heap.heap_released 0 1544756156 gostats.gc.gc_num 0 1544756156 gostats.gc.gc_per_second 0 1544756156 gostats.gc.gc_pause_per_second 0 1544756156
設定ファイルである mackerel-agent.conf は、デフォルトでは /etc/mackerel-agent/mackerel-agent.conf
にインストールされます。mackerel-plugin-gostats を使う際の conf への追記内容などは、README.md に記載されていますので、ご確認ください。
mackerel-agent-plugins/README.md at master · mackerelio/mackerel-agent-plugins · GitHub
conf への追記ができたら、mackerel-agentを再起動することで設定完了です。
取得されるメトリック
このプラグインにより取得され、Mackerelにグラフ描画されるメトリックについて、以下に各グラフ定義ごとに説明します。 また表中の diff
とは、プラグイン側で差分値計算をするかどうかについて示しており、◯
となっている項目はプラグインの処理として「前回の実行時の値と差分」を計算し出力しています(データソースがいわゆるカウンターメトリックで単調増加する値)。diff
が ○
となっている値に関しては差分値ですが、それ以外の値はすべて、プラグイン実行時・そのときその瞬間の値となります。
Runtime
ラベル名 | メトリック名 | diff | 説明 |
---|---|---|---|
Goroutine Num | custom.gostats.runtime.goroutine_num |
- | 起動しているgoroutineの数。 runtime.NumGoroutine() で取得できる値。 |
CGO Call Num | custom.gostats.runtime.cgo_call_num |
○ | cgoによるCのコードの呼び出し回数。 runtime.NumCgoCall() で取得できる値。 |
Memory
ラベル名 | メトリック名 | diff | 説明 |
---|---|---|---|
Alloc | custom.gostats.runtime.memory_alloc |
- | allocateされていて未開放のメモリ領域。単位はbyte。 runtime.MemStats.Alloc で取得できる値。 |
Sys | custom.gostats.runtime.memory_sys |
- | システムが確保しているメモリ領域。単位はbyte。 runtime.MemStats.Sys で取得できる値。 |
Stack In Use | custom.gostats.runtime.memory_stack |
- | スタック領域として確保されているメモリ領域。単位はbyte。 runtime.StackInuse で取得できる値。 |
Operation
ラベル名 | メトリック名 | diff | 説明 |
---|---|---|---|
Pointer Lookups | custom.gostats.runtime.memory_lookups |
○ | ポインタルックアップの回数。 runtime.MemStats.Lookups で取得できる値。 |
Mallocs | custom.gostats.runtime.memory_mallocs |
○ | メモリ確保(malloc)の回数。 runtime.MemStats.Mallocs で取得できる値。 |
Frees | custom.gostats.runtime.memory_frees |
○ | メモリ解放(free)の回数。 runtime.Frees で取得できる値。 |
Heap
ラベル名 | メトリック名 | diff | 説明 |
---|---|---|---|
Sys | custom.gostats.runtime.heap_sys |
- | システムが確保しているメモリ領域。gostats.runtime.memory_sys とはまた別。単位はbyte。 runtime.MemStats.HeapSys で取得できる値。 |
Idle | custom.gostats.runtime.heap_idle |
- | アイドル状態のメモリ領域。単位はbyte。 runtime.MemStats.HeapIdle で取得できる値。 |
In Use | custom.gostats.runtime.heap_inuse |
- | 非アイドル状態のメモリ領域。単位はbyte。 runtime.MemStats.HeapInuse で取得できる値。 |
Released | custom.gostats.runtime.heap_released |
○ | 開放されたメモリ領域。単位はbyte。 runtime.MemStats.HeapReleased で取得できる値。 |
GC
ラベル名 | メトリック名 | diff | 説明 |
---|---|---|---|
GC Num | custom.gostats.runtime.gc_num |
○ | GCが走った回数。 runtime.MemStats.NumGC で取得できる値。 |
GC Per Second | custom.gostats.runtime.gc_per_second |
- | 1秒あたりのGC回数。 runtime.MemStats.NumGC で取得できる値とその前回値との差を、計測間隔の秒数で割った値。 |
GC Pause Per Second | custom.gostats.runtime.gc_pause_per_second |
- | 1秒あたりの、GCによる停止期間。 runtime.MemStats.PauseTotalNs で取得できる値とその前回値との差を、計測間隔の秒数で割った値。 |
利用可能なオプション
-scheme
fukata/golang-stats-api-handler により取得できる gostats の値を返す API エンドポイントへのリクエストの際のプロトコルを指定できます。デフォルト値は http
。
-host
fukata/golang-stats-api-handler により取得できる gostats の値を返す API エンドポイントのホスト部を指定できます。デフォルト値は localhost
。
-port
fukata/golang-stats-api-handler により取得できる gostats の値を返す API エンドポイントのポートを指定できます。デフォルト値は 8080
。
-path
fukata/golang-stats-api-handler により取得できる gostats の値を返す API エンドポイントのパスを指定できます。デフォルト値は /api/stats
。
-uri
fukata/golang-stats-api-handler により取得できる gostats の値を返す API エンドポイント全体を指定できます。デフォルト値なし。以下、使用例。
[plugin.metrics.gostats] command = "mackerel-plugin-gostats -uri=https://foobar:9999/hoge/fuga"
このオプションを指定した場合、上述の -scheme
-host
-port
-path
については無視されます。
-metric-key-prefix
このプラグインで取得されるメトリック、描画されるグラフのラベルなどに prefix を付与することができます。これを活用することにより、ひとつのホスト内で複数のGoアプリケーションが稼働していたとしても、それぞれを個別にモニタリングすることが可能です。こんな↓かんじ。
[plugin.metrics.gostats] command = "mackerel-plugin-gostats" [plugin.metrics.gostats_foobar] command = "mackerel-plugin-gostats -uri=https://foobar:9999/hoge/fuga -metric-key-prefix=foobar"
まとめ
Golang製アプリケーションのモニタリングに有用なプラグイン、mackerel-plugin-gostats を解説しました。私もGoで書いた趣味のWebアプリケーションはいくつか運用していて、このプラグインもすでに利用していたのですが、今回この記事を書いて改めて勉強になりました。runtime
パッケージすごい。
ちなみに、いろいろググっていたら以下のようなブログエントリを発見しました。
golang プロセスのモニタリングってみんなどうしてるんですかね、という話 - tokuhirom's blog
猛者たち(Mackerel のプロダクトマネージャーである id:Songmu の姿も!)のslack?での会話ログのようですね。みんな気にして取ってるのは gc count ぐらいなのかな
goroutineがリークしてないか一番気をつけてる
といった知見が詰まっていそうでしたので、ご興味ありましたらこちらもぜひ!