FIXER cloud.config Tech Blog
Prometheusで辞書形式のメトリクスを持つExporterを作りたい!
2023年08月02日 10時00分更新
本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「Prometheusで辞書形式でメトリクスを持つようなExporterを作りたい!」を再編集したものです。
PrometheusのExporterは自作することができ、先人が既に簡単な書き方の記事を挙げています。 しかし、タイトルにある通り辞書型のような形式でメトリクスを保持するような方法が記載されているドキュメントは見当たらなかったので、ブログにしてみようと思いました。
動作環境
・macOS
・Ventura 13.2.1
・Go
・1.20.3
・Rancher Desktop
そもそもPrometheusとは? Exporterとは?
Prometheusはざっくり言うと、「メトリック監視のために時系列ごとの値を保存することができるOSS」です。 値の収集はymlで定義されたExporterと呼ばれるものからPrometheus側からスクレイピングをしており、そこで収集したデータを独自の圧縮形式でファイルに保存しています。 Prometheusで収集したデータはPrometheusのウェブUIまたはGrafanaなどの可視化ツールでpromqlと呼ばれるクエリを使うことで値の取得やグラフの描画ができます。
詳しくは公式ドキュメントを参考にしてみてください。
ソースコード
今回はプロセス監視のため、 psコマンドで取得したcpu使用率をアプリケーションのファイルパスをキーとするような辞書型のメトリクスで出力できるようにExporterを実装しました。
package main
import (
"flag"
"net/http"
"os/exec"
"strings"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// メトリクスの名前空間用の変数
var namespace = "process"
// メトリクス保持をする変数
var cpuUsagePercentGauge = promauto.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "cpu_usage_percent",
Help: "cpu usage percent by process",
},
[]string{"filename"},
)
// メトリクス収集用の関数
func Collect() {
// psコマンドの実行結果を取得
commandResult, _ := exec.Command("/bin/zsh", "-c", "ps aux | awk '{ printf(\"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\\n\",$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);}'").Output()
convertedCommandResult := string(commandResult)
convertedCommandResultArray := strings.Split(convertedCommandResult, "\n")
// 取得した実行結果からアプリケーションのファイルパスをキーとしてcpu使用率を代入
for i := 0; i < len(convertedCommandResultArray) - 1; i++ {
row := strings.Split(convertedCommandResultArray[i + 1], ",")
if len(row) > 10 {
cpuUsagePercent, _ := strconv.ParseFloat(row[2], 64)
fileName := row[10]
cpuUsagePercentGauge.With(prometheus.Labels{"filename": fileName}).Set(cpuUsagePercent)
}
}
}
func main() {
flag.Parse()
// 並列処理で無限ループ
go func() {
for {
// メトリクス収集
Collect()
// 一度メトリクス収集してから30秒待つ
time.Sleep(30 * time.Second)
}
}()
// localhost:8191で待機
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8191", nil)
Collect()
}
環境構築
Exporter
作成したソースコードをビルドして実行ファイルを生成した後、コマンドラインで実行しておけばExporter側の準備は完了です。
Prometheus
予め適当なディレクトリにprometheus.ymlを配置しておきます。
global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'process_exporter' static_configs: - targets: ['host.docker.internal:8191']
その後また別のディレクトリでdocker-compose.ymlを配置します。
version: '3' services: prometheus: image: prom/prometheus container_name: prometheus volumes: - /path/to/prometheus.yml:/etc/prometheus/prometheus.yml ports: - 9090:9090
最後にdocker-compose.ymlを配置したディレクトリで下記コマンドを実行すればPrometheus側の準備は完了です。
実行結果
http://localhost:9090 をブラウザーで開いた後、クエリの入力欄にprocess_cpu_usage_percentと入力してExecuteボタンを押せば確認できます。
また、クエリを編集すれば出力するプロセスの絞り込みができたり、関数を使って合計値をグラフで出力することも可能です。
感想
今回はローカルマシンでプロセスを監視しましたが、VM上で実行すればVMのプロセスを監視できるはずです。加えて、外部からPrometheusにアクセスできるようにすればわざわざVMに接続してタスクマネージャーなどを開かなくてもウェブ上から閲覧できます。そういう仕組みづくりができればVMの負荷が高騰した時もどのプロセスが原因なのか後から調査する場合でも対応ができるようになると思います。
こういった仕組みづくりはやっぱり好きだなぁとコードを書いていてしみじみ思いました。
三上柊悟/FIXER
開発したり運用したりしてる人。好物はメロンパン。


この連載の記事
-
TECH
「SOSの出し方を知ろう」 新卒入社から1年、学んだことを振り返る -
TECH
はじめてのOSSコントリビュートで“推しからのリプ”をもらった話 -
TECH
Kubernetesのcert-managerについて簡潔にまとめておきますね -
TECH
WSL2でのGitHubの認証をできる限り簡単に行う方法 -
TECH
MacでGitHub CLIの認証を行う方法 -
TECH
ゆるく理解する自作シェル実装1:そもそもシェルってどんなもの? -
TECH
プロンプトエンジニアリングのコツは「5W1Hを忘れずに」 -
TECH
GitHubの 超・超・超 基本的な使い方まとめ -
TECH
業務で使えるExcel関数テクニック − 関数を使った動的な範囲指定のコツ -
TECH
zshの初期設定がダサい…。表示内容を自分好みにカスタマイズしていく -
TECH
Proxmox VE+OpenMediaVaultで自宅用NASを作ってみた - この連載の一覧へ




