1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Prometheus + Grafana で Webサービス監視環境を構築する - 短命ジョブ監視編 -

Last updated at Posted at 2025-05-25

はじめに

Webアプリケーションは、ユーザーがブラウザで操作することを前提としているため、ユーザーを待たせてしまうような実行時間が長い処理は敬遠されます。
画面のボタンを押した後、次の操作ができるまで数分待たされるようなサービスは、誰も使いたがらないですよね。

解決策として、メッセージキューを使って別のバッチジョブに重たい処理を任せて、すぐにユーザーへレスポンスを返し、操作を継続できるようにする手法がよく用いられます。

メッセージキューのリクエストを処理するバッチジョブの実行時間が、想定していたよりも長時間かかる場合、何かしらの問題が発生している可能性があります。
バッチジョブもスロークエリと同様、処理時間がPrometheusで定義した閾値を超えた場合にアラート通知して、速めに原因調査と対策をとっていく必要があります。

ここで一つ課題が発生します。
バッチジョブは常時起動しておらず、メッセージキューにリクエストが登録されることをトリガーに起動し、処理が終わるとジョブ自体もなくなります。
一方で、Prometheusは一定周期でExporterにリクエストを送ってメトリクスを収集しています。
Prometheusがメトリクスを収集するタイミングでバッチジョブが存在していることを前提とするため、すぐに処理終了するバッチジョブの場合はメトリクスを収集できず、異常を検知できません。

image.png

そこで登場するのが「Pushgateway」と呼ばれる、Prometheus向けのメトリクス中継サービスです。
今回は、Pushgatewayを使ったアラート通知について説明します。

前提条件

本記事は、以下について概要レベルの知識を有している読者を想定しています。

本記事で紹介する環境構築は、以下の環境で行いました。

  • Windows11 WSL2(Ubuntu 22.04.5 LTS)
  • Docker version 27.5.1
  • Docker Compose version v2.34.0

本記事では、Prometheusによるモニタリングの中でも、Pushgatewayを用いた監視に焦点を当てて紹介します。
PrometheusやGrafana自体の説明や、外形監視、スロークエリやエラーレート監視、および、検証のための環境構築方法については以下を参照してください。

Prometheus + Grafana で Webサービス監視環境を構築する - 外形監視編 -

Prometheus + Grafana で Webサービス監視環境を構築する - スロークエリ・エラーレート監視編 -

Prometheus + Grafana で Webサービス監視環境を構築する - クライアントライブラリ監視編 -

解説

メッセージキューについて

image.png

メッセージキューについて、大まかな仕組みとしては以下の通りです。
ユーザーからのリクエストをWebアプリケーションが直接処理するのではなく、いったんメッセージキューに登録だけ行い、ユーザーには処理を受け付けたことをレスポンスして、ユーザー操作を継続可能にします。
その後、非同期で別のバッチジョブが起動し、メッセージキューからリクエストを取り出して処理を実行します。
バッチジョブは、以下に挙げるような方法で処理終了したことをWebアプリケーションに通知して、ジョブを停止します。

  • Webアプリケーションとバッチジョブが共有するデータベースに処理ステータスを書き込む
  • Webアプリケーションのエンドポイントにリクエストを送る

Pushgatewayについて

image.png

Pushgatewayはメッセージキューのような役割を担い、Prometheusとバッチジョブの間でメトリクスの中継を行います。
バッチジョブが処理終了する際、Pushgatewayにメトリクスを送信します。
Prometheusは、Pushgatewayに蓄積されたバッチジョブのメトリクスを一定周期で収集します。

なお、Pushgatewayに蓄積されたメトリクスは、APIやWebUIから明示的に削除を実行しない限り残り続けます。
Prometheusは、メトリクスを収集するだけで、Pushgateway上のデータを削除できません。

Prometheusは定期的にメトリクスを収集するため、すでに一度読み取ったメトリクスが何度も収集される可能性があります。
Prometheusが過去の異常値を繰り返し収集してしまうと、毎回アラートが発生する恐れがあります。これを防ぐには、Pushgatewayのメトリクスを定期的に削除する仕組みが必要です。

詳細は割愛しますが、クリーンアップ用のバッチを別途用意して、一定時間ごとにPushgateway上のメトリクスを削除していく仕組みを実行するなど、メトリクスの蓄積によるアラート誤発報を防ぐための、削除やクリーンアップの対策が必要です。
アラート通知が上がった際にGrafanaのダッシュボードを確認する時間を考慮すると、短すぎる周期ではなく、ある程度余裕を持たせた周期でクリーンアップを実行するとよいでしょう。

