Splunk OpenTelemetry Collectorでホスト、NGINX、MySQLを可視化
Observability 川口 明彦ISUCON は、お題となる Web サービスを、決められたルールの中で限界まで高速化するチューニングコンテストです。1〜3 名のチームが限られた時間内にアプリケーションやミドルウェアを改善し、ベンチマーカーが計測したスコアを競います。
ISUCON の練習では、トレースを追う前に、ホスト、リバースプロキシー、データベースの負荷を確認すると、次に調べる対象を絞り込めます。
本記事では、Linux 1 台に Splunk Distribution of the OpenTelemetry Collector(以下 Splunk OTel Collector)を導入します。ホスト、NGINX、MySQL のメトリックを Splunk Observability Cloud へ送り、ボトルネック候補を確認する手順を紹介します。
検証は ISUCON 過去問(ISUCON14)の練習用仮想マシン 1 台で行いました。本記事の内容は、2026 年 10 月 4 日時点の公式インストーラーと画面で確認しています。
本記事で扱う範囲
本記事で扱う範囲は次のとおりです。
- 収集対象:Linux のエージェントモードによるホストメトリック、NGINX の stub_status、MySQL のグローバルステータス
- 対象外:APM、トレース、アプリのゼロコード計装、ログの取り込み、自動検出(--discovery)
本記事では、ボトルネック候補を絞るためのメトリックに範囲を限定します。
前提
次を前提とします。
- ISUCON の本番ではなく、練習環境での実施
- Splunk Observability Cloud Free Edition のアカウント
- NGINX と MySQL が動作する Ubuntu 系の Linux ホスト 1 台
- sudo 権限と、Splunk Observability Cloud への外向き HTTPS 通信
- Splunk OTel Collector が未導入、または再インストールできる環境
インストーラーのメモリー設定は既定で 512 MiB です。本検証では、メモリー 4 GiB のホストで --memory 128 を指定しました。この値は Collector に割り当てるメモリーの設定です。OS が強制する RSS の上限ではありません。メモリー制限の警告やデータの欠落が発生する場合は、既定値へ戻すか値を増やしてください。
トークンやパスワードの実際の値は記事に書きません。コマンド例ではプレースホルダーを使います。実行時は、実際の値に置き換えてください。
Splunk OTel Collector の導入
Splunk Observability Cloud の realm(レルム)と、取り込み用アクセストークンを用意します。次の例では、realm を環境変数に設定し、アクセストークンをファイルに保存します。
Linux 向けインストーラー は agent モードが既定です。メモリーだけ 128 MiB にします。
export SPLUNK_REALM="<your-realm>"
install -d -m 700 "$HOME/.config/splunk"
cat > "$HOME/.config/splunk/ingest.token" <<'EOF'
<ingest-access-token>
EOF
chmod 600 "$HOME/.config/splunk/ingest.token"
curl -fsSL https://dl.observability.splunkcloud.com/splunk-otel-collector.sh \
-o /tmp/splunk-otel-collector.sh &&
sudo sh /tmp/splunk-otel-collector.sh \
--realm "$SPLUNK_REALM" \
--memory 128 \
--mode agent \
< "$HOME/.config/splunk/ingest.token"
sudo rm -f /tmp/splunk-otel-collector.sh
--discovery は付けません。自動検出を使う場合も、NGINX の stub_status と MySQL のモニターユーザーは別途必要です。本記事では、収集対象が設定ファイルで分かるように receiver を明示します。
インストールしたバージョンと、同じホストで動く NGINX、MySQL のバージョンを確認します。
dpkg-query -W -f='${Package} ${Version}\n' splunk-otel-collector
nginx -v
mysql --version
インストーラーが作る既定設定には host metrics receiver が含まれます。CPU、メモリー、ディスク、ファイルシステム、ロード、ネットワークのメトリックを収集できます。プロセス単位のスクレイパーは既定で無効です。後の節で NGINX、MySQL、アプリの 3 種類に絞って有効にします。
インストール後は、同じホストで Collector の起動を確認します。確認先はループバックのポート 13133 です。
curl -fsS http://127.0.0.1:13133
Server available を含む JSON が返れば、Collector プロセスは起動しています。この応答だけでは、各 receiver の収集やデータ送信の成功までは確認できません。
NGINX、MySQL、プロセスメトリックの追加
ホストメトリックは既定で収集されます。続いて NGINX、MySQL、プロセス単位の設定を追加します。
Collector のバージョンによって、ホストメトリックの receiver ID が host_metrics または hostmetrics の場合があります。以降の例では本検証環境の host_metrics を使います。既存の設定が hostmetrics の場合は、その ID を変更せずに使ってください。
以下の YAML は、既存設定に加える差分です。トップレベルの receivers: や service: を重複して作らず、既存の processor、exporter、receiver を残してください。
NGINX の stub_status と receiver
NGINX receiver は、ngx_http_stub_status_module のエンドポイントをスクレイプします。公式サンプルの既定 URL は http://localhost:80/status です。本検証では、80 番の default_server に設定を加え、ループバックからの接続だけを許可しました。
http://127.0.0.1/nginx_status は、この 80 番の default_server に届きます。次のパスは、本検証の ISUCON14 のものです。他の年の ISUCON では、NGINX の構成に合わせて対象ファイルを読み替えてください。
sudo vim /etc/nginx/sites-available/isuride.conf
編集後の先頭の server は、次のとおりです。既存の location / は残します。
server {
listen 80 default_server;
server_name _;
index index.html index.htm index.nginx-debian.html;
root /var/www/html;
location = /nginx_status {
stub_status;
access_log off;
allow 127.0.0.1;
deny all;
}
location / {
try_files $uri $uri/ =404;
}
}
構文を確認してから再読み込みします。続けて Active connections が見えることを確認します。
sudo nginx -t && sudo systemctl reload nginx
curl -fsS http://127.0.0.1/nginx_status
Collector の設定ファイルを開きます。
sudo vim /etc/otel/collector/agent_config.yaml
receivers: に nginx を追加します。metrics パイプラインは receivers 行だけを変更します。既存の processor と exporter は残します。
receivers:
+ nginx:
+ endpoint: http://127.0.0.1/nginx_status
+ collection_interval: 10s
service:
pipelines:
metrics:
- receivers: [host_metrics, otlp]
+ receivers: [host_metrics, otlp, nginx]
MySQL のモニターユーザー
MySQL receiver は、グローバルステータスなどを取得します。アプリ用の DB ユーザーは使わず、必要な権限だけを持つモニターユーザーを作ります。
<password> は、この手順であなたが新しく決める任意のパスワードへ置き換えてください。同じ値を Collector の MYSQL_PASSWORD に設定します。
MySQL クライアントを起動します。
sudo mysql
MySQL プロンプトで Performance Schema の状態を確認します。
SHOW VARIABLES LIKE 'performance_schema';
ON なら、次の手順へ進みます。OFF の場合は、設定ファイルに performance_schema=ON を追加してください。その後、MySQL を再起動します。再度状態を確認し、ON になったらモニターユーザーを作ります。
CREATE USER 'otel'@'127.0.0.1' IDENTIFIED BY '<password>';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'otel'@'127.0.0.1';
GRANT SELECT ON performance_schema.* TO 'otel'@'127.0.0.1';
SHOW GRANTS FOR 'otel'@'127.0.0.1';
本記事ではクエリーサンプルや実行計画を収集しないため、アプリのスキーマに対する SELECT は付与しません。MySQL receiver の既定のメトリック収集は、クエリーサンプルとは別に performance_schema を参照します。対象はテーブル I/O、インデックス I/O、ステートメント統計、テーブルロック待ちです。MySQL receiver のユーザー作成例に従い、performance_schema.* への SELECT を付与します。
すでにモニターユーザーだけを作っている場合は、同じ GRANT SELECT を追加してください。この権限が無いと、10 秒ごとに Error 1142 がログへ出ます。
シェルプロンプトへ戻り、作成したユーザーでステータスを取得できることを確認します。-p の後にはパスワードを書かず、表示されるプロンプトで入力してください。
mysql -h 127.0.0.1 -u otel -p \
-e "SHOW GLOBAL STATUS LIKE 'Threads_running';"
次に、パスワードを Collector の環境変数ファイルへ書きます。既存の SPLUNK_* 行は残します。
sudo vim /etc/otel/collector/splunk-otel-collector.conf
ファイルの末尾へ、次の 2 行を足します。
MYSQL_USER=otel
MYSQL_PASSWORD=<password>
ファイルを保存したら、所有者と権限を確認します。他のローカルユーザーが読める場合は、権限を 600 に制限してください。
sudo stat -c '%U:%G %a %n' \
/etc/otel/collector/splunk-otel-collector.conf
sudo chmod 600 /etc/otel/collector/splunk-otel-collector.conf
Collector の設定を再び開きます。
sudo vim /etc/otel/collector/agent_config.yaml
receivers: に mysql を追加します。metrics パイプラインの既存設定は残します。
receivers:
+ mysql:
+ endpoint: 127.0.0.1:3306
+ username: ${env:MYSQL_USER}
+ password: ${env:MYSQL_PASSWORD}
+ collection_interval: 10s
service:
pipelines:
metrics:
- receivers: [host_metrics, otlp, nginx]
+ receivers: [host_metrics, otlp, nginx, mysql]
Database Monitoring 向けの db.server.query_sample や db.server.top_query は有効にしません。これらを無効にしても、テーブル I/O などの performance_schema メトリックは収集されます。そのため、前の節の SELECT が必要です。
プロセス単位の CPU
NGINX、アプリ、MySQL のどれが CPU を使っているかを分けるため、プロセス単位のスクレイパーをこの 3 つに絞って有効にします。
同じ Collector 設定を再び開きます。
sudo vim /etc/otel/collector/agent_config.yaml
host_metrics の scrapers: にある # process: を、次の差分のように置き換えます。cpu、memory、disk など、ほかの scraper はそのまま残します。
receivers:
host_metrics:
scrapers:
- # process:
+ process:
+ include:
+ names: [nginx, mysqld, isuride]
+ match_type: strict
+ mute_process_exe_error: true
+ mute_process_name_error: true
+ resource_attributes:
+ process.command_line:
+ enabled: false
+ metrics:
+ process.cpu.utilization:
+ enabled: true
isuride は ISUCON14 の Go 実装のプロセス名です。ほかの言語では ps でプロセス名を確認して置き換えてください。
process scraper は、既定でコマンドラインなどの属性も収集できます。アプリの起動引数に認証情報が含まれる場合に備え、この例では process.command_line を無効にしています。
設定の検証
設定を反映するため、サービスを再起動します。
sudo systemctl restart splunk-otel-collector
sudo systemctl is-active splunk-otel-collector
curl -fsS http://127.0.0.1:13133
active と表示され、health check が成功することを確認します。続いて、直近のログを確認します。エラーが出力されないことを確認してください。
sudo journalctl -u splunk-otel-collector \
--since "-5 minutes" --no-pager
チャートが空のままにならないよう、確認用の短い負荷をかけます。本検証では、練習用の HTTP 負荷を 1 分ほど流しました。
process.cpu.utilization は、最初の収集時には値を生成しません。負荷を開始して 20 秒以上待ってから Splunk Observability Cloud の Metrics を開き、次を確認してください。
- cpu.utilization が表示されること
- process.cpu.utilization が表示されること
- NGINX receiver 由来のメトリックが表示されること
- mysql.threads が表示されること
画面の読み方
ホスト CPU、プロセス CPU、MySQL のチャートは Metrics から開きます。本検証環境では、NGINX の情報を Dashboards から確認できました。掲載する 4 枚の画面では、ホスト名やアカウント ID をマスクしています。
SignalFlow を使うチャートは、Metric Finder の View in chart から開きます。その後、Plot editor タブの View SignalFlow で式を置き換えます。
複数のホストが登録されている場合は、チャートのフィルターで対象ホスト 1 台を選んでください。以降の式と数値は、対象ホストを絞り込んだ状態を前提とします。
ホスト CPU
図 1: 負荷区間のホスト CPU 使用率
cpu.utilization です。負荷をかけた約 1 分間、100% に張り付きました。どのプロセスが使っているかは、次のプロセス別のチャートで確かめます。
プロセス別の CPU
図 2: プロセス別の CPU 使用率
process.cpu.utilization をプロセス名(process.executable.name)ごとに合計したチャートです。メトリックは 0 から 1 の比率なので、百分率で表示するために 100 倍します。
SignalFlow での表記は、次のとおりです。
A = data('process.cpu.utilization').sum(by=['process.executable.name']).scale(100).publish(label='A')
各系列のプロセス名と値は、Data table タブで確かめられます。本検証の初期実装では、負荷をかけた区間で mysqld が約 85%、isuride が 1 割未満でした。mysqld が大半なら MySQL 側を、isuride が大半ならアプリ側を先に確認します。
選択していないプロセスやカーネル処理も CPU を使うため、プロセス別の合計がホスト CPU と一致するとは限りません。
NGINX の接続
図 3: NGINX の接続状態と接続処理数
本検証環境では、Dashboards で NGINX を検索し、NGINX servers を開くとデータを確認できました。NGINX receiver の標準ダッシュボード対応はバージョンや構成によって異なります。表示されない場合は、Metrics から NGINX receiver のメトリックを選び、カスタムチャートを作成してください。
Active は現在のクライアント接続数で、Reading、Writing、Waiting を含みます。Waiting は、次のリクエストを待つアイドル状態の keep-alive 接続です。増加だけで異常とは判断しません。
accepted と handled は、NGINX の起動後からの累積カウンターです。通常は同じ値になります。handled が accepted を継続的に下回り、Connections drop が増える場合は、worker_connections などの接続上限を確認します。本検証では Connections drop はほぼ 0% でした。
MySQL のスレッド
図 4: MySQL の接続スレッド数と実行中スレッド数
mysql.threads を、kind が connected と running のものに絞ったチャートです。connected は開いている接続数を示します。running は休止していないスレッド数を示します。
SignalFlow での表記は、次のとおりです。
A = data('mysql.threads', filter=filter('kind', 'connected', 'running')).sum(by=['kind']).publish(label='A')
負荷をかけた区間で、connected は 3 から 51 へ、running は 2 から 27 へ増えました。CPU 使用率と running が同時に増える場合は、クエリーの並行実行、遅いクエリー、ロック待ちなどを調べる手掛かりになります。ただし、このメトリックだけでは原因を特定できません。
本記事の設定では、NGINX のアクセスログや MySQL の低速なクエリーのログを収集しません。必要な場合は、ログ用の receiver とパイプラインを別途設定してください。
計測時の注意
Collector 自体も CPU とメモリーを使用します。診断用の計測では Collector を動かし、ボトルネック候補を絞ります。公式スコアを比較するときは大会のルールを確認し、計測目的に応じて Collector を止める選択肢があります。
Collector を止めると、新しいメトリックは送信されません。スコア計測後に再開する場合は、次のように操作します。
sudo systemctl stop splunk-otel-collector
# スコア計測
sudo systemctl start splunk-otel-collector
ISUCON2026 のレギュレーションによると、競技終了後の追試では主催者がサーバーを再起動します。本番で Collector を使った場合は、追試の再起動で起動しないよう、競技終了前に自動起動も無効にします。
sudo systemctl disable --now splunk-otel-collector
複数台構成への応用
複数台のサーバーを使う場合は、各サーバーに Collector を導入します。NGINX と MySQL の receiver は、それぞれが動くサーバーだけで有効にします。役割を分けた後は、ホストごとのチャートで負荷の偏りを確認できます。
まとめ
本記事では、次の順序でボトルネック候補を絞りました。
- ホスト CPU によるシステム全体の飽和確認
- プロセス別 CPU による負荷の発生元の確認
- NGINX の接続状態によるリバースプロキシーの確認
- MySQL のスレッド数によるデータベース負荷の確認
APM やログ分析へ進む前に、この順序でメトリックを確認すると、次に調べる対象を絞り込めます。
本記事は練習環境を前提にしましたが、同じ手順は ISUCON の本番にも応用できます。本番も NGINX と MySQL を使う場合は、NGINX の設定ファイルとアプリのプロセス名を読み替えて導入できます。最終的なスコアを計測する前には、「計測時の注意」のとおり Collector を止めてください。
次のステップ
- Splunk Observability Cloud Free Edition は、15 ホストまでクレジットカードなしで登録できます。
- Collector の導入方法は、Linux 向けインストーラー を参照してください。
- receiver の詳細は、Host metrics receiver、NGINX receiver、MySQL receiver を確認してください。
- 10/22開催予定のウェビナー「計装して、測って、外す。ISUCON の過去問で学ぶ OpenTelemetry の実践」では、Go アプリの計装からボトルネックの特定までをライブで実演します。ぜひご参加ください。
関連記事

オブザーバビリティの実現が必要な理由 環境の複雑化とビジネスの高速化

データストレージコストの不安を解消:Archived Metricsのご紹介
