validate([ 'from' => 'required|date', 'to' => 'required|date|after:from', 'query' => 'nullable|string|max:1000', 'limit' => 'nullable|integer|min:1|max:1000', 'logstores' => 'nullable|array', 'logstores.*' => 'string', ]); if (!$this->slsService->isConfigured()) { return response()->json([ 'success' => false, 'message' => 'SLS 服务未配置,请检查 .env 中的 SLS_* 配置项', ], 400); } try { // 如果指定了多个 logstore,使用多 logstore 查询 if (!empty($validated['logstores']) && count($validated['logstores']) > 1) { $result = $this->analysisService->queryLogsFromMultipleStores( Carbon::parse($validated['from']), Carbon::parse($validated['to']), $validated['query'] ?? null, $validated['limit'] ?? 100, $validated['logstores'] ); } else { // 单个 logstore 查询 $result = $this->analysisService->queryLogs( Carbon::parse($validated['from']), Carbon::parse($validated['to']), $validated['query'] ?? null, $validated['limit'] ?? 100 ); } return response()->json([ 'success' => true, 'data' => $result, ]); } catch (\Exception $e) { $errorMessage = $e->getMessage(); // 优化常见错误提示 if (str_contains($errorMessage, 'key') && str_contains($errorMessage, 'is not config as key value config')) { $errorMessage = 'SLS 查询语法错误:使用 "字段:值" 语法需要该字段配置为键值索引。建议使用全文搜索(如 "ERROR")或 SQL 语法(如 "* | where level = \"ERROR\"")'; } elseif (str_contains($errorMessage, 'ParameterInvalid')) { $errorMessage = 'SLS 查询参数无效:' . $errorMessage . '。请检查查询语法是否正确'; } return response()->json([ 'success' => false, 'message' => $errorMessage, ], 500); } } /** * 获取可用的 logstore 列表 */ public function getLogstores(): JsonResponse { if (!$this->slsService->isConfigured()) { return response()->json([ 'success' => false, 'message' => 'SLS 服务未配置', ], 400); } try { $logstores = $this->slsService->getLogstores(); return response()->json([ 'success' => true, 'data' => [ 'logstores' => $logstores, ], ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => $e->getMessage(), ], 500); } } /** * 执行异步分析(创建后台任务) */ public function analyze(Request $request): JsonResponse { $validated = $request->validate([ 'from' => 'required|date', 'to' => 'required|date|after:from', 'query' => 'nullable|string|max:1000', 'mode' => 'nullable|in:logs,logs+code', ]); if (!$this->slsService->isConfigured()) { return response()->json([ 'success' => false, 'message' => 'SLS 服务未配置', ], 400); } if (!$this->aiService->isConfigured()) { return response()->json([ 'success' => false, 'message' => 'AI 服务未配置,请在设置页面配置 AI 提供商', ], 400); } $mode = ($validated['mode'] ?? 'logs') === 'logs+code' ? AnalysisMode::LogsWithCode : AnalysisMode::Logs; try { // 创建异步分析任务 $report = $this->analysisService->analyzeAsync( Carbon::parse($validated['from']), Carbon::parse($validated['to']), $validated['query'] ?? null, $mode ); return response()->json([ 'success' => true, 'message' => '分析任务已创建,请在历史报告中查看结果', 'data' => [ 'report_id' => $report->id, 'status' => $report->status, ], ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => $e->getMessage(), ], 500); } } /** * 获取历史报告列表 */ public function listReports(Request $request): JsonResponse { $validated = $request->validate([ 'limit' => 'nullable|integer|min:1|max:100', 'offset' => 'nullable|integer|min:0', ]); $result = $this->analysisService->getReports( $validated['limit'] ?? 20, $validated['offset'] ?? 0 ); return response()->json([ 'success' => true, 'data' => $result, ]); } /** * 获取单个报告详情 */ public function getReport(int $id): JsonResponse { $report = $this->analysisService->getReport($id); if (!$report) { return response()->json([ 'success' => false, 'message' => '报告不存在', ], 404); } return response()->json([ 'success' => true, 'data' => $report, ]); } /** * 获取配置 */ public function getConfig(): JsonResponse { return response()->json([ 'success' => true, 'data' => [ 'sls_configured' => $this->slsService->isConfigured(), 'ai_configured' => $this->aiService->isConfigured(), 'ai_providers' => $this->aiService->getProviders(), 'active_ai_provider' => $this->aiService->getActiveProvider(), 'app_env_map' => $this->configService->get('log_analysis.app_env_map', []), 'settings' => $this->configService->get('log_analysis.settings', [ 'max_logs_per_batch' => 1000, 'max_logs_per_app' => 500, 'default_time_window_minutes' => 60, 'schedule_enabled' => false, ]), ], ]); } /** * 更新配置(需要管理员权限) */ public function updateConfig(Request $request): JsonResponse { $validated = $request->validate([ 'app_env_map' => 'nullable|array', 'settings' => 'nullable|array', 'ai_providers' => 'nullable|array', 'active_ai_provider' => 'nullable|string', ]); try { if (isset($validated['app_env_map'])) { $this->configService->set( 'log_analysis.app_env_map', $validated['app_env_map'], 'Log analysis app to project/env mapping' ); } if (isset($validated['settings'])) { $this->configService->set( 'log_analysis.settings', $validated['settings'], 'Log analysis settings' ); } if (isset($validated['ai_providers'])) { $this->aiService->saveProviders($validated['ai_providers']); } if (isset($validated['active_ai_provider'])) { $this->aiService->setActiveProvider($validated['active_ai_provider']); } return response()->json([ 'success' => true, 'message' => '配置已更新', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => $e->getMessage(), ], 400); } } /** * 测试 SLS 连接 */ public function testSlsConnection(): JsonResponse { if (!$this->slsService->isConfigured()) { return response()->json([ 'success' => false, 'message' => 'SLS 服务未配置', ]); } $connected = $this->slsService->testConnection(); return response()->json([ 'success' => $connected, 'message' => $connected ? 'SLS 连接成功' : 'SLS 连接失败', ]); } /** * 测试 AI 连接 */ public function testAiConnection(): JsonResponse { $result = $this->aiService->testConnection(); return response()->json([ 'success' => $result['success'], 'message' => $result['message'], 'data' => $result, ]); } }