fix: 修复架构分析报告指出的P0问题
**AI 告警分析(P0):** - 替换 setTimeout 伪AI为真实 LLM 调用 (aiApi.chat) - LLM 不可用时回退到规则模板(generateAIAnalysis) - 移除 Math.random() 随机置信度/相似案例 - 分析结果从 LLM JSON 响应解析 **SSH HostKey 验证(P0):** - webshell.go: InsecureIgnoreHostKey → TOFU 模式 - agent_install.go: 同步修复 - 首次连接记录 SHA256 fingerprint 到日志 - 后续连接校验 HostKey 一致性 **Ansible 执行引擎(P0):** - ExecutePlaybook 从模拟改为真实 ansible-playbook 调用 - 支持 extra-vars 参数传递 - 5分钟超时保护 - ansible-playbook 未安装时返回明确错误
This commit is contained in:
1 parent
a3cd0d3910
commit
9af0685e90
5 files changed
+167
-43
No files matched your search
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { alertApi } from '@/services/api';
|
||||
import { alertApi, aiApi } from '@/services/api';
|
||||
import {
|
||||
AlertTriangle,
|
||||
Brain,
|
||||
@@ -26,6 +26,26 @@ import {
|
||||
import { AIAnalysisResult } from './AIAnalysisResult';
|
||||
import { AutoFixDialog } from './AutoFixDialog';
|
||||
|
||||
// Parse LLM JSON response (may have markdown fences) into AIAnalysis
|
||||
function parseAIResponse(raw: string, fallback: AIAnalysis): AIAnalysis {
|
||||
try {
|
||||
// Strip markdown code fences if present
|
||||
let json = raw.replace(/```(?:json)?\s*\n?/g, '').replace(/```$/, '').trim();
|
||||
const parsed = JSON.parse(json);
|
||||
return {
|
||||
rootCause: parsed.root_cause || parsed.rootCause || fallback.rootCause,
|
||||
impact: parsed.impact || fallback.impact,
|
||||
recommendations: Array.isArray(parsed.recommendations) ? parsed.recommendations : fallback.recommendations,
|
||||
autoFixScript: parsed.auto_fix_script || parsed.autoFixScript || fallback.autoFixScript,
|
||||
similarCases: typeof parsed.similar_cases === 'number' ? parsed.similar_cases : (parsed.similarCases ?? fallback.similarCases),
|
||||
confidence: typeof parsed.confidence === 'number' ? parsed.confidence : fallback.confidence,
|
||||
};
|
||||
} catch {
|
||||
// Not valid JSON — return raw text as rootCause
|
||||
return { ...fallback, rootCause: raw };
|
||||
}
|
||||
}
|
||||
|
||||
export function AIAlertAnalyzer() {
|
||||
const [alerts, setAlerts] = useState<AlertItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -53,16 +73,47 @@ export function AIAlertAnalyzer() {
|
||||
}
|
||||
};
|
||||
|
||||
// 触发 AI 分析(模拟 1.5s 思考,实际由 generateAIAnalysis 动态生成上下文相关结果)
|
||||
const handleAnalyze = (alert: AlertItem) => {
|
||||
// 触发 AI 分析 — 优先调用 LLM,失败/未配置时回退到规则模板
|
||||
const handleAnalyze = async (alert: AlertItem) => {
|
||||
setSelectedAlert(alert);
|
||||
setIsAnalyzing(true);
|
||||
setAnalysis(null);
|
||||
|
||||
setTimeout(() => {
|
||||
setAnalysis(generateAIAnalysis(alert));
|
||||
const fallback = generateAIAnalysis(alert);
|
||||
|
||||
try {
|
||||
const prompt = `你是运维专家。请分析以下告警并以 JSON 格式回复(不要 markdown 代码块)。
|
||||
|
||||
告警名称:${alert.name}
|
||||
严重程度:${alert.severity}
|
||||
目标:${alert.source}
|
||||
指标:${alert.metric} = ${alert.currentValue}(阈值 ${alert.threshold})
|
||||
持续:${alert.duration}
|
||||
描述:${alert.description}
|
||||
|
||||
返回 JSON 格式(字段名用 snake_case):
|
||||
{
|
||||
"root_cause": "根因分析(2-3句)",
|
||||
"impact": "影响评估(1-2句)",
|
||||
"recommendations": ["建议1", "建议2", "建议3"],
|
||||
"auto_fix_script": "#!/bin/bash\\n...\\n(可选的自动修复脚本,无则 null)",
|
||||
"similar_cases": 数字(类似案例数预估),
|
||||
"confidence": 数字(0-100 置信度)
|
||||
}`;
|
||||
|
||||
const res = await aiApi.chat([{ role: 'user', content: prompt }]);
|
||||
const content = (res as any)?.content || (res as any)?.message?.content || '';
|
||||
if (content) {
|
||||
setAnalysis(parseAIResponse(content, fallback));
|
||||
} else {
|
||||
setAnalysis(fallback);
|
||||
}
|
||||
} catch {
|
||||
// LLM 未配置或调用失败 → 回退到规则模板
|
||||
setAnalysis(fallback);
|
||||
} finally {
|
||||
setIsAnalyzing(false);
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAutoFix = () => {
|
||||
|
||||
@@ -25,15 +25,14 @@ export interface AIAnalysis {
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
// ─── Dynamic AI analysis generator ───
|
||||
// 基于告警指标类型,生成上下文相关的根因分析、影响评估、修复建议与自动修复脚本。
|
||||
// ─── Dynamic AI analysis generator (rule-based fallback) ───
|
||||
// 当 LLM 未配置或调用失败时,基于告警指标类型生成上下文相关的分析模板。
|
||||
// confidence 设 0 表示规则模板(非 LLM),前端据此显示不同标识。
|
||||
export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
const metric = (alert.metric || '').toLowerCase();
|
||||
const target = alert.source || '目标主机';
|
||||
const isCritical = alert.severity === 'critical';
|
||||
|
||||
const baseConfidence = isCritical ? 88 + Math.floor(Math.random() * 8) : 75 + Math.floor(Math.random() * 12);
|
||||
|
||||
// CPU 告警
|
||||
if (metric.includes('cpu')) {
|
||||
return {
|
||||
@@ -48,8 +47,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'优化应用代码,排查是否存在低效算法或资源泄漏',
|
||||
],
|
||||
autoFixScript: `#!/bin/bash\n# CPU 高负载诊断脚本 - ${target}\necho "===== CPU TOP 10 进程 ====="\nps aux --sort=-%cpu | head -11\necho ""\necho "===== 系统负载 ====="\nuptime\necho ""\necho "===== 高 CPU 进程详情 ====="\nPID=$(ps aux --sort=-%cpu | sed -n '2p' | awk '{print $2}')\nif [ -n "$PID" ]; then\n echo "最高 CPU 进程: PID=$PID"\n cat /proc/$PID/cmdline | tr '\\0' ' '\n echo ""\nfi\n`,
|
||||
similarCases: 18 + Math.floor(Math.random() * 8),
|
||||
confidence: baseConfidence,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -66,8 +65,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'排查是否存在内存泄漏,必要时生成堆转储分析',
|
||||
'调整缓存大小限制或增加交换分区',
|
||||
],
|
||||
similarCases: 12 + Math.floor(Math.random() * 6),
|
||||
confidence: baseConfidence,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,8 +84,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'考虑扩容磁盘或将数据迁移到对象存储',
|
||||
],
|
||||
autoFixScript: `#!/bin/bash\n# 磁盘清理脚本 - ${target}\necho "===== 清理前磁盘使用 ====="\ndf -h /\necho ""\necho "===== 清理 30 天前日志 ====="\nfind /var/log -name "*.log" -mtime +30 -delete 2>/dev/null\nfind /var/log -name "*.gz" -mtime +30 -delete 2>/dev/null\necho ""\necho "===== 清理系统缓存 ====="\njournalctl --vacuum-time=7d 2>/dev/null\necho ""\necho "===== 清理后磁盘使用 ====="\ndf -h /\n`,
|
||||
similarCases: 23 + Math.floor(Math.random() * 10),
|
||||
confidence: baseConfidence + 3,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,8 +102,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'检查防火墙规则是否有限速或异常丢弃',
|
||||
'考虑启用熔断/降级机制保障核心链路',
|
||||
],
|
||||
similarCases: 8 + Math.floor(Math.random() * 5),
|
||||
confidence: baseConfidence - 5,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -122,8 +121,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'必要时重启服务并监控恢复情况',
|
||||
],
|
||||
autoFixScript: `#!/bin/bash\n# 服务恢复脚本 - ${target}\necho "===== 检查服务状态 ====="\nsystemctl list-units --state=failed\necho ""\necho "===== 检查端口监听 ====="\nss -tlnp | grep -E ':(80|443|8080|3306|6379|9090)'\necho ""\necho "===== 重启失败服务 ====="\nsystemctl reset-failed\n`,
|
||||
similarCases: 6 + Math.floor(Math.random() * 4),
|
||||
confidence: baseConfidence,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,8 +138,8 @@ export function generateAIAnalysis(alert: AlertItem): AIAnalysis {
|
||||
'关联同时间段的其他告警,排查是否有连锁反应',
|
||||
'若确认误报,调整告警规则阈值或持续时间',
|
||||
],
|
||||
similarCases: 5 + Math.floor(Math.random() * 5),
|
||||
confidence: baseConfidence - 8,
|
||||
similarCases: 0,
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user