- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
202 lines
6.8 KiB
PHP
202 lines
6.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Console\Health\Commands;
|
|
|
|
use App\Framework\Console\Attributes\ConsoleCommand;
|
|
use App\Framework\Console\ExitCode;
|
|
use App\Framework\Console\Health\HealthService;
|
|
use App\Framework\Console\Health\HealthStatus;
|
|
use App\Framework\Console\Input\ConsoleInput;
|
|
use App\Framework\Console\Layout\ResponsiveOutput;
|
|
use App\Framework\Console\Output\ConsoleOutput;
|
|
|
|
final readonly class HealthCheckCommand
|
|
{
|
|
public function __construct(
|
|
private HealthService $healthService
|
|
) {
|
|
}
|
|
|
|
#[ConsoleCommand(
|
|
name: 'health:check',
|
|
description: 'Run console system health checks'
|
|
)]
|
|
public function checkHealth(ConsoleInput $input, ConsoleOutput $output): ExitCode
|
|
{
|
|
$checkName = $input->getArgument('check');
|
|
$requiredOnly = $input->hasOption('required');
|
|
$verbose = $input->hasOption('verbose');
|
|
$json = $input->hasOption('json');
|
|
|
|
if ($checkName) {
|
|
return $this->runSingleCheck($checkName, $output, $verbose, $json);
|
|
}
|
|
|
|
if ($requiredOnly) {
|
|
return $this->runRequiredChecks($output, $verbose, $json);
|
|
}
|
|
|
|
return $this->runAllChecks($output, $verbose, $json);
|
|
}
|
|
|
|
#[ConsoleCommand(
|
|
name: 'health:list',
|
|
description: 'List available health checks'
|
|
)]
|
|
public function listChecks(ConsoleInput $input, ConsoleOutput $output): ExitCode
|
|
{
|
|
$checks = $this->healthService->getAvailableChecks();
|
|
$responsiveOutput = ResponsiveOutput::create($output);
|
|
|
|
$output->writeLine("<yellow>Available Health Checks:</yellow>\n");
|
|
|
|
// Prepare table data
|
|
$headers = ['Name', 'Required', 'Description'];
|
|
$rows = [];
|
|
|
|
foreach ($checks as $check) {
|
|
$rows[] = [
|
|
$check['name'],
|
|
$check['required'] ? 'Yes' : 'No',
|
|
$check['description'],
|
|
];
|
|
}
|
|
|
|
$responsiveOutput->writeTable($headers, $rows);
|
|
|
|
$output->writeLine('');
|
|
$responsiveOutput->writeList([
|
|
'health:check' => 'Run all checks',
|
|
'health:check --required' => 'Run only required checks',
|
|
'health:check "Check Name"' => 'Run specific check',
|
|
'health:check --json' => 'Output as JSON',
|
|
], 'Usage:');
|
|
|
|
return ExitCode::SUCCESS;
|
|
}
|
|
|
|
private function runSingleCheck(string $checkName, ConsoleOutput $output, bool $verbose, bool $json): ExitCode
|
|
{
|
|
$result = $this->healthService->runCheck($checkName);
|
|
|
|
if ($result === null) {
|
|
$output->writeLine("<red>Health check '{$checkName}' not found.</red>");
|
|
|
|
return ExitCode::NOT_FOUND;
|
|
}
|
|
|
|
if ($json) {
|
|
$output->writeLine(json_encode($result->toArray(), JSON_PRETTY_PRINT));
|
|
|
|
return ExitCode::SUCCESS;
|
|
}
|
|
|
|
$this->displaySingleResult($checkName, $result, $output, $verbose);
|
|
|
|
return $result->isUnhealthy() ? ExitCode::GENERAL_ERROR : ExitCode::SUCCESS;
|
|
}
|
|
|
|
private function runRequiredChecks(ConsoleOutput $output, bool $verbose, bool $json): ExitCode
|
|
{
|
|
$report = $this->healthService->runRequiredChecks();
|
|
|
|
if ($json) {
|
|
$output->writeLine(json_encode($report->toArray(), JSON_PRETTY_PRINT));
|
|
|
|
return ExitCode::SUCCESS;
|
|
}
|
|
|
|
$this->displayReport($report, $output, $verbose, 'Required Health Checks');
|
|
|
|
return $report->isUnhealthy() ? ExitCode::GENERAL_ERROR : ExitCode::SUCCESS;
|
|
}
|
|
|
|
private function runAllChecks(ConsoleOutput $output, bool $verbose, bool $json): ExitCode
|
|
{
|
|
$report = $this->healthService->runAllChecks();
|
|
|
|
if ($json) {
|
|
$output->writeLine(json_encode($report->toArray(), JSON_PRETTY_PRINT));
|
|
|
|
return ExitCode::SUCCESS;
|
|
}
|
|
|
|
$this->displayReport($report, $output, $verbose, 'Console System Health Check');
|
|
|
|
return $report->isUnhealthy() ? ExitCode::GENERAL_ERROR : ExitCode::SUCCESS;
|
|
}
|
|
|
|
private function displayReport($report, ConsoleOutput $output, bool $verbose, string $title): void
|
|
{
|
|
$statusColor = $report->overallStatus->getColor();
|
|
$statusSymbol = $report->overallStatus->getSymbol();
|
|
|
|
$output->writeLine("<{$statusColor}>{$title}</>");
|
|
$output->writeLine("<{$statusColor}>{$statusSymbol} Overall Status: {$report->overallStatus->value}</>");
|
|
$output->writeLine('');
|
|
|
|
$output->writeLine("Summary:");
|
|
$output->writeLine(" Total Checks: {$report->getCheckCount()}");
|
|
$output->writeLine(" <green>Healthy: {$report->getHealthyCount()}</green>");
|
|
$output->writeLine(" <yellow>Warnings: {$report->getWarningCount()}</yellow>");
|
|
$output->writeLine(" <red>Unhealthy: {$report->getUnhealthyCount()}</red>");
|
|
$output->writeLine('');
|
|
|
|
// Show unhealthy checks first
|
|
$unhealthyChecks = $report->getUnhealthyChecks();
|
|
if (! empty($unhealthyChecks)) {
|
|
$output->writeLine('<red>Failed Checks:</red>');
|
|
foreach ($unhealthyChecks as $name => $result) {
|
|
$this->displaySingleResult($name, $result, $output, $verbose);
|
|
}
|
|
$output->writeLine('');
|
|
}
|
|
|
|
// Show warning checks
|
|
$warningChecks = $report->getWarningChecks();
|
|
if (! empty($warningChecks)) {
|
|
$output->writeLine('<yellow>Warning Checks:</yellow>');
|
|
foreach ($warningChecks as $name => $result) {
|
|
$this->displaySingleResult($name, $result, $output, $verbose);
|
|
}
|
|
$output->writeLine('');
|
|
}
|
|
|
|
// Show healthy checks only in verbose mode
|
|
if ($verbose) {
|
|
$healthyChecks = $report->getHealthyChecks();
|
|
if (! empty($healthyChecks)) {
|
|
$output->writeLine('<green>Healthy Checks:</green>');
|
|
foreach ($healthyChecks as $name => $result) {
|
|
$this->displaySingleResult($name, $result, $output, $verbose);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function displaySingleResult(string $name, $result, ConsoleOutput $output, bool $verbose): void
|
|
{
|
|
$color = $result->status->getColor();
|
|
$symbol = $result->status->getSymbol();
|
|
|
|
$output->writeLine("<{$color}>{$symbol} {$name}: {$result->message}</>");
|
|
|
|
if ($verbose && ! empty($result->details)) {
|
|
foreach ($result->details as $key => $value) {
|
|
$displayValue = is_array($value) ? implode(', ', $value) : $value;
|
|
$output->writeLine(" {$key}: {$displayValue}");
|
|
}
|
|
}
|
|
|
|
if ($result->recommendation) {
|
|
$output->writeLine(" 💡 Recommendation: {$result->recommendation}");
|
|
}
|
|
|
|
if ($verbose || $result->status !== HealthStatus::HEALTHY) {
|
|
$output->writeLine('');
|
|
}
|
|
}
|
|
}
|