200, 'warning' => 200, 'critical' => 503, default => 200 }; return Response::success($health, 'Health check completed', $httpCode); } #[GetRoute('/health/{component}')] public function healthComponent(string $component): array { try { $health = MonitorService::checkIndividualHealth($component); $httpCode = match ($health['status']) { 'healthy' => 200, 'warning' => 200, 'critical' => 503, default => 200 }; return Response::success($health, "Health check for {$component} completed", $httpCode); } catch (\InvalidArgumentException $e) { return Response::error(404, "Health check '{$component}' not found"); } } #[GetRoute('/health/checks')] public function healthChecks(): array { $checks = MonitorService::getAvailableHealthChecks(); return Response::success($checks); } #[GetRoute('/metrics')] public function metrics(Request $request): array { $format = $request->get('format', 'json'); if ($format === 'prometheus') { header('Content-Type: text/plain; version=0.0.4'); echo MonitorService::exportMetrics('prometheus'); exit; } $metrics = MonitorService::getMetricsSummary(); return Response::success($metrics); } #[GetRoute('/alerts')] public function alerts(): array { $alerts = MonitorService::getAlerts(); return Response::success($alerts); } #[GetRoute('/alerts/active')] public function activeAlerts(): array { $alerts = MonitorService::getActiveAlerts(); return Response::success($alerts); } #[PostRoute('/alerts/{alertId}/acknowledge')] public function acknowledgeAlert(string $alertId, Request $request): array { $data = $request->all(); $acknowledgedBy = $data['acknowledged_by'] ?? 'system'; $success = MonitorService::acknowledgeAlert($alertId, $acknowledgedBy); if ($success) { return Response::success(null, 'Alert acknowledged'); } else { return Response::error(404, 'Alert not found or already acknowledged'); } } #[PostRoute('/alerts/{alertId}/resolve')] public function resolveAlert(string $alertId): array { $success = MonitorService::resolveAlert($alertId); if ($success) { return Response::success(null, 'Alert resolved'); } else { return Response::error(404, 'Alert not found'); } } #[GetRoute('/errors')] public function errors(Request $request): array { $filters = []; if ($type = $request->get('type')) { $filters['type'] = $type; } if ($severity = $request->get('severity')) { $filters['severity'] = $severity; } $errors = MonitorService::getErrors($filters); return Response::success($errors); } #[GetRoute('/errors/statistics')] public function errorStatistics(): array { $stats = MonitorService::getErrorStatistics(); return Response::success($stats); } #[GetRoute('/errors/trends')] public function errorTrends(Request $request): array { $hours = (int)($request->get('hours', 24)); $trends = MonitorService::getErrorTrends($hours); return Response::success($trends); } #[GetRoute('/logs/search')] public function searchLogs(Request $request): array { $criteria = [ 'level' => $request->get('level'), 'message' => $request->get('message'), 'trace_id' => $request->get('trace_id'), 'start_time' => $request->get('start_time'), 'end_time' => $request->get('end_time'), 'pattern' => $request->get('pattern'), 'limit' => (int)($request->get('limit', 100)), 'offset' => (int)($request->get('offset', 0)), 'sort' => $request->get('sort', 'desc'), 'sort_by' => $request->get('sort_by', 'timestamp') ]; $results = MonitorService::searchLogs($criteria); return Response::success($results); } #[GetRoute('/logs/aggregate')] public function aggregateLogs(Request $request): array { $criteria = [ 'time_range' => $request->get('time_range', '1h'), 'group_by' => $request->get('group_by', 'level') ]; $results = MonitorService::aggregateLogs($criteria); return Response::success($results); } #[GetRoute('/logs/files')] public function getLogFiles(): array { $files = MonitorService::getLogFiles(); return Response::success($files); } #[GetRoute('/logs/content')] public function getLogContent(Request $request): array { $file = $request->get('file'); $lines = (int)($request->get('lines', 100)); $offset = (int)($request->get('offset', 0)); if (!$file) { return Response::error(400, 'File parameter is required'); } $content = MonitorService::getLogContent($file, $lines, $offset); return Response::success($content); } #[GetRoute('/logs/realtime')] public function getRealTimeLogs(Request $request): array { $tail = (int)($request->get('tail', 100)); $logs = MonitorService::getRealTimeLogs($tail); return Response::success($logs); } #[GetRoute('/logs/export')] public function exportLogs(Request $request): void { $criteria = [ 'level' => $request->get('level'), 'message' => $request->get('message'), 'start_time' => $request->get('start_time'), 'end_time' => $request->get('end_time'), 'limit' => (int)($request->get('limit', 1000)) ]; $format = $request->get('format', 'json'); $content = MonitorService::exportLogs($criteria, $format); $filename = 'logs_' . date('Y-m-d_H-i-s') . '.' . $format; header('Content-Type: ' . match ($format) { 'json' => 'application/json', 'csv' => 'text/csv', 'txt' => 'text/plain', default => 'application/octet-stream' }); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo $content; exit; } #[GetRoute('/logs/charts/{chartType}')] public function generateLogChart(string $chartType, Request $request): void { $data = []; $title = $request->get('title', ''); switch ($chartType) { case 'timeline': case 'error_trend': $timeRange = $request->get('time_range', '1h'); $aggregation = MonitorService::aggregateLogs(['time_range' => $timeRange]); $data = $aggregation['timeline'] ?? []; break; case 'level_distribution': $aggregation = MonitorService::aggregateLogs(); $data = $aggregation['groups'] ?? []; break; case 'top_errors': $aggregation = MonitorService::aggregateLogs(); $data = $aggregation['top_errors'] ?? []; break; case 'bar': $aggregation = MonitorService::aggregateLogs(); $data = $aggregation['groups'] ?? []; $title = $title ?: 'Log Distribution'; break; default: $data = []; } $chart = MonitorService::generateLogChart($chartType, $data, $title); header('Content-Type: image/svg+xml'); header('Cache-Control: no-cache'); echo $chart; exit; } #[GetRoute('/stats')] public function stats(): array { $metrics = MonitorService::getMetricsSummary(); $stats = [ 'system' => $metrics['system'] ?? [], 'http_requests' => $this->extractHttpStats($metrics), 'database' => $this->extractDatabaseStats($metrics), 'cache' => $this->extractCacheStats($metrics), 'errors' => $this->extractErrorStats($metrics), 'performance' => $this->extractPerformanceStats($metrics) ]; return Response::success($stats); } #[GetRoute('/dashboard')] public function dashboard(): array { $health = MonitorService::getHealthStatus(); $metrics = MonitorService::getMetricsSummary(); $alerts = MonitorService::getAlerts(); $dashboard = [ 'overview' => [ 'status' => $health['status'], 'uptime' => $metrics['system']['uptime'] ?? 0, 'memory_usage' => $metrics['system']['memory_usage'] ?? 0, 'cpu_usage' => $metrics['system']['cpu_usage'] ?? 0, 'active_alerts' => count($alerts) ], 'health_checks' => $health['checks'], 'metrics' => [ 'requests_total' => $this->getTotalRequests($metrics), 'errors_total' => $this->getTotalErrors($metrics), 'avg_response_time' => $this->getAverageResponseTime($metrics), 'success_rate' => $this->getSuccessRate($metrics) ], 'recent_alerts' => array_slice($alerts, 0, 10) ]; return Response::success($dashboard); } #[GetRoute('/clear')] public function clear(): array { MonitorService::clearMetrics(); return Response::success(null, 'Metrics cleared'); } private function extractHttpStats(array $metrics): array { $httpStats = []; if (isset($metrics['histograms']['http_request_duration'])) { $httpStats['duration'] = $metrics['histograms']['http_request_duration']; } if (isset($metrics['counters'])) { $httpStats['requests_by_status'] = []; foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'http_requests_total')) { $httpStats['requests_by_status'][$key] = $value; } } } return $httpStats; } private function extractDatabaseStats(array $metrics): array { $dbStats = []; if (isset($metrics['histograms']['db_query_duration'])) { $dbStats['query_duration'] = $metrics['histograms']['db_query_duration']; } if (isset($metrics['counters'])) { $dbStats['queries_by_type'] = []; foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'db_queries_total')) { $dbStats['queries_by_type'][$key] = $value; } } } return $dbStats; } private function extractCacheStats(array $metrics): array { $cacheStats = []; if (isset($metrics['counters'])) { $cacheStats['operations'] = []; $totalHits = 0; $totalMisses = 0; foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'cache_operations_total')) { $cacheStats['operations'][$key] = $value; if (str_contains($key, 'hit:true')) { $totalHits += $value; } elseif (str_contains($key, 'hit:false')) { $totalMisses += $value; } } } $total = $totalHits + $totalMisses; $cacheStats['hit_rate'] = $total > 0 ? round(($totalHits / $total) * 100, 2) . '%' : '0%'; } return $cacheStats; } private function extractErrorStats(array $metrics): array { $errorStats = []; if (isset($metrics['counters'])) { $errorStats['errors_by_type'] = []; foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'errors_total')) { $errorStats['errors_by_type'][$key] = $value; } } } if (isset($metrics['metrics']['error'])) { $errorStats['recent_errors'] = array_slice($metrics['metrics']['error'], -10); } return $errorStats; } private function extractPerformanceStats(array $metrics): array { $perfStats = [ 'memory' => $metrics['system'] ?? [], 'response_times' => [], 'throughput' => [] ]; if (isset($metrics['histograms']['http_request_duration'])) { $perfStats['response_times'] = $metrics['histograms']['http_request_duration']; } // 计算吞吐量(每秒请求数) if (isset($metrics['metrics']['http_requests_total'])) { $requests = $metrics['metrics']['http_requests_total']; $now = microtime(true); $requestsInLastMinute = 0; foreach ($requests as $request) { if ($now - $request['timestamp'] < 60) { $requestsInLastMinute++; } } $perfStats['throughput']['requests_per_minute'] = $requestsInLastMinute; $perfStats['throughput']['requests_per_second'] = round($requestsInLastMinute / 60, 2); } return $perfStats; } private function getTotalRequests(array $metrics): int { $total = 0; if (isset($metrics['counters'])) { foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'http_requests_total')) { $total += (int)$value; } } } return $total; } private function getTotalErrors(array $metrics): int { $total = 0; if (isset($metrics['counters'])) { foreach ($metrics['counters'] as $key => $value) { if (str_contains($key, 'errors_total')) { $total += (int)$value; } } } return $total; } private function getAverageResponseTime(array $metrics): float { if (isset($metrics['histograms']['http_request_duration']['mean'])) { return round($metrics['histograms']['http_request_duration']['mean'], 3); } return 0.0; } private function getSuccessRate(array $metrics): string { $totalRequests = $this->getTotalRequests($metrics); $totalErrors = $this->getTotalErrors($metrics); if ($totalRequests === 0) { return '100%'; } $successRate = (($totalRequests - $totalErrors) / $totalRequests) * 100; return round($successRate, 2) . '%'; } }