【入門編】Sentryの「Crons」機能でバッチ処理と定期ジョブの失敗を監視する!Heartbeat監視の実装ガイド – 運用監視・オブザーバビリティ活用バイブル

こんにちは!日々のシステムの安定稼働、本当にお疲れ様です。
WebサーバーのAPIがエラーを出したらすぐにアラートが飛ぶ仕組みを作っている人は多いですが、「夜間バッチがしれっと途中で止まっていた」「KubernetesのCronJobがOOMKilled(メモリ不足)で沈黙していたのに、誰も気づかなかった」……そんな冷や汗をかくような経験はありませんか?

Webアプリケーションの監視が完璧でも、裏でこっそり動くバックグラウンドジョブが「サイレント障害(エラーログすら残さず、ただ沈黙する障害)」を起こすと、翌朝にユーザーからの問い合わせで発覚するという最悪の事態につながります。

今回は、Sentryの隠れた(いや、実は最強の)機能である「Sentry Crons(ハートビート監視)」を使って、バッチ処理や定期ジョブの死活監視を完全に手中に収める方法を、優しく丁寧にお伝えします。これをマスターすれば、朝出社したときの「バッチ動いてるかな…?」という不安なドキドキから完全に解放されますよ。

—

1. なぜ「ログ監視」や「死活監視」だけでは不十分なのか?

まずは、バックグラウンドジョブ監視の難しさを少しだけ整理しましょう。

一般的な監視手法として、サーバーのCPU使用率やプロセスの生存確認(Pingなど)があります。しかし、これらは「プロセスが生きているか」はわかっても、「ジョブが正常に最後まで完了したか」までは教えてくれません。
また、バッチスクリプトの中でエラー起因の例外キャッチを忘れていると、Sentryにエラーすら飛ばずにプロセスが異常終了してしまうこともあります。

そこで登場するのが、Heartbeat(心音)方式の監視です。
「私は今から処理を始めます(Check-in: in_progress)」
「無事に処理が終わりました(Check-in: ok)」
という信号(心音)を、ジョブ側から定期的にSentryへ送り続けるのです。もし、決まった時間になっても「終わったよ」の信号が来なければ、Sentryが「あれ、心音が止まったぞ?」と検知して、Slackやメールに緊急アラートを飛ばしてくれます。

—

2. Sentry Cronsの仕組みと基本概念

Sentry Cronsのセットアップは拍子抜けするほど簡単ですが、事前に知っておくべき概念が2つあります。

1. Monitor Slug(モニター名): ジョブを一意に識別する名前(例: `nightly-billing-batch`)。
2. Check-in(チェックイン): ジョブの状態をSentryに伝えるアクション。主に以下の3つのステータスを送ります。

  • `in_progress`: ジョブが開始された(オプションですが、タイムアウト検知に超重要!)
  • `ok`: ジョブが正常に完了した
  • `error`: ジョブが異常終了した

それでは、実際にLinuxのCronとKubernetesのCronJobでの具体的な実装例を見ていきましょう。

—

3. 実装ガイド①:Linux Cronでの実践

まずは、古典的かつ最も広く使われているLinuxのCron環境での実装です。
シェルスクリプトからSentry公式のCLIツール(`sentry-cli`)を使って、ジョブの開始と終了を通知します。

ステップ1: 準備(sentry-cliの導入と認証)

バッチを実行するサーバーに`sentry-cli`をインストールし、プロジェクトの認証を通しておきます。

sentry-cliのインストール(公式推奨スクリプト)
curl -sL https://sentry.io/get-sentry-cli | bash

認証トークンの設定(環境変数として渡すのが安全です)
export SENTRY_AUTH_TOKEN=”あなたのSentry統合用AuthToken”
export SENTRY_ORG=”あなたの組織名”
export SENTRY_PROJECT=”あなたのプロジェクト名”

ステップ2: ラッパーシェルスクリプトの作成

Cronに直接コマンドを書くのではなく、ラッパーとなるシェルスクリプトを作成し、その中でジョブの「開始(`in_progress`)」と「終了(`ok` / `error`)」をハンドリングします。

`run_batch_with_sentry.sh`

!/bin/bash

エラーが発生した時点でスクリプトを即座に終了させる
set -e

MONITOR_SLUG=”nightly-data-sync”

1. 処理の開始をSentryに通知 (in_progress)
CHECK_IN_ID=$(sentry-cli monitors check-in –monitor “$MONITOR_SLUG” –status in_progress –ci)

実際の重いバッチ処理(例: Pythonスクリプトの実行)
万が一ここでエラーが出ると、trapコマンドが発動します
python3 /path/to/my_heavy_batch.py

2. 処理の正常終了をSentryに通知 (ok)
sentry-cli monitors check-in –monitor “$MONITOR_SLUG” –status ok –check-in-id “$CHECK_IN_ID”

ここでポイントなのが、スクリプトが途中で失敗した場合のハンドリング(trap処理)です。以下のように書くことで、バッチがコケた瞬間にもSentryに「エラー終了」を伝えることができます。

!/bin/bash
set -e

MONITOR_SLUG=”nightly-data-sync”
CHECK_IN_ID=$(sentry-cli monitors check-in –monitor “$MONITOR_SLUG” –status in_progress –ci)