監視環境の構成図(再掲)

今回構築する監視環境の構成図は以下の通りです。

overview.png

環境構築手順

Grafanaのダッシュボード作成

[Home > Dashboards > New dashboard > Edit panel] から、Pushgatewayのメトリクスを表示するダッシュボードを作りましょう。

Metrics browserにPromQLを入力して、VisualizationsにTime seriesを選択してパネルを作成します。

batch_duration_seconds{exported_job=~"sample_.*"}

image.png

続けて、直近のバッチ処理時間を一覧化するパネルを追加します。PromQLは先ほどと同様で、VisualizationsにTableを選択してパネルを作成します。

image.png

Pushgatewayから明示的にメトリクスを削除するまでは、Prometheusは同じバッチジョブのメトリクスを何度も収集するため、バッチジョブ名でフィルタリングして最新の1レコードのみを表示させます。
TransformationからReduceを追加して、CalculationsにLast*を選択しましょう。

image.png

exported_job名と実行時間だけ表示させたいので、TransformationからOrganize fields by nameを追加して、exported_jobとLast*以外は非表示にしましょう。

image.png

バッチ処理時間の閾値の10秒を赤いラインで示したいので、Thresholdsで固定値10を赤色で設定します。

image.png

バッチ処理時間の表示幅を0~10秒で出すため、AxisのSoft minに0、Soft maxに10を設定します。

image.png

パネルの表示位置を調整して、ダッシュボードを保存しましょう。

image.png

アラート条件の設定

アラート条件の設定はprometheus/alert_rules.ymlで定義しています。
今回は、以下のアラート条件を設定しました。

prometheus/alert_rules.yml
  - name: pushgateway_alerts
    rules:
      - alert: PushJobDurationTooLong
        expr: batch_duration_seconds{exported_job=~"sample_.*"} > 10 # ジョブ実行時間が10秒を超えたら
        for: 0s  # すぐにアラートを発火
        labels:
          severity: warning
        annotations:
          summary: "Pushgateway job duration too long"
          description: "A push job took more than 10 seconds to complete. Duration: {{ $value }}s, Job: {{ $labels.exported_job }}"

短命ジョブのアラート通知検証

バッチジョブの作成

今回は、簡易的なシェルスクリプトを作成して、バッチジョブからPushgatewayにリクエストを送る動作検証を行います。
シェルのパラメータでジョブIDと処理時間(秒)をパラメータで受け取り、指定された秒数sleepして、バッチの処理時間を算出してPushgatewayにcurlコマンドでメトリクスをPushするだけのものです。

pushgateway/push_duration.sh
#!/bin/bash

# 引数チェック
if [ "$#" -ne 2 ]; then
  echo "Usage: $0 <request_id> <sleep_seconds>"
  exit 1
fi

REQUEST_ID="$1"
SLEEP_SECONDS="$2"

# バリデーション(sleep秒数は整数のみ許可)
if ! [[ "$SLEEP_SECONDS" =~ ^[0-9]+$ ]]; then
  echo "Error: sleep_seconds must be a positive integer"
  exit 1
fi

# 開始時刻(秒)
START_TIME=$(date +%s)

# ----------------------------------
# バッチ処理の代わりに sleep
sleep "$SLEEP_SECONDS"
# ----------------------------------

# 終了時刻(秒)
END_TIME=$(date +%s)

# duration 計算
DURATION=$((END_TIME - START_TIME))

# ジョブ名の生成
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
JOB_NAME="sample_${REQUEST_ID}_${TIMESTAMP}"

# Pushgateway URL
PUSHGATEWAY_URL="http://localhost:9091"

# メトリクスをPush
cat <<EOF | curl --data-binary @- "${PUSHGATEWAY_URL}/metrics/job/${JOB_NAME}"
# TYPE batch_duration_seconds gauge
batch_duration_seconds ${DURATION}
EOF

echo "Pushed batch_duration_seconds=${DURATION} to job=${JOB_NAME}"

また、Pushgatewayに蓄積されたメトリクスを削除するためのシェルスクリプトも作成しておきましょう。
Pushgatewayからメトリクスの一覧を取得し、1件ずつDELETEするだけのものです。

pushgateway/clean_pushed_jobs.sh
#!/bin/bash

PUSHGATEWAY_URL="http://localhost:9091"
PROMETHEUS_URL="http://localhost:9090"
JOB_PREFIX="sample_"

echo "=== Fetch job list from Pushgateway ==="

