"use strict"; /** * Prompt 解析器 - 从命令输出中提取指标 * * 分层策略: * 1. 正则匹配(快,简单场景够用) * 2. 返回原始输出(解析失败时让用户看原始数据) */ /** * 华为/H3C 交换机命令解析配置 */ const HUAWEI_H3C_PATTERNS = { cpu_usage: { // CPU 使用率:多种可能的格式 patterns: [ /CPU\s+Usage\s*:\s*(\d+)%/i, /CPU\s+utilization.*one\s+minute:\s*(\d+)%/i, /CPU\s+Usage\s+:\s*(\d+)%/i, ], default: null, }, memory_usage: { // 内存使用率:多种格式 patterns: [ /Memory\s+Using\s+Percentage\s+Is:\s*(\d+)%/i, /Memory\s+utilization.*:\s*(\d+)%/i, ], default: null, }, }; /** * 解析单行指标 * @param {string} output - 命令原始输出 * @param {object} config - { patterns: RegExp[], default: any } * @returns {any} 解析结果 */ function parseMetric(output, config) { if (!output || !config?.patterns) return config?.default ?? null; for (const pattern of config.patterns) { const match = output.match(pattern); if (match) { return parseFloat(match[1]); } } return config.default ?? null; } /** * 解析端口状态 * @param {string} output - 命令输出 * @returns {object} { up_count, down_count, ports } */ function parseInterfaceBrief(output) { const lines = output.split("\n"); const ports = []; let upCount = 0; let downCount = 0; for (const line of lines) { // 匹配端口行:GigabitEthernet0/0/1 up up const portMatch = line.match(/^(GigabitEthernet|FastEthernet|Ethernet)(\S+)\s+(\w+)\s+(\w+)/); if (portMatch) { const phy = portMatch[3].toLowerCase(); const proto = portMatch[4].toLowerCase(); ports.push({ name: portMatch[1] + portMatch[2], phy, protocol: proto, is_up: phy === "up" && proto === "up", }); if (phy === "up") upCount++; else downCount++; } } return { up_count: upCount, down_count: downCount, ports }; } /** * 解析电源状态 * @param {string} output - 命令输出 * @returns {object} { normal_count, abnormal_count } */ function parsePowerStatus(output) { const lines = output.split("\n"); let normalCount = 0; let abnormalCount = 0; for (const line of lines) { // 匹配电源状态行 if (/Normal|Supply|OK/i.test(line)) { normalCount++; } else if (/Absent|Fault|Error/i.test(line)) { abnormalCount++; } } return { normal_count: normalCount, abnormal_count: abnormalCount }; } /** * 清理交换机输出 * @param {string} output - 原始输出 * @returns {string} 清理后的输出 */ function cleanOutput(output) { return output // 移除提示符 .replace(/<\w+[-A-Za-z0-9]*>/g, "") // 移除分页标记 .replace(/---- More ----/g, "") // 移除命令回显 .replace(/^[^\r\n]*\r?\n/, "") // 移除空行 .replace(/\n{3,}/g, "\n\n") .trim(); } /** * 使用 prompt 风格解析交换机输出 * @param {string} output - 原始命令输出 * @param {object} context - { catalog_id, device_info } * @returns {object} 结构化指标 */ function parseSwitchOutput(output, context = {}) { const cleaned = cleanOutput(output); const lines = cleaned.split("\n"); const metrics = { cpu_usage: null, memory_usage: null, port_status: [], power_status: [], fan_status: [], }; // 解析 CPU metrics.cpu_usage = parseMetric(cleaned, HUAWEI_H3C_PATTERNS.cpu_usage); // 解析内存 metrics.memory_usage = parseMetric(cleaned, HUAWEI_H3C_PATTERNS.memory_usage); // 解析端口 metrics.port_status = parseInterfaceBrief(cleaned); // 解析电源 metrics.power_status = parsePowerStatus(cleaned); // 原始输出(便于调试) metrics._raw_output = cleaned; metrics._parse_errors = []; if (metrics.cpu_usage === null) { metrics._parse_errors.push("cpu_usage: 无法解析"); } if (metrics.memory_usage === null) { metrics._parse_errors.push("memory_usage: 无法解析"); } return metrics; } module.exports = { parseMetric, parseInterfaceBrief, parsePowerStatus, cleanOutput, parseSwitchOutput, };