Files

174 lines
4.1 KiB
JavaScript
Raw Permalink Normal View History

"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,
};