失敗時のトラップ設定
trap ‘sentry-cli monitors check-in –monitor “$MONITOR_SLUG” –status error –check-in-id “$CHECK_IN_ID”‘ ERR

バッチ処理実行
python3 /path/to/my_heavy_batch.py

正常終了時
sentry-cli monitors check-in –monitor “$MONITOR_SLUG” –status ok –check-in-id “$CHECK_IN_ID”

ステップ3: Linux Cronへの登録

あとは、このシェルスクリプトをCronに登録するだけです。

毎日深夜2時に実行
0 2 /path/to/run_batch_with_sentry.sh > /dev/null 2>&1

これで、もしバッチがメモリ不足で途中で死んでも、無限ループで固まっても、Sentryが即座に検知してくれます!

—

4. 実装ガイド②:Kubernetes (K8s) CronJobでの実践

現代的なインフラであるKubernetesをお使いですか?ご安心ください、K8sのCronJobともシームレスに連携できます。
K8sの場合は、`sentry-cli`を毎回入れる代わりに、Sentryが提供するHTTP API(Check-in Endpoint)を `curl` で叩くのが最も軽快でスマートです。

以下は、Kubernetesの `CronJob` マニフェストのサンプルです。

`k8s-cronjob.yaml`

apiVersion: batch/v1
kind: CronJob
metadata:
name: kubernetes-cleanup-job
spec:
schedule: “0 3 ” # 毎日深夜3時に実行
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:

  • name: cleanup-task

image: my-cleanup-image:latest
command: [“/bin/sh”, “-c”]
args:

  • |

# 1. 処理開始の通知 (SentryのWebhookエンドポイントへPOST)
# 環境変数からSentryのDsnやSecretを取得します
CHECK_IN_RESPONSE=$(curl -s -X POST \
“https://sentry.io/api/0/organizations/YOUR_ORG/monitors/k8s-cleanup-monitor/checkins/” \
-H “Authorization: Bearer $SENTRY_MONITOR_TOKEN” \
-H “Content-Type: application/json” \
data='{“status”: “in_progress”}’)

# 返却された check_in_id を抽出(簡易的にjq等を使用、または無視してOK)

# 2. メインの処理を実行
if python3 /app/cleanup.py; then
# 3-A. 成功の通知
curl -s -X PUT \
“https://sentry.io/api/0/organizations/YOUR_ORG/monitors/k8s-cleanup-monitor/checkins/” \
-H “Authorization: Bearer $SENTRY_MONITOR_TOKEN” \
-H “Content-Type: application/json” \
-d ‘{“status”: “ok”}’
else
# 3-B. 失敗の通知
curl -s -X PUT \
“https://sentry.io/api/0/organizations/YOUR_ORG/monitors/k8s-cleanup-monitor/checkins/” \
-H “Authorization: Bearer $SENTRY_MONITOR_TOKEN” \
-H “Content-Type: application/json” \
-d ‘{“status”: “error”}’
exit 1
fi
env:

  • name: SENTRY_MONITOR_TOKEN

valueFrom:
secretKeyRef:
name: sentry-secret
key: monitor-token

Kubernetesのポッド自体がクラッシュしたり、ノードが消失してPodが消滅したような場合でも、Sentry側で「設定されたスケジュール(`0 3 `)を過ぎたのに `ok` も `in_progress` も届かない!」と判断し、タイムアウト(Missing)アラートを確実に発報してくれます。

—

5. Sentryダッシュボードでの設定とHelloWorld動作確認

コードの準備ができたら、SentryのWebコンソール側でモニターを有効化しましょう。

1. Sentryのダッシュボードを開き、左メニューの [Crons] をクリックします。
2. 初めてチェックイン(`sentry-cli` または `curl`)を実行すると、ダッシュボード上に自動的に `nightly-data-sync` や `k8s-cleanup-monitor` が認識され、リストに現れます。
3. モニターの設定画面を開き、以下を調整します。

  • Schedule Type: Cron (例: `0 2 `)
  • Timezone: Asia/Tokyo (日本時間にするのを忘れずに!)
  • Max Runtime: バッチが通常何分で終わるか(例: 30分を超えたら異常とみなす)

これで設定は完了です!
手動で一度バッチを実行(あるいはテスト実行)し、Sentryの画面上で「Green(正常完了)」のステータスが綺麗にプロットされるのを確認してください。この瞬間が、オブザーバビリティエンジニアにとって最も快感な瞬間です。

—

まとめ:今夜から「目隠しバッチ」を卒業しよう

今回は、Sentry Cronsを使ったバッチ処理・定期ジョブのハートビート監視について解説しました。

  • プロセスが生きているかではなく、「ジョブが正常に完了したか」を監視する。
  • 開始(`in_progress`)と終了(`ok` / `error`)をシグナルとして送る。
  • 万が一サイレント障害が起きても、Sentryのタイムアウト検知があなたを救ってくれる。

バックグラウンド処理の監視は、後回しにされがちですが、システム全体の信頼性を担保する上ではWebサーバーと同じくらい(あるいはそれ以上に)重要です。
ぜひ今回のコードを参考に、あなたのシステムのバックグラウンドタスクに「心音」を宿してあげてください。毎日の平穏な朝が、あなたを待っていますよ!

タイトルとURLをコピーしました