Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Health Bundle Laravel Package

cushon/health-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require cushon/health-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        Cushon\HealthBundle\CushonHealthBundle::class => ['all' => true],
    ];
    
  2. First Health Check: Create a custom health check class (e.g., src/Health/DatabaseHealthCheck.php):

    namespace App\Health;
    
    use Cushon\HealthBundle\Health\HealthCheckInterface;
    use Cushon\HealthBundle\Health\Result\HealthResult;
    use Doctrine\DBAL\Connection;
    
    class DatabaseHealthCheck implements HealthCheckInterface
    {
        public function __construct(private Connection $connection) {}
    
        public function check(): HealthResult
        {
            return $this->connection->getSchemaManager()->listTableNames()
                ? HealthResult::healthy()
                : HealthResult::unhealthy('Database connection failed');
        }
    }
    
  3. Register the Check: Configure in config/packages/cushon_health.yaml:

    cushon_health:
        checks:
            - App\Health\DatabaseHealthCheck
    
  4. Trigger Health Endpoint: Access /health (default route) or /health/{check_name} (e.g., /health/database).


First Use Case: Microservice Health Dashboard

  • Use the bundle to expose a /health endpoint for monitoring tools (e.g., Prometheus, Kubernetes liveness probes).
  • Combine with Symfony’s HttpClient to poll dependent services (e.g., databases, APIs) and aggregate results.

Implementation Patterns

1. Check Registration

  • Dynamic Registration: Use dependency injection to inject checks dynamically (e.g., via compiler passes or service tags).
    # config/services.yaml
    tags:
        cushon_health.check:
            - { service: App\Health\DatabaseHealthCheck }
    
  • Priority-Based Execution: Order checks by priority (e.g., critical checks first) via check_priority in config:
    cushon_health:
        checks:
            - { id: database, service: App\Health\DatabaseHealthCheck, priority: 100 }
    

2. Result Aggregation

  • Custom Aggregators: Extend Cushon\HealthBundle\Health\Result\HealthResultAggregator to implement custom logic (e.g., weighted voting).
    class CustomAggregator implements HealthResultAggregator
    {
        public function aggregate(array $results): HealthResult
        {
            $healthy = array_filter($results, fn($r) => $r->isHealthy());
            return count($healthy) >= 2 ? HealthResult::healthy() : HealthResult::unhealthy();
        }
    }
    
    Register in config:
    cushon_health:
        aggregator: App\Health\CustomAggregator
    

3. Integration with Laravel (Symfony Bridge)

  • Symfony HTTP Client: Use symfony/http-client to call the health endpoint from Laravel:
    $client = new Client();
    $response = $client->request('GET', 'http://symfony-app/health');
    $status = json_decode($response->getContent(), true)['status'];
    
  • Shared Checks: Reuse checks across Laravel/Symfony by abstracting logic into a shared library (e.g., App\Shared\Health\CheckInterface).

4. Testing

  • Mock Checks: Test health checks in isolation:
    $check = new DatabaseHealthCheck($mockConnection);
    $result = $check->check();
    $this->assertTrue($result->isHealthy());
    
  • Endpoint Testing: Use Laravel’s Http::fake() or Symfony’s WebTestCase to test /health routes.

5. Advanced: Check Dependencies

  • Chained Checks: Make a check depend on another (e.g., CacheHealthCheck depends on DatabaseHealthCheck):
    class CacheHealthCheck implements HealthCheckInterface
    {
        public function __construct(private HealthCheckInterface $databaseCheck) {}
    
        public function check(): HealthResult
        {
            if (!$this->databaseCheck->check()->isHealthy()) {
                return HealthResult::unhealthy('Database dependency failed');
            }
            // ... cache-specific logic
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies:

    • Avoid circular dependencies between checks (e.g., CheckA depends on CheckB, which depends on CheckA). Use priority ordering or refactor.
  2. Performance Overhead:

    • Heavy checks (e.g., full database queries) can slow down /health responses. Optimize with lightweight probes (e.g., ping queries).
  3. Configuration Overrides:

    • Bundle config in config/packages/cushon_health.yaml can be overridden by environment-specific configs (e.g., config/packages/dev/cushon_health.yaml). Ensure critical checks are not disabled accidentally.
  4. Symfony-Specific Quirks:

    • Event Dispatcher: If using Symfony events (e.g., kernel.request), ensure health checks don’t trigger side effects (e.g., logging, notifications) during probes.
  5. Laravel-Symfony Integration:

    • Session/State: Avoid checks that rely on Symfony’s session or request state (e.g., auth) unless explicitly designed for stateless health probes.

Debugging

  1. Check Execution Order:

    • Use check_priority to debug why a check is skipped or runs out of order. Higher priority = earlier execution.
  2. Result Inspection:

    • Dump results in a check to verify logic:
      public function check(): HealthResult
      {
          $result = HealthResult::unhealthy('Debug: ' . $this->connection->getWarnings());
          return $result;
      }
      
  3. Endpoint Debugging:

    • Enable Symfony’s profiler (APP_DEBUG=1) to inspect the /_profiler endpoint for check execution details.

Tips

  1. Idempotent Checks:

    • Design checks to be idempotent (same result on repeated calls) to avoid flaky probes in monitoring tools.
  2. Custom HTTP Status Codes:

    • Extend the HealthResult to include custom HTTP status codes (e.g., 503 for maintenance mode):
      return HealthResult::unhealthy('Maintenance', 503);
      
  3. Environment-Specific Checks:

    • Disable non-critical checks in production:
      cushon_health:
          checks:
              - { id: logs, service: App\Health\LogHealthCheck, enabled: '%kernel.environment% != "prod"' }
      
  4. Prometheus Metrics:

    • Expose check durations/metrics via Symfony’s sensio_framework_extra or symfony/monolog-bundle:
      $start = microtime(true);
      $result = $this->databaseCheck->check();
      $duration = microtime(true) - $start;
      // Log $duration for Prometheus scraping
      
  5. Documentation:

    • Add a README.md in your project’s docs/health folder to document:
      • List of checks and their purpose.
      • Expected response formats (e.g., JSON schema for /health).
      • SLA requirements (e.g., "Database check must respond in <100ms").
  6. Security:

    • Restrict access to /health in production:
      # config/routes.yaml
      health:
          path: /health
          controller: Cushon\HealthBundle\Controller\HealthController::checkAction
          methods: [GET]
          requirements:
              _ip: 192.168.1.0/24  # Allow only internal IPs
      
  7. Laravel-Specific Workarounds:

    • Service Container: If using Laravel’s container, bind Symfony services explicitly:
      $this->app->bind(
          Cushon\HealthBundle\Health\HealthCheckerInterface::class,
          fn($app) => new HealthChecker($app->make('cushon_health.checker'))
      );
      
    • Route Prefix: Prefix Symfony routes in Laravel to avoid conflicts:
      # config/routes.yaml
      _symfony_health:
          resource: "@CushonHealthBundle/Resources/config/routing.yaml"
          prefix: /_symfony
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky