Skip to content

Health Checks

The health check system provides endpoints to monitor the application's health and readiness status.

Overview

The health check infrastructure consists of:

  • Health check controller with multiple endpoints
  • Individual service health checks (database, Notion API, etc.)
  • Aggregated health status reporting
  • Response time tracking

Architecture

Components

  1. HealthController: Exposes health check endpoints
  2. HealthCheckService: Aggregates health checks from multiple services
  3. Individual Health Checks: Check specific services (DatabaseHealthCheck, NotionHealthCheck)
  4. DTOs: Structured response objects for health data

Health Check Flow

Request → HealthController → HealthCheckService → Individual Checks → Response

Endpoints

GET /api/health

Returns the overall health status of the application and all its services.

Response:

json
{
  "status": "healthy",
  "timestamp": "2024-01-01T00:00:00+00:00",
  "version": "1.0.0",
  "services": [
    {
      "name": "database",
      "status": "healthy",
      "message": "Database connection is working",
      "details": {
        "driver": "pdo_mysql",
        "database": "yappa_db"
      },
      "response_time": 12.34
    },
    {
      "name": "notion",
      "status": "healthy",
      "message": "Notion API is accessible",
      "response_time": 234.56
    }
  ]
}

Status Codes:

  • 200 OK: System is healthy or degraded
  • 503 Service Unavailable: System is unhealthy

GET /api/health/live

Liveness probe - confirms the application is running.

Response:

json
{
  "status": "alive",
  "timestamp": "2024-01-01T00:00:00+00:00"
}

Status Codes:

  • 200 OK: Application is running

GET /api/health/ready

Readiness probe - confirms the application is ready to serve traffic.

Response:

json
{
  "status": "ready",
  "timestamp": "2024-01-01T00:00:00+00:00",
  "services": [...]
}

Status Codes:

  • 200 OK: Application is ready
  • 503 Service Unavailable: Application is not ready

GET /api/health/metrics

Returns system and application metrics.

Response:

json
{
  "system": {
    "memory": {
      "usage": 12345678,
      "peak": 23456789,
      "limit": "256M"
    },
    "php": {
      "version": "8.2.0",
      "sapi": "cli"
    },
    "server": {
      "load": {
        "1min": 0.5,
        "5min": 0.3,
        "15min": 0.2
      },
      "uptime": 86400
    }
  },
  "application": [],
  "timestamp": "2024-01-01T00:00:00+00:00"
}

Health Status Values

  • healthy: Service is operating normally
  • degraded: Service is operational but with reduced performance
  • unhealthy: Service is not operational

Adding New Health Checks

To add a new health check:

  1. Create a new health check class in src/Service/Health/
  2. Implement a check() method that returns ServiceHealthResponse
  3. Register the service in config/services.yaml with the app.health_check tag
  4. The health check will be automatically included in the aggregated health status

Example:

php
<?php

namespace App\Service\Health;

use App\DTO\Response\Health\ServiceHealthResponse;

class RedisHealthCheck
{
    public function __construct(
        private readonly RedisClient $redis,
        private readonly LoggerInterface $logger
    ) {
    }

    public function check(): ServiceHealthResponse
    {
        $startTime = microtime(true);

        try {
            $this->redis->ping();
            $responseTime = (microtime(true) - $startTime) * 1000;

            return new ServiceHealthResponse(
                name: 'redis',
                status: 'healthy',
                message: 'Redis is accessible',
                responseTime: round($responseTime, 2)
            );
        } catch (\Exception $e) {
            return new ServiceHealthResponse(
                name: 'redis',
                status: 'unhealthy',
                message: 'Redis connection failed: ' . $e->getMessage(),
                responseTime: round((microtime(true) - $startTime) * 1000, 2)
            );
        }
    }
}

Kubernetes Integration

The health check endpoints are designed to work with Kubernetes probes:

yaml
livenessProbe:
  httpGet:
    path: /api/health/live
    port: 8000
  initialDelaySeconds: 10
  periodSeconds: 30

readinessProbe:
  httpGet:
    path: /api/health/ready
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 10

Testing

Health checks are tested at multiple levels:

  • Unit Tests: Test individual health check logic
  • Integration Tests: Test health check endpoints with real services

Run health check tests:

bash
php bin/phpunit tests/Unit/Service/Health/
php bin/phpunit tests/Integration/Health/