2026年6月28日
2026年6月28日
WordPressのヘルスチェックAPIで死活監視を実装する方法
はじめに
WordPressサイトの死活監視は「サイトが表示されるかどうか」だけでは不十分です。データベース接続・外部API・ファイルシステムの書き込み権限など、複数のコンポーネントを個別に検査するヘルスチェックAPIを実装することで、障害の根本原因を素早く特定できます。本記事では、WordPress REST APIにカスタムエンドポイントを追加し、Uptime Robot + Slack通知で完全な監視体制を構築する方法を解説します。
症状・原因
- サイトは表示されるがDBエラーが断続的に発生している
- ファイルアップロードが失敗するが原因がわからない
- 外部APIの応答遅延がWordPressの動作に影響しているか不明
- メール送信機能が停止しているが気づくのが遅れる
- 監視ツールが単純なHTTP 200応答チェックしかしていない
解決手順
ステップ1:カスタムヘルスチェックエンドポイントの作成
REST APIにヘルスチェックエンドポイントを登録します。
<?php
// mu-plugins/health-check-api.php
/**
* WordPress カスタムヘルスチェックAPI
* エンドポイント: /wp-json/wpdr/v1/health
*/
add_action( 'rest_api_init', function () {
register_rest_route( 'wpdr/v1', '/health', [
'methods' => 'GET',
'callback' => 'wpdr_health_check_handler',
'permission_callback' => 'wpdr_health_check_permission',
'args' => [
'token' => [
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
'description' => '認証トークン',
],
],
] );
} );
/**
* 認証チェック(トークンベース)
*/
function wpdr_health_check_permission( WP_REST_Request $request ): bool {
$token = $request->get_param( 'token' );
$expected_token = defined( 'WP_HEALTH_TOKEN' ) ? WP_HEALTH_TOKEN : '';
return hash_equals( $expected_token, $token );
}
/**
* ヘルスチェックの実行と結果返却
*/
function wpdr_health_check_handler( WP_REST_Request $request ): WP_REST_Response {
$checks = [];
$status = 'healthy';
// 1. データベース接続チェック
global $wpdb;
$db_result = $wpdb->get_var( 'SELECT 1' );
$checks['database'] = [
'status' => ( '1' === (string) $db_result ) ? 'ok' : 'error',
'message' => ( '1' === (string) $db_result ) ? 'Connected' : $wpdb->last_error,
];
// 2. ファイルシステム書き込みチェック
$upload_dir = wp_upload_dir();
$test_file = $upload_dir['basedir'] . '/.health-check-test';
$fs_writeable = file_put_contents( $test_file, 'test' ) !== false;
if ( $fs_writeable ) {
unlink( $test_file );
}
$checks['filesystem'] = [
'status' => $fs_writeable ? 'ok' : 'error',
'message' => $fs_writeable ? 'Writable' : 'Upload directory not writable',
];
// 3. Redisキャッシュチェック(wp-redis使用時)
if ( class_exists( 'WP_Object_Cache' ) && method_exists( $GLOBALS['wp_object_cache'], 'redis_instance' ) ) {
try {
$redis = $GLOBALS['wp_object_cache']->redis_instance();
$pong = $redis->ping();
$checks['redis'] = [
'status' => ( 'PONG' === $pong || true === $pong ) ? 'ok' : 'error',
'message' => 'Redis: ' . ( is_string( $pong ) ? $pong : ( $pong ? 'PONG' : 'No response' ) ),
];
} catch ( Exception $e ) {
$checks['redis'] = [ 'status' => 'error', 'message' => $e->getMessage() ];
}
}
// いずれかにエラーがあれば全体ステータスをerrorに
foreach ( $checks as $check ) {
if ( 'error' === $check['status'] ) {
$status = 'unhealthy';
break;
}
}
$response = new WP_REST_Response( [
'status' => $status,
'timestamp' => current_time( 'c' ),
'site_url' => get_site_url(),
'checks' => $checks,
'wp_version'=> get_bloginfo( 'version' ),
], 'healthy' === $status ? 200 : 503 );
return $response;
}
ステップ2:wp_schedule_eventによる自動セルフチェック
WordPressのCronを使って定期的に内部チェックを実行します。
<?php
// mu-plugins/health-check-cron.php
/**
* 5分ごとにセルフヘルスチェックを実行
*/
add_filter( 'cron_schedules', function ( array $schedules ): array {
$schedules['every_five_minutes'] = [
'interval' => 300,
'display' => __( '5分ごと' ),
];
return $schedules;
} );
add_action( 'wpdr_self_health_check', 'wpdr_run_self_health_check' );
function wpdr_run_self_health_check(): void {
// ヘルスチェックAPIを内部から呼び出す
$token = defined( 'WP_HEALTH_TOKEN' ) ? WP_HEALTH_TOKEN : '';
$url = get_rest_url( null, 'wpdr/v1/health' );
$response = wp_remote_get( add_query_arg( 'token', $token, $url ), [
'timeout' => 10,
'sslverify' => true,
] );
if ( is_wp_error( $response ) ) {
wpdr_send_health_alert( 'セルフチェック失敗: ' . $response->get_error_message() );
return;
}
$code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( 200 !== (int) $code ) {
$failed_checks = array_filter( $body['checks'] ?? [], fn($c) => 'error' === $c['status'] );
$details = implode(', ', array_keys( $failed_checks ) );
wpdr_send_health_alert( "ヘルスチェック失敗 (HTTP {$code}): {$details}" );
} else {
// 回復通知(前回エラーだった場合のみ)
if ( get_transient( 'wpdr_last_health_error' ) ) {
wpdr_send_health_alert( '✅ サイトが回復しました', 'recovery' );
delete_transient( 'wpdr_last_health_error' );
}
}
}
// スケジュール登録
if ( ! wp_next_scheduled( 'wpdr_self_health_check' ) ) {
wp_schedule_event( time(), 'every_five_minutes', 'wpdr_self_health_check' );
}
ステップ3:Slack通知の実装
障害検知時にSlackへリアルタイム通知を送ります。
<?php
// mu-plugins/health-check-notifications.php
/**
* Slack Webhook でヘルスチェックアラートを送信
*/
function wpdr_send_health_alert( string $message, string $type = 'error' ): void {
$webhook_url = defined( 'WP_SLACK_WEBHOOK_URL' ) ? WP_SLACK_WEBHOOK_URL : '';
if ( empty( $webhook_url ) ) {
// フォールバック: メール通知
wp_mail(
get_option( 'admin_email' ),
'[WordPress ヘルスチェック] ' . ( 'recovery' === $type ? '回復' : '異常検知' ),
$message . "\n\nサイト: " . get_site_url() . "\n時刻: " . current_time( 'mysql' )
);
return;
}
$color = 'recovery' === $type ? '#00a32a' : '#d63638';
$emoji = 'recovery' === $type ? ':white_check_mark:' : ':rotating_light:';
$title = 'recovery' === $type ? 'WordPress サイト回復' : 'WordPress 障害検知';
$payload = [
'username' => 'WordPress Health Monitor',
'icon_emoji' => $emoji,
'attachments' => [[
'color' => $color,
'title' => $title,
'text' => $message,
'fields' => [
[ 'title' => 'サイトURL', 'value' => get_site_url(), 'short' => true ],
[ 'title' => '検知時刻', 'value' => current_time( 'mysql' ), 'short' => true ],
],
'footer' => 'WP Health Check API',
'ts' => time(),
]],
];
wp_remote_post( $webhook_url, [
'body' => wp_json_encode( $payload ),
'headers' => [ 'Content-Type' => 'application/json' ],
'timeout' => 5,
] );
if ( 'error' === $type ) {
set_transient( 'wpdr_last_health_error', $message, HOUR_IN_SECONDS );
}
}
ステップ4:wp-config.phpでの設定
ヘルスチェックに必要なトークンとWebhook URLを設定します。
<?php
// wp-config.php に追加
// ヘルスチェックAPIの認証トークン(ランダムな文字列を生成して設定)
define( 'WP_HEALTH_TOKEN', 'your-super-secret-health-token-here' );
// Slack Webhook URL(Slack App設定から取得)
define( 'WP_SLACK_WEBHOOK_URL', 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX' );
// ヘルスチェックエンドポイントURL:
// https://example.com/wp-json/wpdr/v1/health?token=your-super-secret-health-token-here
ステップ5:Uptime Robotでの外部監視設定
Uptime Robotでエンドポイントを定期的に監視します。
# Uptime Robot API でモニター作成(curlコマンド)
curl -X POST "https://api.uptimerobot.com/v2/newMonitor" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "api_key=YOUR_UPTIMEROBOT_API_KEY" \
-d "friendly_name=WordPress Health Check" \
-d "url=https://example.com/wp-json/wpdr/v1/health?token=your-token" \
-d "type=1" \
-d "interval=300" \
-d "http_method=1" \
-d "keyword_type=1" \
-d "keyword_value=healthy" \
-d "alert_contacts=YOUR_ALERT_CONTACT_ID"
# レスポンスに "healthy" が含まれているかキーワード監視
# 含まれていない場合(503など)にアラートを発火
# 監視結果の確認
curl -X POST "https://api.uptimerobot.com/v2/getMonitors" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "api_key=YOUR_UPTIMEROBOT_API_KEY" \
-d "format=json" | jq '.monitors[].status'
# 2=up, 8=down, 9=appears down
注意事項
- ヘルスチェックエンドポイントのURLとトークンは外部に公開しないこと。Uptime RobotやPingdomに設定する際はHTTPS必須
WP_HEALTH_TOKENは必ず32文字以上のランダムな文字列を使用する。wp_generate_password(32)やopenssl rand -hex 32で生成すること- WP Cronは本番環境では
define('DISABLE_WP_CRON', true)にしてシステムCronで代替することを推奨する。リクエスト依存のWP Cronは高負荷時に実行されない - ヘルスチェックAPIを実行するとDB接続が発生する。外部からの連続アクセス(1分以下のインターバル)は避け、Uptime Robotの最短300秒インターバルを推奨する
- Redis/Memcachedのチェックはオプション扱いとし、キャッシュ障害時でも503ではなくwarningステータスを返す設計にすることでフォールスアラートを減らせる
まとめ
カスタムヘルスチェックAPIと外部監視ツールを組み合わせることで、WordPressの障害を多角的かつ迅速に検知できます。検知した問題への対応手順は「WordPressへの突然のトラフィックスパイクを対処する方法」を、パフォーマンスの継続監視には「New Relic APMでWordPressのパフォーマンスを監視する方法」を参照してください。