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のパフォーマンスを監視する方法」を参照してください。

お気軽にご相談ください

お見積りへ お問い合わせへ