job_list=$(curl -s "$PUSHGATEWAY_URL/metrics" | grep '^batch_duration_seconds{' | sed -E 's/.*job="([^"]+)".*/\1/' | sort | uniq)

echo "=== job_list ==="
echo "$job_list"
echo "==============="

for job in $job_list; do
  if [[ "$job" =~ ^$JOB_PREFIX ]]; then
    echo "🔍 Checking Prometheus for job: '$job'"

    query="batch_duration_seconds{exported_job=\"$job\"}"
    result=$(curl -s --get --data-urlencode "query=$query" "$PROMETHEUS_URL/api/v1/query" | jq -r '.data.result | length')

    echo "Result count: $result"

    if [[ "$result" -gt 0 ]]; then
      echo "✅ Job '$job' found in Prometheus. Deleting from Pushgateway..."
      curl -s -X DELETE "$PUSHGATEWAY_URL/metrics/job/$job"
      echo "Deleted job '$job' from Pushgateway."
    else
      echo "⏭️  Job '$job' not yet collected by Prometheus. Skipping deletion."
    fi
  fi
done

メトリクスをPushし、アラート通知確認

事前に用意したシェルスクリプトを使って、アラート通知を検証します。
ジョブIDにid_0001、処理時間(秒)に3を指定してシェルスクリプトを実行します。
なお、閾値の10秒超を指定していないため、アラート通知はされません。

$ . pushgateway/push_duration.sh id_0001 3
Pushed batch_duration_seconds=3 to job=sample_id_0001_20250525092623

PushgatewayのWebUIで、Pushされたメトリクスを確認できます。

http://localhost:9091/
image.png

Grafanaのダッシュボードでもメトリクスを確認できます。

image.png

それでは、シェルスクリプトで11秒を指定して、アラート通知を確認してみましょう。

$ . pushgateway/push_duration.sh id_0002 11
Pushed batch_duration_seconds=11 to job=sample_id_0002_20250525093138

Pushgatewayにメトリクスが送られます。

image.png

Prometheusでアラートを検知しました。

image.png

Slackにもアラートが通知されました。

image.png

Grafanaのダッシュボードでも閾値を超えたことを確認できます。

image.png

最後に、クリーンアップのシェルスクリプトでPushgatewayのメトリクスを削除しておきましょう。

$ . pushgateway/clean_pushed_jobs.sh 
=== Fetch job list from Pushgateway ===
=== job_list ===
sample_id_0001_20250525092623
sample_id_0002_20250525093138
===============
🔍 Checking Prometheus for job: 'sample_id_0001_20250525092623'
Result count: 1
✅ Job 'sample_id_0001_20250525092623' found in Prometheus. Deleting from Pushgateway...
Deleted job 'sample_id_0001_20250525092623' from Pushgateway.
🔍 Checking Prometheus for job: 'sample_id_0002_20250525093138'
Result count: 1
✅ Job 'sample_id_0002_20250525093138' found in Prometheus. Deleting from Pushgateway...
Deleted job 'sample_id_0002_20250525093138' from Pushgateway.

PushgatewayのWebUIからメトリクスが削除されたことを確認できます。

image.png

Prometheusのアラートも正常に戻りました。

image.png

Slackにもアラート状態が回復されたことが通知されました。

image.png

Grafanaのダッシュボードでもメトリクスが削除されたことを確認できます。

image.png

image.png

まとめ

本記事では、短命なバッチジョブの実行時間を監視し、一定時間を超えた処理に対してアラート通知を行う方法として、Pushgatewayを用いたPrometheus監視の手法を紹介しました。

Webアプリケーションにおいて、ユーザー体験を損なわないために非同期バッチ処理を採用するケースは多くありますが、それに伴い即時起動・即時終了するジョブの監視の難しさが生まれます。

Pushgatewayはその課題を解決する手段として非常に有効です。ジョブ終了時にメトリクスをPushすることで、Prometheusが定期収集するモデルと両立しながら、ジョブの実行時間を確実に監視できます。また、Grafanaを用いた可視化やアラートルールの設定によって、異常の早期発見と対処が可能になります。

ただし、Pushされたメトリクスは明示的に削除しない限り残り続けるため、不要なアラートの再発防止のためのクリーンアップ処理は必須です。

この手法を導入することで、ユーザーに見えないバッチ処理の遅延を素早くキャッチでき、より信頼性の高いWebアプリケーションの運用につながるでしょう。

一緒にOSSについて学んでいきたいなど、ご興味を持たれた方は、弊社ホームページからお問い合わせいただければ幸いです。

参考

ウィキペディア:メッセージキュー

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?