Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,447 @@
<?php
declare(strict_types=1);
namespace App\Framework\Discovery\Health;
use App\Framework\Discovery\Memory\DiscoveryMemoryManager;
use App\Framework\Discovery\Memory\MemoryStatus;
use App\Framework\Discovery\Storage\DiscoveryCacheManager;
use App\Framework\Discovery\UnifiedDiscoveryService;
use App\Framework\Health\HealthCheckCategory;
use App\Framework\Health\HealthCheckInterface;
use App\Framework\Health\HealthCheckResult;
use App\Framework\Health\HealthStatus;
/**
* Health check for the Discovery system
*
* Monitors discovery cache, memory management, and system performance
* to ensure the discovery system is operating optimally.
*/
final readonly class DiscoveryHealthCheck implements HealthCheckInterface
{
public function __construct(
private ?UnifiedDiscoveryService $discoveryService = null,
private ?DiscoveryCacheManager $cacheManager = null,
private ?DiscoveryMemoryManager $memoryManager = null
) {
}
public function check(): HealthCheckResult
{
$checks = [];
$overallHealth = HealthStatus::HEALTHY;
$details = [];
// Check Discovery Service availability
if ($this->discoveryService !== null) {
$serviceCheck = $this->checkDiscoveryService();
$checks['discovery_service'] = $serviceCheck;
if ($serviceCheck['status'] !== 'healthy') {
$overallHealth = $this->getWorseStatus($overallHealth, $serviceCheck['health_status']);
}
$details = array_merge($details, $serviceCheck['details']);
}
// Check Cache System
if ($this->cacheManager !== null) {
$cacheCheck = $this->checkCacheSystem();
$checks['cache_system'] = $cacheCheck;
if ($cacheCheck['status'] !== 'healthy') {
$overallHealth = $this->getWorseStatus($overallHealth, $cacheCheck['health_status']);
}
$details = array_merge($details, $cacheCheck['details']);
}
// Check Memory Management
if ($this->memoryManager !== null) {
$memoryCheck = $this->checkMemoryManagement();
$checks['memory_management'] = $memoryCheck;
if ($memoryCheck['status'] !== 'healthy') {
$overallHealth = $this->getWorseStatus($overallHealth, $memoryCheck['health_status']);
}
$details = array_merge($details, $memoryCheck['details']);
}
// Overall system check
$systemCheck = $this->checkOverallSystem($checks);
$details = array_merge($details, $systemCheck['details']);
if ($systemCheck['status'] !== 'healthy') {
$overallHealth = $this->getWorseStatus($overallHealth, $systemCheck['health_status']);
}
$message = $this->generateHealthMessage($overallHealth, $checks);
return match ($overallHealth) {
HealthStatus::HEALTHY => HealthCheckResult::healthy($message, $details),
HealthStatus::WARNING => HealthCheckResult::warning($message, $details),
HealthStatus::UNHEALTHY => HealthCheckResult::unhealthy($message, $details)
};
}
/**
* Check Discovery Service health
*/
private function checkDiscoveryService(): array
{
try {
$startTime = microtime(true);
// Test basic discovery functionality
$testResult = $this->discoveryService->test();
$responseTime = (microtime(true) - $startTime) * 1000; // Convert to ms
$status = 'healthy';
$healthStatus = HealthStatus::HEALTHY;
$details = [
'service_available' => true,
'response_time_ms' => round($responseTime, 2),
];
// Check response time
if ($responseTime > 5000) { // 5 seconds
$status = 'unhealthy';
$healthStatus = HealthStatus::UNHEALTHY;
$details['performance_issue'] = 'Response time too high';
} elseif ($responseTime > 2000) { // 2 seconds
$status = 'warning';
$healthStatus = HealthStatus::WARNING;
$details['performance_warning'] = 'Response time elevated';
}
return [
'status' => $status,
'health_status' => $healthStatus,
'details' => $details,
];
} catch (\Throwable $e) {
return [
'status' => 'unhealthy',
'health_status' => HealthStatus::UNHEALTHY,
'details' => [
'service_available' => false,
'error' => $e->getMessage(),
'error_type' => get_class($e),
],
];
}
}
/**
* Check Cache System health
*/
private function checkCacheSystem(): array
{
try {
$healthStatus = $this->cacheManager->getHealthStatus();
$status = 'healthy';
$health = HealthStatus::HEALTHY;
$details = [
'cache_driver' => $healthStatus['cache_driver'],
'memory_aware' => $healthStatus['memory_aware'],
];
// Check memory management if available
if (isset($healthStatus['memory_management'])) {
$memoryInfo = $healthStatus['memory_management'];
$details['memory_status'] = $memoryInfo['status'];
$details['memory_pressure'] = $memoryInfo['memory_pressure'];
$details['cache_level'] = $memoryInfo['cache_level'];
// Evaluate memory status
if ($memoryInfo['status'] === 'critical') {
$status = 'unhealthy';
$health = HealthStatus::UNHEALTHY;
} elseif ($memoryInfo['status'] === 'warning') {
$status = 'warning';
$health = HealthStatus::WARNING;
}
}
// Check cache metrics if available
$cacheMetrics = $this->cacheManager->getCacheMetrics();
if ($cacheMetrics !== null) {
$details['hit_rate'] = $cacheMetrics->hitRate->toPercentage()->toString();
$details['total_size'] = $cacheMetrics->totalSize->toHumanReadable();
$details['compression_ratio'] = $cacheMetrics->compressionRatio->toPercentage()->toString();
// Check performance metrics
$hitRate = $cacheMetrics->hitRate->toString();
if ($hitRate < 0.3) { // Less than 30% hit rate
$status = $this->getWorseStatusString($status, 'warning');
$health = $this->getWorseStatus($health, HealthStatus::WARNING);
$details['cache_performance_warning'] = 'Low cache hit rate';
}
}
return [
'status' => $status,
'health_status' => $health,
'details' => $details,
];
} catch (\Throwable $e) {
return [
'status' => 'unhealthy',
'health_status' => HealthStatus::UNHEALTHY,
'details' => [
'cache_available' => false,
'error' => $e->getMessage(),
],
];
}
}
/**
* Check Memory Management health
*/
private function checkMemoryManagement(): array
{
try {
$memoryStatus = $this->memoryManager->getMemoryStatus('health_check');
$status = 'healthy';
$health = HealthStatus::HEALTHY;
$details = [
'current_usage' => $memoryStatus->currentUsage->toHumanReadable(),
'memory_pressure' => $memoryStatus->memoryPressure->toString(),
'status' => $memoryStatus->status->value,
];
// Evaluate memory status
switch ($memoryStatus->status) {
case MemoryStatus::CRITICAL:
$status = 'unhealthy';
$health = HealthStatus::UNHEALTHY;
$details['critical_issue'] = 'Memory usage is critical';
break;
case MemoryStatus::WARNING:
$status = 'warning';
$health = HealthStatus::WARNING;
$details['warning'] = 'Memory usage is elevated';
break;
case MemoryStatus::NORMAL:
// Check if we're close to warning threshold
if ($memoryStatus->memoryPressure->toDecimal() > 0.7) {
$status = 'warning';
$health = HealthStatus::WARNING;
$details['approaching_limit'] = 'Memory usage approaching threshold';
}
break;
}
// Add memory statistics
if (method_exists($this->memoryManager, 'getStatistics')) {
$stats = $this->memoryManager->getStatistics();
$details['cleanup_count'] = $stats['cleanup_operations_count'] ?? 0;
$details['memory_freed'] = isset($stats['total_memory_freed'])
? $stats['total_memory_freed']->toHumanReadable()
: '0 B';
}
return [
'status' => $status,
'health_status' => $health,
'details' => $details,
];
} catch (\Throwable $e) {
return [
'status' => 'unhealthy',
'health_status' => HealthStatus::UNHEALTHY,
'details' => [
'memory_manager_available' => false,
'error' => $e->getMessage(),
],
];
}
}
/**
* Check overall system health
*/
private function checkOverallSystem(array $checks): array
{
$details = [];
$status = 'healthy';
$health = HealthStatus::HEALTHY;
// Count health status distribution
$healthyCounts = 0;
$warningCounts = 0;
$unhealthyCounts = 0;
foreach ($checks as $check) {
switch ($check['status']) {
case 'healthy':
$healthyCounts++;
break;
case 'warning':
$warningCounts++;
break;
case 'unhealthy':
$unhealthyCounts++;
break;
}
}
$totalChecks = count($checks);
if ($totalChecks === 0) {
$status = 'warning';
$health = HealthStatus::WARNING;
$details['no_components'] = 'No discovery components available for health check';
} else {
// Determine overall status based on component health
if ($unhealthyCounts > 0) {
$status = 'unhealthy';
$health = HealthStatus::UNHEALTHY;
$details['unhealthy_components'] = $unhealthyCounts;
} elseif ($warningCounts > 0) {
$status = 'warning';
$health = HealthStatus::WARNING;
$details['warning_components'] = $warningCounts;
}
$details['health_summary'] = [
'total_components' => $totalChecks,
'healthy' => $healthyCounts,
'warning' => $warningCounts,
'unhealthy' => $unhealthyCounts,
];
}
// Add system recommendations
$recommendations = $this->generateRecommendations($checks);
if (! empty($recommendations)) {
$details['recommendations'] = $recommendations;
}
return [
'status' => $status,
'health_status' => $health,
'details' => $details,
];
}
/**
* Generate health message
*/
private function generateHealthMessage(HealthStatus $overallHealth, array $checks): string
{
$componentCount = count($checks);
$healthyCount = 0;
foreach ($checks as $check) {
if ($check['status'] === 'healthy') {
$healthyCount++;
}
}
return match ($overallHealth) {
HealthStatus::HEALTHY => "Discovery system is healthy ({$healthyCount}/{$componentCount} components optimal)",
HealthStatus::WARNING => "Discovery system has warnings ({$healthyCount}/{$componentCount} components optimal)",
HealthStatus::UNHEALTHY => "Discovery system is unhealthy ({$healthyCount}/{$componentCount} components optimal)"
};
}
/**
* Generate recommendations based on check results
*/
private function generateRecommendations(array $checks): array
{
$recommendations = [];
foreach ($checks as $checkName => $check) {
if ($check['status'] === 'unhealthy' || $check['status'] === 'warning') {
switch ($checkName) {
case 'discovery_service':
if (isset($check['details']['performance_issue'])) {
$recommendations[] = 'Consider optimizing discovery algorithms or enabling parallel processing';
}
if (isset($check['details']['service_available']) && ! $check['details']['service_available']) {
$recommendations[] = 'Discovery service is unavailable - check configuration and dependencies';
}
break;
case 'cache_system':
if (isset($check['details']['cache_performance_warning'])) {
$recommendations[] = 'Improve cache hit rate by reviewing cache strategy and warming critical data';
}
if (isset($check['details']['memory_status']) && $check['details']['memory_status'] === 'critical') {
$recommendations[] = 'Enable memory pressure management and increase cleanup frequency';
}
break;
case 'memory_management':
if (isset($check['details']['critical_issue'])) {
$recommendations[] = 'Immediate action required: reduce memory usage or increase system limits';
}
if (isset($check['details']['approaching_limit'])) {
$recommendations[] = 'Monitor memory usage closely and consider optimization strategies';
}
break;
}
}
}
return array_unique($recommendations);
}
/**
* Get worse health status
*/
private function getWorseStatus(HealthStatus $current, HealthStatus $new): HealthStatus
{
if ($new->getPriority() < $current->getPriority()) {
return $new;
}
return $current;
}
/**
* Get worse status string
*/
private function getWorseStatusString(string $current, string $new): string
{
$priority = [
'healthy' => 3,
'warning' => 2,
'unhealthy' => 1,
];
return $priority[$new] < $priority[$current] ? $new : $current;
}
public function getName(): string
{
return 'Discovery System Health';
}
public function getCategory(): HealthCheckCategory
{
return HealthCheckCategory::DISCOVERY;
}
public function getTimeout(): int
{
return 10000; // 10 seconds timeout
}
}