diff options
| author | chenjinsong <[email protected]> | 2018-09-27 16:11:54 +0800 |
|---|---|---|
| committer | chenjinsong <[email protected]> | 2018-09-27 16:11:54 +0800 |
| commit | 56d71f261a8bd6031e47e2bf80867049a2aa13da (patch) | |
| tree | f09257b2143782a333a9eda3395137837d9bdad1 /src/com/nis/systeminfo | |
initial commit
Diffstat (limited to 'src/com/nis/systeminfo')
| -rw-r--r-- | src/com/nis/systeminfo/model/DetectInfo.java | 49 | ||||
| -rw-r--r-- | src/com/nis/systeminfo/model/SystemInfo.java | 1029 | ||||
| -rw-r--r-- | src/com/nis/systeminfo/thread/GetInfoRun.java | 592 | ||||
| -rw-r--r-- | src/com/nis/systeminfo/thread/NewPluginResultMerge.java | 476 | ||||
| -rw-r--r-- | src/com/nis/systeminfo/thread/PluginResultMerge.java | 451 |
5 files changed, 2597 insertions, 0 deletions
diff --git a/src/com/nis/systeminfo/model/DetectInfo.java b/src/com/nis/systeminfo/model/DetectInfo.java new file mode 100644 index 0000000..8ffd12f --- /dev/null +++ b/src/com/nis/systeminfo/model/DetectInfo.java @@ -0,0 +1,49 @@ +package com.nis.systeminfo.model; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class DetectInfo { + /* + * 该字段是针对,同一时间点多条具体数据(写多个文件),比如:网卡监测(多个网卡问题) + */ + private List<String> detailDatas = new LinkedList<String>(); + /* + * 针对公共数据的描述信息 + */ + private String descInfo; + /* + * 该字段是针对一条数据,关联的其他表的数据;写入到一个文件的: String 是解析标识, List<String[]>是多条数据(String[]存入表中的数据) + * 如:系统信息监测,数据中有网卡数量,网卡数量关联着其他表(表中又有多个字段,如网卡名称,IP,子网掩码等等) + */ + private Map<String, List<String[]>> relatedDatas; + + private String diskMsg;//用于存储硬盘只读和磁盘满的异常信息 + + public List<String> getDetailDatas() { + return detailDatas; + } + public void setDetailDatas(List<String> detailDatas) { + this.detailDatas = detailDatas; + } + public String getDescInfo() { + return descInfo; + } + public void setDescInfo(String descInfo) { + this.descInfo = descInfo; + } + public Map<String, List<String[]>> getRelatedDatas() { + return relatedDatas; + } + public void setRelatedDatas(Map<String, List<String[]>> relatedDatas) { + this.relatedDatas = relatedDatas; + } + public String getDiskMsg() { + return diskMsg; + } + public void setDiskMsg(String diskMsg) { + this.diskMsg = diskMsg; + } + +} diff --git a/src/com/nis/systeminfo/model/SystemInfo.java b/src/com/nis/systeminfo/model/SystemInfo.java new file mode 100644 index 0000000..0a2d42f --- /dev/null +++ b/src/com/nis/systeminfo/model/SystemInfo.java @@ -0,0 +1,1029 @@ +package com.nis.systeminfo.model; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.apache.log4j.Logger; +import org.hyperic.sigar.Cpu; +import org.hyperic.sigar.CpuInfo; +import org.hyperic.sigar.CpuPerc; +import org.hyperic.sigar.FileSystem; +import org.hyperic.sigar.FileSystemUsage; +import org.hyperic.sigar.Mem; +import org.hyperic.sigar.NetFlags; +import org.hyperic.sigar.NetInterfaceConfig; +import org.hyperic.sigar.NetInterfaceStat; +import org.hyperic.sigar.ProcCpu; +import org.hyperic.sigar.ProcState; +import org.hyperic.sigar.Sigar; +import org.hyperic.sigar.SigarException; +import org.hyperic.sigar.Swap; +import org.hyperic.sigar.Uptime; +import org.hyperic.sigar.cmd.Ps; +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.thread.socket.CommonSocket; +import com.nis.nmsclient.thread.socket.SSLClient; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.ProcessUtil; +import com.nis.nmsclient.util.Utils; + +public class SystemInfo +{ + + static Logger logger = Logger.getLogger(SystemInfo.class); + + public static String SEPARATOR = "@#@"; + + private Thread thread = null;// 这个属性是取进程信息中启动进程时使用 + + public DetectInfo getDetectInfo(String checkType, String pidFile, String processPath, + String procSearchKey, boolean isStart) + { + DetectInfo detectInfo = null; + if (checkType != null) + { + if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_CPU)) + {// CPU + detectInfo = testCpuPerc(); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_MEMORY)) + {// 内存 + detectInfo = testPhysicalMemory(); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_DISK)) + {// 硬盘 + detectInfo = testFileSystemInfo(); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_NET)) + {// 网络流量 + detectInfo = testNetDataList(); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_SYSDATE)) + {// 系统时间 + detectInfo = testSystemDate(); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_PROCESS)) + {// 进程信息 + detectInfo = testProcessInfo(pidFile, processPath, procSearchKey, isStart); + } else if (checkType.equalsIgnoreCase(Contants.SYS_CHECK_TYPE_SYSTEMINFO)) + {// 系统信息 + detectInfo = testSystemInfo(); + } + } + + return detectInfo; + } + + // CPU的用户使用量、系统使用剩余量、总的剩余量、总的使用占用量等(单位:100%) + public DetectInfo testCpuPerc() + { + DetectInfo detectInfo = new DetectInfo(); + try + { + Sigar sigar = new Sigar(); + // 不管是单块CPU还是多CPU都适用 + CpuPerc cpuList[] = sigar.getCpuPercList(); + CpuInfo[] cpuInfos = sigar.getCpuInfoList(); +// StringBuffer sb2 = new StringBuffer(cpuList.length + "核: "); + StringBuffer sb2 = new StringBuffer(); + double userCpuPerc = 0.0; + double sysCpuPerc = 0.0; + double waitCpuPerc = 0.0; + double niceCpuPerc = 0.0; + double idleCpuPerc = 0.0; + double totalCpuPerc = 0.0; + long mhzCpuPerc = 0; + for (int i = 0; i < cpuList.length; i++) + { + StringBuffer sb = new StringBuffer(); + sb.append("cpu" + i);// 标识 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getUser()));// 用户使用率:CPU耗费在不正常的用户进程的使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getSys()));// 系统使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getWait()));// 当前等待率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getNice()));// 用户使用率:正常的用户进程的CPU使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getIdle()));// 当前空闲率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(cpuList[i].getCombined()));// 总的使用率 + sb.append(SEPARATOR); + sb.append(cpuInfos[i].getMhz());// 主频 + detectInfo.getDetailDatas().add(sb.toString().replace("%", "")); +// sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+"cpu" + i + " 主频" + cpuInfos[i].getMhz() + "MHz,使用率 " + sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+"cpu" + i + " i18n_client.SystemInfo.mhz_n81i" + cpuInfos[i].getMhz() + "MHz,i18n_client.SystemInfo.shiyonglv_n81i " + + CpuPerc.format(cpuList[i].getCombined()) + "; "); + + // CPU总体信息情况 + userCpuPerc += cpuList[i].getUser();// 用户使用率累加 + sysCpuPerc += cpuList[i].getSys();// 系统使用率 + waitCpuPerc += cpuList[i].getWait();// 当前等待率 + niceCpuPerc += cpuList[i].getNice();// 用户使用率:正常的用户进程的CPU使用率 + idleCpuPerc += cpuList[i].getIdle();// 当前空闲率 + totalCpuPerc += cpuList[i].getCombined();// 总的使用率 + mhzCpuPerc = cpuInfos[i].getMhz();// 主频 + } + + StringBuffer sb = new StringBuffer(); + sb.append("cpu");// 标识 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(userCpuPerc/cpuList.length));// 用户使用率:CPU耗费在不正常的用户进程的使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(sysCpuPerc/cpuList.length));// 系统使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(waitCpuPerc/cpuList.length));// 当前等待率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(niceCpuPerc/cpuList.length));// 用户使用率:正常的用户进程的CPU使用率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(idleCpuPerc/cpuList.length));// 当前空闲率 + sb.append(SEPARATOR); + sb.append(CpuPerc.format(totalCpuPerc/cpuList.length));// 总的使用率 + sb.append(SEPARATOR); + sb.append(mhzCpuPerc);// 主频 + detectInfo.getDetailDatas().add(sb.toString().replace("%", "")); +// sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+"cpu" + " 主频" +mhzCpuPerc + "MHz,使用率 " + CpuPerc.format(totalCpuPerc/cpuList.length) + "; "); +// sb2.insert(0,cpuList.length + "核: "+Contants.DETEC_STATE_INFO_FORMATE_POINT+"cpu" + " 主频" +mhzCpuPerc + "MHz,使用率 " + CpuPerc.format(totalCpuPerc/cpuList.length) + "; "); + sb2.insert(0,cpuList.length + "i18n_client.SystemInfo.core_n81i: "+Contants.DETEC_STATE_INFO_FORMATE_POINT+"cpu" + "i18n_client.SystemInfo.mhz_n81i" +mhzCpuPerc + "MHz,i18n_client.SystemInfo.shiyonglv_n81i " + CpuPerc.format(totalCpuPerc/cpuList.length) + "; "); + + detectInfo.setDescInfo(sb2.toString()); + logger.debug("testCpuPerc---" + sb2.toString()); + } catch (Exception e) + { + logger.error("Getting CPU information exception", e); + return null; + } + + return detectInfo; + } + + // 内存资源信息 + public DetectInfo testPhysicalMemory() + { + DetectInfo detectInfo = new DetectInfo(); + try + { + Sigar sigar = new Sigar(); + + StringBuffer sb = new StringBuffer(); + // b)系统页面文件交换区信息 + Swap swap = sigar.getSwap(); + Long swapTotal = swap.getTotal(); // 交换区总量 + Long swapFree = swap.getFree();// 当前交换区剩余量 + sb.append(doubleFormat(swapTotal / (1024 * 1024 * 1024.0), 2));// 交换区总量,单位:"G" + sb.append(SEPARATOR); + sb.append(doubleFormat(swapFree / (1024 * 1024 * 1024.0), 2));// 当前交换区剩余量,单位:"G" + sb.append(SEPARATOR); + // sb.append(SEPARATOR); + // sb.append(swap.getUsed() / 1024L);// 当前交换区使用量,单位:"K" + // a)物理内存信息 + Mem mem = sigar.getMem(); + Long memTotal = mem.getTotal();// 内存总量 + Long memUsed = mem.getUsed();// 当前内存使用量 + Long memFree = mem.getFree();// 当前内存剩余量 + sb.append(doubleFormat(memTotal / (1024 * 1024 * 1024.0), 2));// 内存总量,单位:"G" + sb.append(SEPARATOR); + sb.append(doubleFormat(memUsed / (1024 * 1024 * 1024.0), 2));// 当前内存使用量,单位:"G" + sb.append(SEPARATOR); + sb.append(doubleFormat(memFree / (1024 * 1024 * 1024.0), 2));// 当前内存剩余量,单位:"G" + sb.append(SEPARATOR); + sb.append(doubleFormat(((memTotal - memFree) * 100.0) / memTotal, 1));// 内存使用率 + + StringBuffer sb2 = new StringBuffer(); +// sb2.append("内存总大小: " + doubleFormat(memTotal / (1024 * 1024 * 1024.0), 2) + "G, 现使用:" +// + doubleFormat(memUsed / (1024 * 1024 * 1024.0), 2) + "G, 剩余:" +// + doubleFormat(memFree / (1024 * 1024 * 1024.0), 2) + "G, 使用率:" +// + doubleFormat(((memTotal - memFree) * 100.0) / memTotal, 1) + "%"); + sb2.append("i18n_client.SystemInfo.memerySize_n81i: " + doubleFormat(memTotal / (1024 * 1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.currentUsed_n81i:" + + doubleFormat(memUsed / (1024 * 1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.spaceRemain_n81i:" + + doubleFormat(memFree / (1024 * 1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.shiyonglv_n81i:" + + doubleFormat(((memTotal - memFree) * 100.0) / memTotal, 1) + "%"); + + detectInfo.getDetailDatas().add(sb.toString()); + detectInfo.setDescInfo(sb2.toString()); + + logger.debug("testPhysicalMemory--sb2=[ " + sb2.toString() + " ] -- tt=" + + doubleFormat(mem.getUsedPercent(), 1)); + } catch (SigarException e) + { + logger.error("Getting the exception of memory information", e); + return null; + } + + return detectInfo; + } + + // 资源信息(主要是硬盘已有的分区及其详细信息) + public DetectInfo testFileSystemInfo() + { + int num=0; + DetectInfo detectInfo = new DetectInfo(); + try + { + Sigar sigar = new Sigar(); + long allTotal = 0l; + long allUse = 0l; + // long allFree = 0l; + StringBuffer sb2 = new StringBuffer(); + String dirName = ""; + FileSystem fslist[] = sigar.getFileSystemList(); + for (int i = 0; i < fslist.length; i++) + { + FileSystem fs = fslist[i]; + try + { + FileSystemUsage usage = sigar.getFileSystemUsage(fs.getDirName()); + if (fs.getType() == 2) + {// 先取每个盘符的大小和剩余空间 + long total = usage.getTotal();// 文件系统总大小, 单位:"KB" + long free = usage.getFree();// 文件系统剩余大小, 单位:"KB" + String usePerc = doubleFormat(usage.getUsePercent() * 100, 1); // 文件系统资源的利用率 + + allTotal += total;// 文件系统总大小, 单位:"KB" + // allFree += free;// 文件系统剩余大小, 单位:"KB" + allUse += usage.getUsed();//文件系统使用大小, 单位:"KB" + + StringBuffer sb = new StringBuffer(); + sb.append(fs.getDirName()); + dirName +=fs.getDirName()+","; + sb.append(SEPARATOR); + sb.append(doubleFormat(total / (1024 * 1024.0), 2));// 文件系统总大小, + // 单位:"GB" + sb.append(SEPARATOR); + sb.append(doubleFormat(free / (1024 * 1024.0), 2));// 文件系统剩余大小, + // 单位:"GB" + sb.append(SEPARATOR); + sb.append(usePerc);// 文件系统资源的利用率 + sb.append(SEPARATOR); + if (checkFileSystemIsWrite(fs.getDirName())) + {// 文件系统是否可写 + sb.append("0");// 可写:0 + } else + { + sb.append("1");// 不可写:1 + num ++; + } + + detectInfo.getDetailDatas().add(sb.toString()); + +// sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+"【" + fs.getDirName() + "】大小 " +// + doubleFormat(total / (1024 * 1024.0), 2) + "G, 已使用 " +// + doubleFormat((total-free) / (1024 * 1024.0), 2) + "G, 剩余 " +// + doubleFormat(free / (1024 * 1024.0), 2) + "G, Usage 使用率 " +// + usePerc + "% ; "); + sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+"【" + fs.getDirName() + "】i18n_client.SystemInfo.size_n81i " + + doubleFormat(total / (1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.used1_n81i " + + doubleFormat((total-free) / (1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.spaceRemain_n81i " + + doubleFormat(free / (1024 * 1024.0), 2) + "G, i18n_client.SystemInfo.shiyonglv_n81i " + + usePerc + "% ; "); + } + } catch (SigarException e) + { + if (fs.getType() == 2) + throw e; + continue; + } + } + // 文件系统资源的总利用率 + // String allUsePerc = doubleFormat((allUse * 1.0 / allTotal) * 100, + // 1); + + if(num==detectInfo.getDetailDatas().size()){//所有硬盘不可写 主动告警 +// String msg = "磁盘"+dirName.substring(0,dirName.length()-1)+"只读"; + String msg = "i18n_client.SystemInfo.disk_n81i"+dirName.substring(0,dirName.length()-1)+"i18n_client.SystemInfo.readOnly_n81i"; + detectInfo.setDiskMsg(msg); + return detectInfo; + } + if(allUse==allTotal){//当磁盘满时候主动告警 +// String msg = "磁盘总大小"+doubleFormat(allTotal / (1024 * 1024.0), 2)+"G,总的使用率 100%,分区 "+dirName.substring(0,dirName.length()-1)+"剩余 0%"; + String msg = "i18n_client.SystemInfo.diskSize_n81i"+doubleFormat(allTotal / (1024 * 1024.0), 2)+"G,i18n_client.SystemInfo.zongShiYongLv_n81i,i18n_client.SystemInfo.zone_n81i "+dirName.substring(0,dirName.length()-1)+"i18n_client.SystemInfo.spaceRemain_n81i 0%"; + detectInfo.setDiskMsg(msg); + return detectInfo; + } + + DecimalFormat decimalFormat = new DecimalFormat("0.00"); +// sb2.insert(0, "磁盘总大小:" + doubleFormat(allTotal / (1024 * 1024.0), 2) + "G,已使用 "+decimalFormat.format(((double)allUse/(double)allTotal)*100)+"% ; "); + sb2.insert(0, "i18n_client.SystemInfo.diskSize_n81i:" + doubleFormat(allTotal / (1024 * 1024.0), 2) + "G,i18n_client.SystemInfo.used2_n81i "+decimalFormat.format(((double)allUse/(double)allTotal)*100)+"% ; "); + detectInfo.setDescInfo(sb2.toString()); + logger.debug("testFileSystemInfo--sb2=[ " + sb2.toString() + " ]"); + + } catch (SigarException e) + { + logger.error("Getting hard disk information abnormity", e); + return null; + } + + return detectInfo; + } + + // 获取网络流量等信息 + public DetectInfo testNetDataList() + { + DetectInfo detectInfo = new DetectInfo(); + try + { + Sigar sigar = new Sigar(); + String ifNames[] = sigar.getNetInterfaceList(); + if (ifNames.length > 0) + { + StringBuffer sb2 = new StringBuffer(); + int ethernetCnt = 0; + + // 2013-02-26 设备名的处理并去重,这个是针对一块网卡有多个逻辑配置 如 eth0和eth0:1,只取eth0即可 + List<String> nameList = new LinkedList<String>(); + for (int i = 0; i < ifNames.length; i++) + { + String name = ifNames[i]; + + if (name.indexOf(":") != -1) + { + name = name.substring(0, name.indexOf(":")); + } + + if (!nameList.contains(name)) + { + nameList.add(name); + } + } + + for (int i = 0; i < nameList.size(); i++) + { + String name = nameList.get(i); + + NetInterfaceConfig ifconfig = sigar.getNetInterfaceConfig(name); + logger.debug("testNetDataList----type= " + ifconfig.getType()); + + // *** 网卡类型:ethernet, Local Loopback(本地环回网卡) + // *** 这里只取 ethernet 网卡类型 + if ((ifconfig.getFlags() & NetFlags.IFF_LOOPBACK) > 0) + { + continue; + } + /* + * if ((ifconfig.getFlags() & NetFlags.IFF_POINTOPOINT) > 0) { + * continue; } + */ + // 2013-4-22 针对LInux,按名称过滤掉sit0,实际命令查看类型为:IPv6-in-IPv4 + if (name.equals("sit0")) + { + continue; + } + // 2013-5-23 针对Win7取到的网卡数量太多问题 + if ((ifconfig.getFlags() & NetFlags.IFF_BROADCAST) <= 0) + {// broadcast地址无效 + continue; + } + if ((ifconfig.getFlags() & NetFlags.IFF_MULTICAST) <= 0) + {// 不支持multicast + continue; + } + ethernetCnt++; + + if ((ifconfig.getFlags() & NetFlags.IFF_UP) <= 0) + { + // print("!IFF_UP...skipping getNetInterfaceStat"); +// sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+name + " 不可用; "); + sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+name + " i18n_client.SystemInfo.disable_n81i; "); + continue; + } + + NetInterfaceStat ifstat; + try + { + ifstat = sigar.getNetInterfaceStat(name); + } catch (SigarException e) + { + continue; + } + Long rxPackets1 = ifstat.getRxPackets();// 接收的总包裹数 + Long txPackets1 = ifstat.getTxPackets();// 发送的总包裹数 + Long rxBytes1 = ifstat.getRxBytes();// 接收到的总字节数 + Long txBytes1 = ifstat.getTxBytes();// 发送的总字节数 + Long rxErrors1 = ifstat.getRxErrors();// 接收到的错误包数 + Long txErrors1 = ifstat.getTxErrors();// 发送数据包时的错误数 + Long rxDropped1 = ifstat.getRxDropped();// 接收时丢弃的包数 + Long txDropped1 = ifstat.getTxDropped();// 发送时丢弃的包数 + + int seconds = 5; + try + { + Thread.sleep(seconds * 1000);// 等待5秒 + } catch (InterruptedException e) + { + e.printStackTrace(); + } + + ifstat = sigar.getNetInterfaceStat(name); + Long rxPackets2 = ifstat.getRxPackets();// 接收的总包裹数 + Long txPackets2 = ifstat.getTxPackets();// 发送的总包裹数 + Long rxBytes2 = ifstat.getRxBytes();// 接收到的总字节数 + Long txBytes2 = ifstat.getTxBytes();// 发送的总字节数 + Long rxErrors2 = ifstat.getRxErrors();// 接收到的错误包数 + Long txErrors2 = ifstat.getTxErrors();// 发送数据包时的错误数 + Long rxDropped2 = ifstat.getRxDropped();// 接收时丢弃的包数 + Long txDropped2 = ifstat.getTxDropped();// 发送时丢弃的包数 + + + // 添加监测日志,用于检查网络流量出现负值的原因 + logger.debug(" bps 输入: rxBytes1:" + rxBytes1 + ", rxBytes2:" + rxBytes2); + logger.debug(" bps 输出: txBytes1:" + txBytes1 + ", txBytes2:" + txBytes2); + logger.debug(" pps 输入: rxPackets1:" + rxPackets1 + ", rxPackets2:" + rxPackets2); + logger.debug(" pps 输出: txPackets1:" + txPackets1 + ", txPackets2:" + txPackets2); + + Long speed = ifstat.getSpeed() / (1000 * 1000);// 带宽:Mbps + // bps 输入:((第二次接收的总字节数-第一次)*8)/(时间秒*1000*1000)Mbps + // String rx_bps = doubleFormat(((rxBytes2 - rxBytes1) * 8) + // / (seconds * 1000 * 1000), 2); + // bps 输入:((第二次接收的总字节数-第一次)*8)/(时间秒)bps + String rx_bps = doubleFormat(((rxBytes2 - rxBytes1) * 8) / (seconds), 2); + // bps 输出:((第二次发送的总字节数-第一次)*8)/(时间秒)bps + String tx_bps = doubleFormat(((txBytes2 - txBytes1) * 8) / (seconds), 2); + // pps 输入:(第二次接收的总包裹数-第一次)/时间秒 + Long rx_pps = (rxPackets2 - rxPackets1) / seconds; + // pps 输出:(第二次发送的总包裹数-第一次)/时间秒 + Long tx_pps = (txPackets2 - txPackets1) / seconds; + Long rx_errorPerc = 0l;// 接收错包率 + Long tx_errorPerc = 0l;// 发送错包率 + Long rx_droppedPerc = 0l;// 接收丢包率 + Long tx_droppedPerc = 0l;// 发送丢包率 + if (rxPackets2 - rxPackets1 > 0) + { + rx_errorPerc = (rxErrors2 - rxErrors1) / (rxPackets2 - rxPackets1) * 100;// 接收错包率 + rx_droppedPerc = (rxDropped2 - rxDropped1) / (rxPackets2 - rxPackets1) + * 100;// 接收丢包率 + } + if (txPackets2 - txPackets1 > 0) + { + tx_errorPerc = (txErrors2 - txErrors1) / (txPackets2 - txPackets1) * 100;// 发送错包率 + tx_droppedPerc = (txDropped2 - txDropped1) / (txPackets2 - txPackets1) + * 100;// 发送丢包率 + } + + StringBuffer sb = new StringBuffer(); + sb.append(name);// 网卡名称 + sb.append(SEPARATOR); + sb.append(rxPackets2);// 接收的总包裹数 + sb.append(SEPARATOR); + sb.append(txPackets2);// 发送的总包裹数 + sb.append(SEPARATOR); + sb.append(rxBytes2);// 接收到的总字节数 + sb.append(SEPARATOR); + sb.append(txBytes2);// 发送到的总字节数 + sb.append(SEPARATOR); + sb.append(rxErrors2);// 接收到的错误包数 + sb.append(SEPARATOR); + sb.append(txErrors2);// 发送到的错误包数 + sb.append(SEPARATOR); + sb.append(rxDropped2);// 接收时丢弃的包数 + sb.append(SEPARATOR); + sb.append(txDropped2);// 发送时丢弃的包数 + sb.append(SEPARATOR); + sb.append(speed);// 带宽:Mbps + sb.append(SEPARATOR); + sb.append(rx_bps);// bps 输入:Mbps + sb.append(SEPARATOR); + sb.append(tx_bps);// bps 输出:Mbps + sb.append(SEPARATOR); + sb.append(rx_pps);// pps 输入:每秒接收包数 + sb.append(SEPARATOR); + sb.append(tx_pps);// pps 输出:每秒发送包数 + sb.append(SEPARATOR); + sb.append(rx_errorPerc);// 接收错包率 + sb.append(SEPARATOR); + sb.append(tx_errorPerc);// 发送错包率 + sb.append(SEPARATOR); + sb.append(rx_droppedPerc);// 接收丢包率 + sb.append(SEPARATOR); + sb.append(tx_droppedPerc);// 发送丢包率 + detectInfo.getDetailDatas().add(sb.toString()); + +// sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+name + " 带宽" + speed + "Mbps, 输入" + rx_bps + "bps、" + rx_pps +// + "pps, 输出" + tx_bps + "bps、" + tx_pps + "pps; "); + sb2.append(Contants.DETEC_STATE_INFO_FORMATE_POINT+name + " i18n_client.SystemInfo.netSpeed_n81i" + speed + "Mbps, i18n_client.SystemInfo.input_n81i" + rx_bps + "bps、" + rx_pps + + "pps, Output" + tx_bps + "bps、" + tx_pps + "pps; "); + } +// sb2.insert(0, ethernetCnt + "个逻辑网卡: "); + sb2.insert(0, ethernetCnt + "i18n_client.SystemInfo.insert_n81i: "); + detectInfo.setDescInfo(sb2.toString()); + logger.debug("testNetDataList----" + sb2); + } + + } catch (SigarException e) + { + logger.error("Obtaining network information abnormity", e); + return null; + } + return detectInfo; + } + + public DetectInfo testSystemDate() + { + DetectInfo detectInfo = new DetectInfo(); + try + { + String sysDateStr = getServerSystemDate(); + if (sysDateStr != null) + { + long sysDate = Long.parseLong(sysDateStr);// 服务器系统时间 + long localDate = System.currentTimeMillis();// 客户机系统时间 + long timeDelay = Math.abs(DateUtil.getMinutesFromBeginToEnd(sysDate, localDate)); + + detectInfo.getDetailDatas().add(sysDate + SEPARATOR + localDate + SEPARATOR + + timeDelay); + detectInfo.setDescInfo("server:" + + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(sysDate)) + + " agent:" + + DateUtil + .getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(localDate))); + } else + { +// detectInfo.setDescInfo("获取DataController系统时间失败"); + detectInfo.setDescInfo("i18n_client.SystemInfo.getSysTimeErr_n81i"); + } + + } catch (Exception e) + { + logger.error("Getting the time anomaly of the system", e); + return null; + } + return detectInfo; + } + + /* + * 获取服务端系统时间 + */ + private static String getServerSystemDate() + { + String date = null; + try + { + Future<?> future = Common.service.submit(new SSLClient( + Thread.currentThread().getName(), CommonSocket.REQ_SERVER_SYSTEMDATE, null)); + String msg = (String) future.get(); + if (Contants.isSucessByResult(msg)) + { + date = Contants.getDescByResult(msg); + } + } catch (Exception e) + { + logger.error("Getting the time exception of the server system:" + Utils.printExceptionStack(e)); + date = null; + } + + return date; + } + + public DetectInfo testProcessInfo(String pidFile, final String procPath, String procSearchKey, + boolean isStart) + { + DetectInfo detectInfo = new DetectInfo(); + try + { + Object[] objArr = ProcessUtil.checkPidAndGetPid(pidFile, procSearchKey); + int isExistFlag = Integer.parseInt(objArr[0].toString()); + String pidInfo = objArr[1].toString(); + + if (isStart && isExistFlag == 0) + {// Agent启动且进程不存在,启动 + logger.info("进程“" + procPath + "”不存在,正在启动……"); + // -------------------启动进程开始 + final String threadName = Thread.currentThread().getName(); + Future future = Common.service.submit(new Runnable() + { + + @Override + public void run() + { + thread = Thread.currentThread(); + Thread.currentThread().setName(threadName); + try + { + ProcessUtil.runExec(procPath, null, null, null); + } catch (IOException e) + { + logger.error(e); + } + } + + }); + // ----获取最大等待时间(单位秒) + long delay = 3 * 60;// 3分钟 + // ----超过一定时间,终止执行线程,返回结果超时 + try + { + future.get(delay, TimeUnit.SECONDS); + } catch (TimeoutException e) + { + if (thread != null && thread.isAlive()) + { + thread.stop(); + logger.debug(procPath + "---testProcessInfo Timeout stop thread--" + + thread.isAlive()); + } + future.cancel(true); + logger.info("执行“" + procPath + "”, 超时"); + } + // -------------------启动进程结束 + // -------------------检查PID + objArr = ProcessUtil.checkPidAndGetPid(pidFile, procSearchKey); + isExistFlag = Integer.parseInt(objArr[0].toString()); + pidInfo = objArr[1].toString(); + if (isExistFlag != 0) + { + logger.info("进程“" + procPath + "”启动成功"); + } else + { + logger.info("进程“" + procPath + "”启动失败"); + } + } + logger.debug("testProcessInfo pidInfo --> " + pidInfo); + if(isExistFlag == 0){ + StringBuffer sb = new StringBuffer(); + //sb.append(CpuPerc.format(procCpu.getTotal() * 1.0 / cpuTotal));// 进程的CPU使用率 + sb.append(SEPARATOR); + //sb.append(doubleFormat((memUse * 1.0 / sigar.getMem().getTotal()) * 100, 1) + "%");// 进程的内存使用率 + sb.append(SEPARATOR); + //sb.append(procCpu.getStartTime());// 进程的启动时间 + sb.append(SEPARATOR); + sb.append("NO");// 进程状态 + sb.append(SEPARATOR); + //sb.append(state.getPriority());// 进程优先级 + + int index = 0; + String[] tmp = sb.toString().split(SEPARATOR); + + detectInfo.getDetailDatas().add(sb.toString().replace("%", "")); + detectInfo.setDescInfo(pidInfo); + return detectInfo; + } + if (isExistFlag != 1) + {// 进程不存在或找到多个进程 + detectInfo.setDescInfo(pidInfo); + return detectInfo; + } else + { + long pid = Long.parseLong(pidInfo); + + Sigar sigar = new Sigar(); + // 获取进程的CPU信息 + ProcCpu procCpu = sigar.getProcCpu(pid); + long cpuTotal = 0; + Cpu[] cpuArr = sigar.getCpuList(); + for (Cpu cpu2: cpuArr) + { + cpuTotal += cpu2.getTotal(); + } + logger.debug("testProcessInfo---->cpuTotal=" + cpuTotal); + logger.debug("testProcessInfo---->cpuUse=" + procCpu.getTotal()); + + ProcState state = sigar.getProcState(pid); + + Ps ps = new Ps(); + List<String> list = ps.getInfo(sigar, pid); + String memUseStr = ""; + for (int i = 0; i < list.size(); i++) + { + switch (i) + { + // case 0 : System.out.print("--Pid=" + list.get(0)); + // break; + // case 1 : System.out.print("\tUser=" + list.get(1)); + // break; + // case 2 : System.out.print("\tStartTimes=" + + // list.get(2)); break; + // case 3 : memSizeStr= list.get(3); break; + case 4: + memUseStr = list.get(4); + break; + // case 5 : logger.debug("testProcessInfo---->MemHare=" + // + list.get(5)); break; + // case 6 : System.out.print("\tState=" + list.get(6)); + // break; + // case 7 : System.out.print("\tCpuTime=" + + // list.get(7)); break; + // case 8 : System.out.println("\tName=" + list.get(8)); + // break; + default: + break; + } + } + double memUse = Double.parseDouble(memUseStr.substring(0, memUseStr.length() - 1)); + char useUnit = memUseStr.toUpperCase().charAt(memUseStr.length() - 1); + switch (useUnit) + { + case 'K': + memUse = memUse * 1024; + break; + case 'M': + memUse = memUse * 1024 * 1024; + break; + case 'G': + memUse = memUse * 1024 * 1024 * 1024; + break; + case 'T': + memUse = memUse * 1024 * 1024 * 1024 * 1024; + break; + case 'P': + memUse = memUse * 1024 * 1024 * 1024 * 1024 * 1024; + break; + default: + break; + } + + logger.debug("testProcessInfo---->memTotal=" + sigar.getMem().getTotal() / 1024 + + "KB"); + logger.debug("testProcessInfo---->memUseStr=" + memUseStr); + logger.debug("testProcessInfo---->memUse=" + memUse); + + StringBuffer sb = new StringBuffer(); + sb.append(CpuPerc.format(procCpu.getTotal() * 1.0 / cpuTotal));// 进程的CPU使用率 + sb.append(SEPARATOR); + sb.append(doubleFormat((memUse * 1.0 / sigar.getMem().getTotal()) * 100, 1) + "%");// 进程的内存使用率 + sb.append(SEPARATOR); + sb.append(procCpu.getStartTime());// 进程的启动时间 + sb.append(SEPARATOR); + sb.append(state.getState());// 进程状态 + sb.append(SEPARATOR); + sb.append(state.getPriority());// 进程优先级 + + int index = 0; + String[] tmp = sb.toString().split(SEPARATOR); + StringBuffer sb2 = new StringBuffer(); + sb2.append("cpuUsage:" + tmp[index++]); + sb2.append(" memUsage:" + tmp[index++]); + sb2.append(" startTime:" + + DateUtil.getStingDate(DateUtil.YYYY_MM_DD_HH24_MM_SS, new Date(Long + .parseLong(tmp[index++])))); + sb2.append(" state:" + tmp[index++]); + sb2.append(" priority:" + tmp[index++]); + + detectInfo.getDetailDatas().add(sb.toString().replace("%", "")); + detectInfo.setDescInfo(sb2.toString()); + + logger.debug("testProcessInfo---->" + sb2.toString()); + + } + } catch (Exception e) + { + logger.error("Getting process information abnormity", e); + return null; + } + + return detectInfo; + } + + public DetectInfo testSystemInfo() + { + DetectInfo detectInfo = new DetectInfo(); + try + { + Sigar sigar = new Sigar(); + + StringBuffer sb = new StringBuffer(); + sb.append(sigar.getNetInfo().getHostName());// 主机名称 + sb.append(SEPARATOR); + // 操作系统和发行版本 (os.getVendorName() + " " + os.getVersion()) + // Linux: uname -r;uname -i;lsb_release -d| cut -d: -f2| cut -f2 + // Windows: ver + String operateSystem = Utils.getOperateSystem(); + sb.append(operateSystem);// 操作系统和发行版本 + sb.append(SEPARATOR); + sb.append(sigar.getCpuInfoList().length);// CPU核数 + sb.append(SEPARATOR); + sb.append(sigar.getCpuInfoList()[0].getMhz());// CPU主频 + sb.append(SEPARATOR); + String totalMem = doubleFormat(sigar.getMem().getTotal() / (1024 * 1024 * 1024.0), 2); + sb.append(totalMem);// 内存大小,单位:G + sb.append(SEPARATOR); + sb.append(doubleFormat(sigar.getSwap().getTotal() / (1024 * 1024 * 1024.0), 2));// SWAP大小,单位:G + sb.append(SEPARATOR); + + long allTotal = 0; + // **************** 以下是各分区大小 ******************* // + List<String[]> diskDatas = new ArrayList<String[]>(); + FileSystem fslist[] = sigar.getFileSystemList(); + for (int i = 0; i < fslist.length; i++) + { + FileSystem fs = fslist[i]; + try + { + FileSystemUsage usage = sigar.getFileSystemUsage(fs.getDirName()); + if (fs.getType() == 2) + {// 先取每个盘符的大小和剩余空间 + long total = usage.getTotal();// 文件系统大小, 单位:"KB" + allTotal += total;// 文件系统总大小, 单位:"KB" + // 各分区名称和大小(单位G) + diskDatas.add(new String[] { fs.getDirName(), + doubleFormat(total / (1024 * 1024.0), 2) }); + } + } catch (SigarException e) + { + if (fs.getType() == 2) + throw e; + continue; + } + } + // ---------------- 以上是各分区大小 ------------------- // + sb.append(doubleFormat(allTotal / (1024 * 1024.0), 2));// 硬盘总大小,单位:G + sb.append(SEPARATOR); + + int ethernetCnt = 0; + // **************** 以下是各网卡状态 ******************* // + List<String[]> netDatas = new ArrayList<String[]>(); + String ifNames[] = sigar.getNetInterfaceList(); + if (ifNames.length > 0) + { + String defaultGateWay = sigar.getNetInfo().getDefaultGateway(); + for (int i = 0; i < ifNames.length; i++) + { + String name = ifNames[i]; + + NetInterfaceConfig ifconfig = sigar.getNetInterfaceConfig(name); + + // *** 网卡类型:ethernet, Local Loopback(本地环回网卡) + // *** 这里只取 ethernet 网卡类型 + if ((ifconfig.getFlags() & NetFlags.IFF_LOOPBACK) > 0) + { + continue; + } + /* + * if ((ifconfig.getFlags() & NetFlags.IFF_POINTOPOINT) > 0) { + * continue; } + */ + // 2013-4-22 针对LInux,按名称过滤掉sit0,实际命令查看类型为:IPv6-in-IPv4 + if (name.equals("sit0")) + { + continue; + } + // 2013-5-23 针对Win7取到的网卡数量太多问题 + if ((ifconfig.getFlags() & NetFlags.IFF_BROADCAST) <= 0) + {// broadcast地址无效 + continue; + } + if ((ifconfig.getFlags() & NetFlags.IFF_MULTICAST) <= 0) + {// 不支持multicast + continue; + } + ethernetCnt++; + +// String state = "可用"; + String state = "Available"; + if ((ifconfig.getFlags() & NetFlags.IFF_UP) <= 0) + {// 网卡状态: 2050 网络电缆被拔出 2115 已连接上 +// state = "不可用"; + state = "Unavailable"; + } + String speed = null; + try + { + NetInterfaceStat ifstat = sigar.getNetInterfaceStat(name); + speed = ifstat.getSpeed() / (1000 * 1000) + "";// 带宽:Mbps + } catch (SigarException e) + { + speed = ""; + } + + netDatas.add(new String[] { name, // 网卡名称 + state, // 网卡状态 + speed, // 带宽 + ifconfig.getAddress(), // IP + ifconfig.getNetmask(), // 子网掩码 + defaultGateWay, // 网关 + ifconfig.getHwaddr() // Mac地址 + }); + } + } + // System.out.println(sigar.getNetInfo().getDefaultGateway()); + // ---------------- 以上是各网卡状态 ------------------- // + sb.append(ethernetCnt);// 网卡数量 + + detectInfo.getDetailDatas().add(sb.toString()); + + StringBuffer sb2 = new StringBuffer(); +// sb2.append(sigar.getNetInfo().getHostName() + ":" + operateSystem + ", " +// + sigar.getCpuInfoList().length + "核CPU, " + sigar.getCpuInfoList()[0].getMhz() +// + "MHz, " + totalMem + "GB的内存, " + doubleFormat(allTotal / (1024 * 1024.0), 2) +// + "GB的硬盘, " + ethernetCnt + "个逻辑网卡"); + sb2.append(sigar.getNetInfo().getHostName() + ":" + operateSystem + ", " + + sigar.getCpuInfoList().length + "i18n_client.SystemInfo.message.core_n81i CPU, " + sigar.getCpuInfoList()[0].getMhz() + + "MHz, " + totalMem + "i18n_client.SystemInfo.message.memery_n81i, " + doubleFormat(allTotal / (1024 * 1024.0), 2) + + "i18n_client.SystemInfo.message.disk_n81i, " + ethernetCnt + "i18n_client.SystemInfo.message.netcard_n81i"); + detectInfo.setDescInfo(sb2.toString()); + logger.debug("testSystemInfo--sb2--" + sb2.toString()); + + Map<String, List<String[]>> relatedDataMap = new HashMap<String, List<String[]>>(); + relatedDataMap.put("disk", diskDatas); + relatedDataMap.put("net", netDatas); + detectInfo.setRelatedDatas(relatedDataMap); + + } catch (Exception e) + { + logger.error("Getting the information anomaly of the system", e); + return null; + } + + return detectInfo; + } + + public static String getStartComputerTime() + { + String value = ""; + Sigar sigar = new Sigar(); + try + { + Uptime uptime = sigar.getUptime(); + Double d = new Double(uptime.getUptime()); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, -d.intValue()); + + value = cal.getTimeInMillis() + ""; + } catch (SigarException e) + { + logger.error("Getting the boot time anomaly", e); + return value; + } + + return value; + } + + private String doubleFormat(double val, int xsws) + { +// String pattern = "#."; + String pattern = "0."; + if (xsws < 1) + { + xsws = 1; + } + for (int i = 1; i <= xsws; i++) + { + pattern += "0"; + } + + String temp = new DecimalFormat(pattern).format(val); +// if (val < 1) +// { +// return "0" + temp; +// } else +// { +// return temp; +// } + return temp; + } + + /** + * 检查硬盘是否可写:在指定盘符目录下写指定字节大小的文件,写异常-不可写,正常-可写 + * + * @param fsDirName + * 盘符 + * @return + */ + private boolean checkFileSystemIsWrite(String fsDirName) + { + boolean isWrite = true; + OutputStreamWriter fos = null; + File file = new File(fsDirName + File.separator + "writetest.temp"); + logger.debug("checkFileSystemIsWrite---file path = " + file.getAbsolutePath()); + try + { + fos = new OutputStreamWriter(new FileOutputStream(file), "utf-8"); +// fos.write("测试硬盘是否可写,现在开始写入文件\n"); + fos.write("i18n_client.SystemInfo.outputTest_n81i"); + fos.flush(); + } catch (IOException e) + { + logger.error("Test whether the hard disk can be written:" + e.getMessage()); + isWrite = false; + } finally + { + if (fos != null) + { + try + { + fos.close(); + } catch (IOException e) + { + } + } + } + if (file.exists()) + {// 不管是否写异常都将删除文件 + file.delete(); + logger.debug("checkFileSystemIsWrite---delete file = " + file.getAbsolutePath()); + } + return isWrite; + } + + public SystemInfo() + { + } + +} diff --git a/src/com/nis/systeminfo/thread/GetInfoRun.java b/src/com/nis/systeminfo/thread/GetInfoRun.java new file mode 100644 index 0000000..17cf8a2 --- /dev/null +++ b/src/com/nis/systeminfo/thread/GetInfoRun.java @@ -0,0 +1,592 @@ +package com.nis.systeminfo.thread; + +import java.io.File; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.SysConfig; +import com.nis.nmsclient.config.DetecConfOper; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileWrUtil; +import com.nis.nmsclient.util.Utils; +import com.nis.systeminfo.model.DetectInfo; +import com.nis.systeminfo.model.SystemInfo; + +/** + * 客户端读取本机信息,并写入到.csv文件的具体实现体 + * + */ +public class GetInfoRun implements Runnable{ + Logger logger = Logger.getLogger(GetInfoRun.class); + private String name; + private SetInfo setInfo; // 当前线程读取的信息要存入的表,如CPU信息表、内存信息表等 + private Date startTime;// 服务启动时间 + private List<AlarmInfo> alarmInfos; + + private int diskUsageTime=0; + private int cpuUsageTime=0; + private String cpuUsageName=""; + private String diskUsageName=""; + + private List<String> detailDatas ; + + //暂存各告警字段连续超过告警值的次数 + //public static Map<Long, Integer> alarmTimes = new HashMap<Long, Integer>(); + + //暂存各告警信息告警状态 + //public static Map<Long, Boolean> alarmStates = new HashMap<Long, Boolean>(); + + private int alarmTimes = 0; + private boolean alarmState = false; + + private String firstPerformData=""; + + public GetInfoRun(String name, SetInfo setInfo, Date startTime, List<AlarmInfo> alarmInfos) { + super(); + this.name = name; + this.setInfo = setInfo; + this.startTime = startTime; + this.alarmInfos = alarmInfos; + //如果设置是process类型,且设置名称是nmsclient,即是自身则设置进程PID文件 + if (Contants.SYS_CHECK_TYPE_PROCESS.equalsIgnoreCase(setInfo.getCheckTypeName()) + && Contants.SYS_CHECK_TYPE_PROCESS_NMSAGENT + .equalsIgnoreCase(setInfo.getProcessIden())) { + setInfo.setProcessFile(Contants.localAgentPidFile); + } + } + + public void run() { + Thread.currentThread().setName(name); + + Date writeDate = new Date(); + int checkTimes = 0;//尝试次数 + //初始化值 + String filePath = Contants.localDataFilePath + + File.separator + + DetecConfOper.getFileName(setInfo.getCheckTypeName(), setInfo + .getProcessIden(), null) + File.separator; + String fileName = DateUtil.getStingDate(DateUtil.YYYYMMDDHH24MMSS, writeDate) + ".csv"; + // 针对进程,是NC启动还是手动启动 + boolean isAgentStart = ("0".equals(setInfo.getIsControlStart()) ? false : true); + + do { + checkTimes++; + try { + /* + * 2013-4-11 数据顺序调整如下: + * 总数据:本机IP,监测设置ID,监测类别,进程名称(监测类别设置名称),监测服务启动时间,检测时延(秒),本次检测时间,尝试次数,下次计划监测时间, + * 执行状态是否成功是否正常(用于报警:-1执行失败,0不正常,1正常),状态信息(描述信息),性能数据 + * 详细信息:details,详细信息条数(要入到对应的监测类别信息表的数据条数) + * 告警列序号,告警级别,告警值,监测具体数据信息(多列),,,, + */ + + // detailDatas存放监测具体数据信息(可能多条,如多个网卡),descInfo存放状态信息 + DetectInfo detectInfo = new SystemInfo().getDetectInfo(setInfo + .getCheckTypeName(), setInfo.getProcessFile(), setInfo + .getProcessPath(), setInfo.getProcessSearchKeyCode(), isAgentStart); + + String checkDelayTime = getCheckDelayTime(writeDate);// 检测时延 + + // ------- 数据状态(告警)和详细监测数据组织 + int totalStatus = Contants.DETECTION_STATUS_NORMAL; + int totalAlarmLevel = 99; + String totalShowNum ="";//告警序列号,取告警级别高的showNum add by jinsj for 紧急告警 + StringBuffer functionSb = new StringBuffer(); + List<String[]> detailDataList = new LinkedList<String[]>(); + if (detectInfo == null || detectInfo.getDetailDatas() == null || detectInfo.getDetailDatas().size() == 0) {// 执行失败 + totalStatus = Contants.DETECTION_STATUS_FAILURE; + // detectInfo不为空,即无具体的详细数据,有描述信息(目前是针对进程与系统时间) + if (detectInfo != null){ + // 如果是进程监测, 找不到进程或找到多个进程时,告警;如果时间差监测,获取DC系统时间失败,告警 + String alarmMsg = detectInfo.getDescInfo(); + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), 1, Contants.DETECTION_STATUS_FAILURE, alarmMsg); + } + logger.info("预设监测 setId: " + this.setInfo.getId() + " > " + + this.setInfo.getCheckTypeName() + "_" + setInfo.getProcessIden() + ",获取数据失败"); + }else if(!StringUtils.isBlank(detectInfo.getDiskMsg())){ + //出现硬盘不可写或磁盘满 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), 0, Contants.DETECTION_STATUS_ABNORMAL, detectInfo.getDiskMsg()); + return ; + }else {// 即正常生成详细监测数据 + detailDatas = detectInfo.getDetailDatas(); + for(int i=0; i<detailDatas.size(); i++){ + String[] detailData = detailDatas.get(i).split(SystemInfo.SEPARATOR); + int index = 0; + String[] dataArr = new String[4 + detailData.length]; + // 与报警字段值比较是否状态正常 + String[] alarmArr = getAlarmState(detailData); + if (alarmArr != null && "".equals(alarmArr[0])) {// 记录的状态正常 + dataArr[index++] = "";// 告警列序号 + dataArr[index++] = "";// 告警级别 + dataArr[index++] = "";// 告警值 + } else {// 记录的状态不正常 + totalStatus = Contants.DETECTION_STATUS_ABNORMAL; + dataArr[index++] = alarmArr[0];// 告警列序号 + dataArr[index++] = alarmArr[1];// 告警级别 + dataArr[index++] = alarmArr[2];// 告警值 + + if(!"".equals(alarmArr[4]) && totalAlarmLevel > Integer.parseInt(alarmArr[4])){// 将更高的告警级别赋给总告警级别 + totalAlarmLevel = Integer.parseInt(alarmArr[4]); + totalShowNum = alarmArr[5]; + } + } + if(detailDatas.size()>1 && alarmArr[3].length()>0){ + functionSb.append("【" + detailData[0] + "】 " + alarmArr[3] + "</br>");// 组织性能数据 + }else{ + functionSb.append(alarmArr[3]);// 组织性能数据 + } + for (int j = 0; j < detailData.length; j++) {// 监测具体数据信息 + dataArr[index + j] = detailData[j]; + } + + detailDataList.add(dataArr); + } + } + if(StringUtils.isNotBlank(firstPerformData)){ + functionSb.insert(0,firstPerformData+"</br>"); + } + // ------- 主动告警 + String totalAlarmInfo = null; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL){ + // 本次数据正常,看原本的状态:若是告警状态,则发送恢复通知;若是正常状态,则不变 + if(alarmState){ + totalAlarmInfo = "【i18n_client.GetInfoRun.totalAlarmInfo1_n81i】</br>" + functionSb.toString(); + } + alarmState = false; + alarmTimes = 0; + }else if(totalStatus == Contants.DETECTION_STATUS_ABNORMAL){//状态异常 + alarmTimes ++; + if(!alarmState){// 本次数据不正常,看原本的状态:若是正常状态,则发送告警,此主动告警也只有一次,除非监测恢复正常,之后又异常 + if(setInfo!=null && "process".equalsIgnoreCase(setInfo.getCheckTypeName())) {//如果是进程监测 + totalAlarmInfo = functionSb.toString(); + }else { + totalAlarmInfo = "【i18n_client.GetInfoRun.totalAlarmInfo2_n81i】</br>" + functionSb.toString(); + } + }else if(alarmTimes == Contants.overAlarmValTimes && alarmState){//若原本的状态是告警状态,则判断是否连续几次达到告警值,次数会一直累积,知道监测恢复正常,所以如果一直异常,则也只告警一次连续4次异常 + totalAlarmInfo = "【i18n_client.GetInfoRun.totalAlarmInfo3_n81i】</br>" + functionSb.toString(); + } + alarmState = true; + } + if(totalAlarmInfo!=null){ + //2014-5-12 add:根据配置的参数,决定是否启用监测数据超过设定值时的主动告警 + Boolean activeAlarmStart = Contants.ACTIIVE_ALARM_START; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL ||//数据恢复主动告警 + (activeAlarmStart && totalStatus == Contants.DETECTION_STATUS_ABNORMAL)) {//数据异常主动告警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), totalAlarmLevel, totalStatus, totalAlarmInfo,totalShowNum); + } + } + // ------- 总监测数据组织 + int index = 0; + String[] totalData = new String[12]; + totalData[index++] = getUUID();// UUID + totalData[index++] = setInfo.getId() + "";// 监测设置ID + totalData[index++] = setInfo.getCheckTypeName();// 监测类别 + totalData[index++] = setInfo.getProcessIden();// 进程名称 + totalData[index++] = getStartClientTime();// 监测服务启动时间 + totalData[index++] = checkDelayTime;// 检测时延(秒) + totalData[index++] = writeDate.getTime() + "";// 本次检测时间 + totalData[index++] = checkTimes + "";// 尝试次数 + totalData[index++] = getNextCheckTime(writeDate);// 下次计划监测时间 + totalData[index++] = totalStatus + "";// 执行状态是否成功是否正常 + totalData[index++] = (detectInfo == null ? "" : detectInfo.getDescInfo());// 状态信息(描述信息) + totalData[index++] = StringUtils.isBlank(functionSb.toString())?detectInfo.getDescInfo():functionSb.toString();// 性能数据 + + List<String[]> dataList = new LinkedList<String[]>(); + // 总数据 + dataList.add(totalData); + // 详细信息 + dataList.add(new String[]{"details", detailDataList.size() + ""});// details(解析标识),详细信息条数 + dataList.addAll(detailDataList);// 具体的详细数据 + // 特殊数据定制(目前是针对系统信息监测systeminfo) + if (detectInfo!=null && detectInfo.getRelatedDatas() != null) { + Set<Map.Entry<String, List<String[]>>> set = detectInfo.getRelatedDatas().entrySet(); + for(Map.Entry<String, List<String[]>> entry : set){ + dataList.add(new String[]{entry.getKey(), entry.getValue().size() + ""});// 解析标识, 行数(当前解析标识指定的类型有多少条数据) + dataList.addAll(entry.getValue());// 多条数据 + } + } + + for(String[] val : dataList){ +// logger.debug(Arrays.toString(val));//i18nlog + } + + File file = new File(filePath); + if (!file.exists()) { + file.mkdirs(); + } + file = new File(filePath + fileName + ".tp"); + FileWrUtil.csvFilePrinter(file, Contants.charset, dataList); + + File file2 = new File(filePath + fileName); + file.renameTo(file2); + break; + } catch (Exception e) { + logger.error("Client write file" + fileName + "error: " + Utils.printExceptionStack(e)); + continue; + }finally{ + diskUsageTime=0; + cpuUsageTime=0; + cpuUsageName=""; + diskUsageName=""; + } + } while (checkTimes < setInfo.getCheckMaxTimes()); + + } + + /** + * 获得当前的报警设置信息,与相应字段值比较 + * 2014-5-15 update: 标识字段,标识 + */ + private String[] getAlarmState(String[] sysData){ + // strs数组数据依次为:告警序列号、告警级别、告警值、性能数据、本次最高告警级别 + String[] strs = new String[]{"", "", "", "", "",""}; + if(alarmInfos==null){ + return strs; + } + int maxAlarmLevel = 99; + String maxShowNum = "" ; + for (AlarmInfo alarm : alarmInfos) { +// logger.info("*****marker:"+alarm.getMarker()); + if (sysData.length < alarm.getShowNum()) {// 得到的数据个数和告警列数比较 + continue; + } + String data = sysData[alarm.getShowNum() - 1]; + boolean alarmFlag = false; + + /** + * 2014-5-15 add: + * 1.指定了特定的标识: + * (1).当前标识非空:不在指定标识内,则不做告警判断;在,则做告警判断 + * (2).当前标识为空:空不在指定标识内,不做告警判断 + * 2.未指定特定的标识:所有标识都进行告警判断 + */ + String marker = alarm.getMarker(); +// Integer markerShowNum = 1;//先默认取第一个 + Integer markerShowNum = alarm.getMarkerFiledShowNum(); + logger.info("告警设置:checkType|"+alarm.getCheckType()+" setInfoId|"+alarm.getSetInfoId()+" markerShowNum|"+alarm.getMarkerFiledShowNum()+" marker|"+alarm.getMarker()); + if(markerShowNum!=null && markerShowNum>0 //若未指定标识字段,则从DC传递到NC的json字符串中markerShowNum的值为0 + && StringUtils.isNotBlank(marker)) { + String markerCurVal = sysData[markerShowNum - 1];//当前条详细监测数据的标识符 + String sperator = SysConfig.getStringVal("alarm.set.marker.separator", "|"); + if(StringUtils.isNotBlank(markerCurVal)) { + if(!(sperator+marker.trim()+sperator).toLowerCase().contains((sperator+markerCurVal.trim()+sperator).toLowerCase())) {//当前标识不在指定的标识里 + continue; + } + }else { + continue; + } + } + + if ("equals".equalsIgnoreCase(alarm.getPoliceSysmbols())) {//相同 + if(data.equals(alarm.getPoliceValue())){ + alarmFlag = true; + } + } else if ("include".equalsIgnoreCase(alarm.getPoliceSysmbols())) {//包含告警值内容 + if(data.contains(alarm.getPoliceValue())){ + alarmFlag = true; + } + } else if ("exclude".equalsIgnoreCase(alarm.getPoliceSysmbols())) {//不包含告警值内容 + if(!data.contains(alarm.getPoliceValue())){ + alarmFlag = true; + } + } else { + double result = Double.parseDouble(data) - Double.parseDouble(alarm.getPoliceValue()); + if ((">".equals(alarm.getPoliceSysmbols()) && result > 0) + || ("<".equals(alarm.getPoliceSysmbols()) && result < 0) + || ("=".equals(alarm.getPoliceSysmbols()) && result == 0) + || (">=".equals(alarm.getPoliceSysmbols()) && result >= 0) + || ("<=".equals(alarm.getPoliceSysmbols()) && result <=0) ) { + alarmFlag = true; + } + } + String sysmbol = getAlarmSymbol(alarm.getPoliceSysmbols(), alarmFlag); + if(alarmFlag){ + strs[0] += alarm.getShowNum() + "|";// 告警序列号 + strs[1] += alarm.getPoliceLevel() + "|"; //告警级别 + strs[2] += alarm.getPoliceValue() + "|"; //告警值 + //性能信息 + if(setInfo!=null && "process".equalsIgnoreCase(setInfo.getCheckTypeName())) {//如果是进程监测 +// strs[3] +="进程不存在 ";//如果不加\",则只显示进程不存,少一个字符,所以在最后加空格,这样就不会少显示一个字符了 + strs[3] +="i18n_client.GetInfoRun.processNotExists_n81i ";//如果不加\",则只显示进程不存,少一个字符,所以在最后加空格,这样就不会少显示一个字符了 +// strs[3] +="进程不存在(进程PID文件:"+setInfo.getProcessFile()+",进程搜索关键字:"+setInfo.getProcessSearchKeyCode()+")"; +// }else if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "磁盘是否可写".equals(alarm.getFiledCommonts())){ + }else if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "i18n_client.GetInfoRun.isDiskWriteAble_n81i".equals(alarm.getFiledCommonts())){ + strs[3] += alarm.getFiledCommonts()+":not writable;"; + }else { +// if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "磁盘使用率(%)".equals(alarm.getFiledCommonts())){ + if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "i18n_client.GetInfoRun.diskUsed_n81i".equals(alarm.getFiledCommonts())){ + diskUsageTime ++; + if("Linux".equals(System.getProperties().getProperty("os.name"))){ + diskUsageName+=sysData[0]+","; +// firstPerformData = diskUsageTime+"个磁盘使用率超过"+alarm.getPoliceValue()+"%:"+diskUsageName; + firstPerformData = diskUsageTime+"i18n_client.GetInfoRun.warning_n81i"+alarm.getPoliceValue()+"%:"+diskUsageName; + }else{ + diskUsageName+=sysData[0].substring(0,sysData[0].length()-2)+","; +// firstPerformData = diskUsageTime+"个磁盘使用率超过"+alarm.getPoliceValue()+"%:"+diskUsageName.substring(0,diskUsageName.length()-1); + firstPerformData = diskUsageTime+"i18n_client.GetInfoRun.warning_n81i"+alarm.getPoliceValue()+"%:"+diskUsageName.substring(0,diskUsageName.length()-1); + } + } +// if(setInfo!=null && "cpu".equalsIgnoreCase(setInfo.getCheckTypeName()) && "总的使用率(%)".equals(alarm.getFiledCommonts())){ + if(setInfo!=null && "cpu".equalsIgnoreCase(setInfo.getCheckTypeName()) && "i18n_client.GetInfoRun.ZongShiYongLv_n81i".equals(alarm.getFiledCommonts())){ + cpuUsageTime ++;//超过告警值得cpu数量 + cpuUsageName+=sysData[0]+","; +// firstPerformData = cpuUsageTime+"个CPU的使用率占"+alarm.getPoliceValue()+"%:"+cpuUsageName.substring(0,cpuUsageName.length()-1); + firstPerformData = cpuUsageTime+"i18n_client.GetInfoRun.cpuShiyonglv_n81i"+alarm.getPoliceValue()+"%:"+cpuUsageName.substring(0,cpuUsageName.length()-1); + } +// strs[3] += alarm.getFiledCommonts()+":" +// + sysData[alarm.getShowNum() - 1] +// + "("+alarm.getPoliceUnit()+") " + sysmbol + "告警值" +// + alarm.getPoliceValue() +// + "("+alarm.getPoliceUnit()+") " + " 不正常;"; + strs[3] += alarm.getFiledCommonts()+":" + + sysData[alarm.getShowNum() - 1] + + "("+alarm.getPoliceUnit()+") " + sysmbol + "i18n_client.GetInfoRun.warningValue_n81i" + + alarm.getPoliceValue() + + "("+alarm.getPoliceUnit()+") " + " i18n_client.GetInfoRun.abnormal_n81i;"; + } + + //2011-09-29 添加了连续几次达到告警值后主动告警,恢复正常后发送恢复信息 + //2013-03-26 添加了告警状态控制是否立刻主动告警,如果已经告警则后期不发送告警信息。 + //alarmHandler(alarm, strs[3]); + + if (maxAlarmLevel > alarm.getPoliceLevel()) {// 保留本次最高告警级别,值越小级别越高 + maxAlarmLevel = alarm.getPoliceLevel(); + maxShowNum = alarm.getShowNum()+""; + } + + }else{ +// if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "磁盘是否可写".equals(alarm.getFiledCommonts())){ +// strs[3] += alarm.getFiledCommonts()+":可写;"; + if(setInfo!=null && "disk".equalsIgnoreCase(setInfo.getCheckTypeName()) && "i18n_client.GetInfoRun.isDiskWriteAble_n81i".equals(alarm.getFiledCommonts())){ + strs[3] += alarm.getFiledCommonts()+":i18n_client.GetInfoRun.writeAble_n81i;"; + }else{ + // 性能信息 + strs[3] += alarm.getFiledCommonts() + + sysData[alarm.getShowNum() - 1] + + alarm.getPoliceUnit() + sysmbol + "i18n_client.GetInfoRun.warningValue_n81i" + + alarm.getPoliceValue() + + alarm.getPoliceUnit() + " i18n_client.GetInfoRun.normal_n81i;"; + } + //对发送告警信息后,恢复正常的信息(为保证告警成对) + //2013-03-26 当告警恢复后发送恢复告警信息。 + //alarmRecovery(alarm, strs[3]); + + } + + }//for end + for (int i = 0; i < strs.length-1; i++) { + if (strs[i].length() > 0) { + strs[i] = strs[i].substring(0, strs[i].length() - 1); + } + } + strs[strs.length-2] = maxAlarmLevel + "";// 本次告警最高级别 + strs[strs.length-1] = maxShowNum ;// 本次告警最高级别对应的序列号showNum + return strs; + } + + private String getAlarmSymbol(String oldSymbol, boolean alarmFlag){ + String symbol = ""; + if(alarmFlag){ +// if(">".equals(oldSymbol)){ +// symbol = "大于"; +// }else if(">=".equals(oldSymbol)){ +// symbol = "超过"; +// }else if("<".equals(oldSymbol)){ +// symbol = "小于"; +// }else if("<=".equals(oldSymbol)){ +// symbol = "未超过"; +// }else if("=".equals(oldSymbol)){ +// symbol = "等于"; +// }else{ +// symbol = oldSymbol; +// } + if(">".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.gt_n81i"; + }else if(">=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.out_n81i"; + }else if("<".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.lt_n81i"; + }else if("<=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.in_n81i"; + }else if("=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.eq_n81i"; + }else{ + symbol = oldSymbol; + } + }else{ +// if(">".equals(oldSymbol)){ +// symbol = "未超过"; +// }else if(">=".equals(oldSymbol)){ +// symbol = "小于"; +// }else if("<".equals(oldSymbol)){ +// symbol = "超过"; +// }else if("<=".equals(oldSymbol)){ +// symbol = "大于"; +// }else if("=".equals(oldSymbol)){ +// symbol = "不等于"; + if(">".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.in_n81i"; + }else if(">=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.lt_n81i"; + }else if("<".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.out_n81i"; + }else if("<=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.gt_n81i"; + }else if("=".equals(oldSymbol)){ + symbol = "i18n_client.GetInfoRun.notEquels_n81i"; + }else if("equals".equalsIgnoreCase(oldSymbol)){ + symbol = "not equals"; + }else if("include".equalsIgnoreCase(oldSymbol)){ + symbol = "exclude"; + }else if("exclude".equalsIgnoreCase(oldSymbol)){ + symbol = "include"; + } + } + return symbol; + } + + /*// 判断是否主动告警 + private void alarmHandler(AlarmInfo alarm, String alarmInfo){ + // 判断告警状态是否变化,主动告警 + synchronized (alarmStates) { + boolean isAlarm = false; + if(alarmStates.containsKey(alarm.getId())){ + isAlarm = alarmStates.get(alarm.getId()); + } + if(!isAlarm){ + alarmStates.put(alarm.getId(), true); + // 报警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), + new Date(), alarm.getPoliceLevel(), + Contants.DETECTION_STATUS_ABNORMAL, alarmInfo); + logger.debug("主动告警:" + alarmInfo); + logger.debug("------id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val=-1"); + } + } + // 判断连续达到告警值的次数,达到一定次数,主动告警 + synchronized (alarmTimes) { + if(alarmTimes.containsKey(alarm.getId())){ + int alarmCnt = alarmTimes.get(alarm.getId()); + if(alarmCnt + 1 >= Contants.overAlarmValTimes){//连续几次达到告警值 + String alarmMsg = alarm.getFiledCommonts() + ", 连续" + (alarmCnt + 1) + "次达到告警值"; + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), + new Date(), alarm.getPoliceLevel(), + Contants.DETECTION_STATUS_ABNORMAL, alarmMsg); + logger.debug("主动告警:"+alarmMsg); + alarmTimes.put(alarm.getId(), -1); + + logger.debug("------id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val=-1"); + }else if(alarmCnt > -1){ + alarmTimes.put(alarm.getId(), alarmCnt + 1); + logger.debug("------id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val="+(alarmCnt + 1)); + } + }else{ + alarmTimes.put(alarm.getId(), 1); + logger.debug("---nokey---id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val=1"); + } + } + } + // 判断是否恢复正常 + private void alarmRecovery(AlarmInfo alarm, String alarmInfo){ + // 判断是否告警状态,恢复正常 + synchronized (alarmStates) { + if(alarmStates.containsKey(alarm.getId())){ + boolean isAlarm = alarmStates.get(alarm.getId()); + if(isAlarm){ + alarmStates.put(alarm.getId(), false); + // 报警状态:恢复正常 + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), + new Date(), 99, Contants.DETECTION_STATUS_NORMAL, + alarmInfo); + logger.debug(alarmInfo + ", 恢复正常"); + logger.debug("------id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val=0"); + } + } + } + // 判断是否连续几次达到告警值后主动告警,恢复正常 + synchronized (alarmTimes) { + if(alarmTimes.containsKey(alarm.getId())){ + if(alarmTimes.get(alarm.getId()) == -1){ + AlarmUtil.sendAlarmMsg(setInfo.getId(), + setInfo.getCheckTypeName(), + setInfo.getProcessIden(), new Date(), + new Date(), 99, Contants.DETECTION_STATUS_NORMAL, + alarm.getFiledCommonts() + ", 恢复正常"); + logger.debug(alarm.getFiledCommonts() + ", 恢复正常"); + } + alarmTimes.put(alarm.getId(), 0); + logger.debug("------id=" + alarm.getId() + "---Comments="+alarm.getFiledCommonts()+"---val=0"); + } + } + }*/ + + private String getUUID(){ + return Contants.AGENT_HOST_UUID + ""; //Utils.getLocalIp(); + } + // 检测时延(秒) + private String getCheckDelayTime(Date now){ + long val = System.currentTimeMillis() - now.getTime(); + return val/1000 + ""; + } + // 下一次检测时间 + private String getNextCheckTime(Date now){ + Calendar cal = Calendar.getInstance(); + cal.setTime(now); + cal.add(Calendar.MINUTE, setInfo.getCheckGap().intValue()); + return cal.getTimeInMillis() + ""; + } + // 服务监控开始时间 + private String getStartClientTime(){ + return this.startTime.getTime() + ""; + } + // 开机时间 + private String getStartComputerTime(){ + return SystemInfo.getStartComputerTime(); + } + + public SetInfo getSetInfo() { + return setInfo; + } + + public void setSetInfo(SetInfo setInfo) { + this.setInfo = setInfo; + } + + public List<AlarmInfo> getAlarmInfos() { + return alarmInfos; + } + + public void setAlarmInfos(List<AlarmInfo> alarmInfos) { + this.alarmInfos = alarmInfos; + } + + public String getFirstPerformData() { + return firstPerformData; + } + + public void setFirstPerformData(String firstPerformData) { + this.firstPerformData = firstPerformData; + } + +} diff --git a/src/com/nis/systeminfo/thread/NewPluginResultMerge.java b/src/com/nis/systeminfo/thread/NewPluginResultMerge.java new file mode 100644 index 0000000..900e26a --- /dev/null +++ b/src/com/nis/systeminfo/thread/NewPluginResultMerge.java @@ -0,0 +1,476 @@ +package com.nis.systeminfo.thread; + +import java.io.File; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.SysConfig; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileWrUtil; + +public class NewPluginResultMerge { + + private static final Logger logger = Logger.getLogger(NewPluginResultMerge.class); + + private static final File srcRootDir = new File(Contants.localTempDataIncomingPath); + private static final File tarRootDir = new File(Contants.localDataFilePath); + + private static HashMap<Long, Boolean> historyAlarmStateMap = new HashMap<Long, Boolean>(); + private static HashMap<Long, Integer> historyAlarmTimesMap = new HashMap<Long, Integer>(); + + public void clearTmpFile(SetInfo setInfo) { + try { + String subDir = setInfo.getCheckTypeName() + "_" + setInfo.getProcessIden(); + File dir = new File(srcRootDir, subDir); + + if(!dir.exists()) { + dir.mkdirs(); // 临时目录不存在 + return; + } + + File[] results = dir.listFiles(); + for (File file : results) { + file.delete(); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + public void merge(SetInfo setInfo) { + try { + logger.debug("合并临时结果文件开始 ~~~~~~~"); + String subDir = setInfo.getCheckTypeName() + "_" + setInfo.getProcessIden(); + File dir = new File(srcRootDir, subDir); + File tarDir = new File(tarRootDir, subDir); + + /* + * 临时目录为空,当前检测未生成结果数据 + */ + if (!dir.exists() || dir.listFiles().length == 0) { + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), +// new Date(), new Date(), 1, Contants.DETECTION_STATUS_FAILURE, "监测数据未生成"); + new Date(), new Date(), 1, Contants.DETECTION_STATUS_FAILURE, "i18n_client.NewPluginResultMerge.detecateData_n81i"); + return; + } + + // 监测信息报警相关信息 + System.out.println(Common.detecAlarmInfoMap); + List<AlarmInfo> alarmInfoList = Common.getDetecAlarmInfo(setInfo.getId()); + + // 获取临时结果文件 + File srcFile = dir.listFiles()[0]; + // 从文件名获取监测时间毫秒数(YYYYMMDDhhmmss.tmp) + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, Integer.parseInt(srcFile.getName().substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(srcFile.getName().substring(4, 6)) - 1); + cal.set(Calendar.DATE, Integer.parseInt(srcFile.getName().substring(6, 8))); + cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(srcFile.getName().substring(8, 10))); + cal.set(Calendar.MINUTE, Integer.parseInt(srcFile.getName().substring(10, 12))); + cal.set(Calendar.SECOND, Integer.parseInt(srcFile.getName().substring(12, 14))); + + Long detecTime = cal.getTimeInMillis(); + Date writeDate = new Date(detecTime); // 临时文件写入时间 + + //读取临时结果文件 + List<String[]> lines = FileWrUtil.csvFileParser(srcFile, Contants.charset); + + /* 临时数据文件新格式形式 + * line1: 监测时延(秒),尝试次数,状态信息(描述信息),字段1,字段2,··· + * + * 旧格式转新格式 + */ + if(lines.size() == 1 && lines.get(0).length > 3) { + String[] data = lines.get(0); + lines.clear(); + lines.add((String[]) ArrayUtils.subarray(data, 0, 3)); + lines.add(new String[]{"details","1"}); + lines.add((String[]) ArrayUtils.subarray(data, 3, data.length)); + } + + /* + * 临时数据文件新格式形式 + * line1: 监测时延(秒),尝试次数,状态信息(描述信息) + * line2: details,具体数据条数 + * line3: 监测字段1,监测字段2,··· + * ··· ··· ··· + * + * 任务执行失败状态判断(临时文件存在时,告警并删除临时文件): + * 1、公共信息不完整;2、无具体数据信息或具体数据信息为空 + */ + boolean execFail = false; + if(lines.size() < 1 || lines.get(0).length < 3) { // 公共信息不完整 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",公共信息不完整,监测执行错误"); + execFail = true; + } + if(lines.size() < 3) { // 无具体数据信息 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",无具体数据信息,监测执行错误"); + execFail = true; + } + if(lines.size() >= 3) { // 具体数据信息为空字段 + String detailStr = Arrays.toString(lines.get(1)); + String detailReg = "^\\[details,\\s*(\\d+)\\s*\\]$"; + if(detailStr.matches(detailReg)) { + int endNum = Integer.parseInt(detailStr.replaceAll(detailReg, "$1")); // details格式校验 + if (endNum < 1) { + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息格式错误,监测执行错误"); + execFail = true; + } + for (int r = 0; r < endNum; r++) { + String[] sysData = lines.get(r + 2); + if (Arrays.toString(sysData).matches("^\\[[,|\\s]*\\]$")) { // 空字段 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息为空字段,监测执行错误"); + execFail = true; + } + } + } else { + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息格式错误,监测执行错误"); + execFail = true; + } + } + if(execFail) { + historyAlarmStateMap.put(setInfo.getId(), true); // 数据状态不正常 + srcFile.delete(); // 删除错误临时文件,并告警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), +// new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "监测数据未生成或数据格式错误"); + new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "i18n_client.NewPluginResultMerge.formatErr_n81i"); + return; + } + + + String checkDelayTime = lines.get(0)[0];// 检测时延(秒) + String checkTimes = lines.get(0)[1]; // 尝试次数 + String detectInfo = lines.get(0)[2]; // 状态信息(描述信息) + StringBuffer functionSb = new StringBuffer(); // 性能数据 + + // 执行状态,告警级别 + int totalStatus = Contants.DETECTION_STATUS_ABNORMAL; //监测信息不正常 + int totalAlarmLevel = 99; + String totalShowNum ="";//告警序列号,取告警级别高的showNum add by jinsj for 紧急告警 + if(lines.size() > 1) { + String[] detail = lines.get(1); + if("details".equalsIgnoreCase(detail[0]) && detail[1].trim().matches("\\d+")) { + int endNum = StringUtils.isBlank(detail[1])?0:Integer.parseInt(detail[1].trim()); + + if(endNum > 0) { // 详细信息条数大于0,且所有数据不超过告警值时,监测信息正常 + totalStatus = Contants.DETECTION_STATUS_NORMAL; // 监测信息正常 + + for (int r = 0; r < endNum; r++) { + String[] sysData = lines.get(r + 2); + String[] warninfos = getAlarmState(alarmInfoList, sysData); + String[] combine = new String[sysData.length + 3]; // 组合详细信息 + System.arraycopy(warninfos, 0, combine, 0, 3); + System.arraycopy(sysData, 0, combine, 3, sysData.length); + lines.set(r + 2, combine); + + if(StringUtils.isNotBlank(warninfos[4])) { + totalAlarmLevel = Integer.parseInt(warninfos[4]); + } + totalShowNum = warninfos[5]; + + if(StringUtils.isNotBlank(warninfos[0])) { + totalStatus = Contants.DETECTION_STATUS_ABNORMAL; // 监测信息不正常 + functionSb.append(warninfos[3] + "</br>"); // 组织性能数据 + } else { + if(StringUtils.isNotBlank(warninfos[3])) { + functionSb.append(warninfos[3] + "</br>"); // 组织性能数据 + } + } + } + } + } + } + + // 主动告警 + String totalAlarmInfo = null; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL){ + historyAlarmStateMap.put(setInfo.getId(), false); + historyAlarmTimesMap.put(setInfo.getId(), 0); + + // 本次数据正常,看原本的状态:若是告警状态,则发送恢复通知;若是正常状态,则不变 + if(getHistoryAlarmState(setInfo.getId())){ + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo1_n81i】</br>" + functionSb.toString(); + } + + }else if(totalStatus == Contants.DETECTION_STATUS_ABNORMAL){//状态异常 + historyAlarmStateMap.put(setInfo.getId(), true); + historyAlarmTimesMap.put(setInfo.getId(), getHistoryAlarmTimes(setInfo.getId()) + 1); + + // 本次数据不正常,看原本的状态:若是正常状态,则发送告警,此主动告警也只有一次,除非监测恢复正常,之后又异常 + if(getHistoryAlarmTimes(setInfo.getId()) == 1) {//如果是进程监测 + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo2_n81i】</br>" + functionSb.toString(); + } + if(getHistoryAlarmTimes(setInfo.getId()) == Contants.overAlarmValTimes) {//若原本的状态是告警状态,则判断是否连续几次达到告警值,次数会一直累积,知道监测恢复正常,所以如果一直异常,则也只告警一次连续4次异常 + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo3_n81i】</br>" + functionSb.toString(); + } + } + if(totalAlarmInfo!=null){ + //2014-5-12 add:根据配置的参数,决定是否启用监测数据超过设定值时的主动告警 + Boolean activeAlarmStart = Contants.ACTIIVE_ALARM_START; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL || //数据恢复主动告警 + (activeAlarmStart && totalStatus == Contants.DETECTION_STATUS_ABNORMAL)) { //数据异常主动告警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), totalAlarmLevel, totalStatus, totalAlarmInfo,totalShowNum); + } + } + + // 组织监测数据组织 + List<String[]> dataList = new LinkedList<String[]>(); + // 总数据 + String[] totalData = new String[12]; + int index = 0; + totalData[index++] = Contants.AGENT_HOST_UUID + ""; // UUID + totalData[index++] = setInfo.getId() + ""; // 监测设置ID + totalData[index++] = setInfo.getCheckTypeName(); // 监测类别 + totalData[index++] = setInfo.getProcessIden(); // 进程名称 + totalData[index++] = setInfo.getPlanCheckTime() + ""; // 监测服务启动时间 + totalData[index++] = checkDelayTime; // 检测时延(秒) + totalData[index++] = writeDate.getTime() + ""; // 本次检测时间 + totalData[index++] = checkTimes; // 尝试次数 + totalData[index++] = getNextCheckTime(writeDate, setInfo);// 下次计划监测时间 + totalData[index++] = totalStatus + "";// 执行状态是否成功是否正常 + totalData[index++] = detectInfo; // 状态信息(描述信息) + totalData[index++] = StringUtils.isBlank(functionSb.toString()) ? detectInfo : functionSb.toString();// 性能数据 + + dataList.add(totalData); + // 详细信息 + dataList.addAll(lines.subList(1, lines.size())); + + // 写入文件 + String fileName = DateUtil.getStingDate(DateUtil.YYYYMMDDHH24MMSS, writeDate) + ".csv"; + File tarFile1 = new File(tarDir, fileName + ".tp"); + FileWrUtil.csvFilePrinter(tarFile1, Contants.charset, dataList); + File tarFile2 = new File(tarDir, fileName); + if (tarFile2.exists()) + tarFile2.delete(); + tarFile1.renameTo(tarFile2); + srcFile.delete(); + + logger.info("生成监测结果文件:" + tarFile2.getParentFile().getName() + "/" + tarFile2.getName()); + + // 忽略NC停止时间内的监测周期 + // setInfo.setLastMergeDetecTime(detecTime); + setInfo.setLastMergeDetecTime(Math.max(detecTime, setInfo.getLastMergeDetecTime())); + + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + // 下一次检测时间 + private String getNextCheckTime(Date now, SetInfo setInfo) { + Calendar cal = Calendar.getInstance(); + cal.setTime(now); + cal.add(Calendar.MINUTE, setInfo.getCheckGap().intValue()); + return cal.getTimeInMillis() + ""; + } + + /** + * 获取当前行告警信息 + * @param sysData + * @return + */ + private String[] getAlarmState(List<AlarmInfo> alarmInfos, String[] sysData) { + // strs数组数据依次为:告警序列号、告警级别、告警值、性能数据、本次最高告警级别 + String[] strs = new String[] { "", "", "", "", "", "" }; + if (alarmInfos == null) { + return strs; + } + int maxAlarmLevel = 99; + String maxShowNum = ""; + for (AlarmInfo alarm : alarmInfos) { + if (sysData.length < alarm.getShowNum()) {// 得到的数据个数和告警列数比较 + continue; + } + String data = sysData[alarm.getShowNum() - 1]; + boolean alarmFlag = false; + + /** + * 2014-5-15 add: 1.指定了特定的标识: (1).当前标识非空:不在指定标识内,则不做告警判断;在,则做告警判断 + * (2).当前标识为空:空不在指定标识内,不做告警判断 2.未指定特定的标识:所有标识都进行告警判断 + */ + String marker = alarm.getMarker(); + // Integer markerShowNum = 1;//先默认取第一个 + Integer markerShowNum = alarm.getMarkerFiledShowNum(); + logger.info("告警设置:checkType|" + alarm.getCheckType() + " setInfoId|" + alarm.getSetInfoId() + + " markerShowNum|" + alarm.getMarkerFiledShowNum() + " marker|" + alarm.getMarker()); + if (markerShowNum != null && markerShowNum > 0 // 若未指定标识字段,则从DC传递到NC的json字符串中markerShowNum的值为0 + && StringUtils.isNotBlank(marker)) { + String markerCurVal = sysData[markerShowNum - 1];// 当前条详细监测数据的标识符 + String sperator = SysConfig.getStringVal("alarm.set.marker.separator", "|"); + if (StringUtils.isNotBlank(markerCurVal)) { + if (!(sperator + marker.trim() + sperator).toLowerCase().contains( + (sperator + markerCurVal.trim() + sperator).toLowerCase())) {// 当前标识不在指定的标识里 + continue; + } + } else { + continue; + } + } + + if ("equals".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 相同 + if (data.equals(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else if ("include".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 包含告警值内容 + if (data.contains(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else if ("exclude".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 不包含告警值内容 + if (!data.contains(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else { + double result = Double.parseDouble(data) + - Double.parseDouble(alarm.getPoliceValue()); + if ((">".equals(alarm.getPoliceSysmbols()) && result > 0) + || ("<".equals(alarm.getPoliceSysmbols()) && result < 0) + || ("=".equals(alarm.getPoliceSysmbols()) && result == 0) + || (">=".equals(alarm.getPoliceSysmbols()) && result >= 0) + || ("<=".equals(alarm.getPoliceSysmbols()) && result <= 0)) { + alarmFlag = true; + } + } + + String sysmbol = getAlarmSymbol(alarm.getPoliceSysmbols(), alarmFlag); + if (alarmFlag) { + strs[0] += alarm.getShowNum() + "|";// 告警序列号 + strs[1] += alarm.getPoliceLevel() + "|"; // 告警级别 + strs[2] += alarm.getPoliceValue() + "|"; // 告警值 + // 性能信息 +// strs[3] += alarm.getFiledCommonts() + ":" +// + sysData[alarm.getShowNum() - 1] + "(" +// + alarm.getPoliceUnit() + ") " + sysmbol + "告警值" +// + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() +// + ") " + "不正常;"; + strs[3] += alarm.getFiledCommonts() + ":" + + sysData[alarm.getShowNum() - 1] + "(" + + alarm.getPoliceUnit() + ") " + sysmbol + "i18n_client.NewPluginResultMerge.warningValue_n81i" + + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() + + ") " + "i18n_client.NewPluginResultMerge.abnormal_n81i;"; + } else { + // 性能信息 +// strs[3] += alarm.getFiledCommonts() + ":" +// + sysData[alarm.getShowNum() - 1] + "(" +// + alarm.getPoliceUnit() + ") " + sysmbol + "告警值" +// + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() +// + ") " + "正常;"; + strs[3] += alarm.getFiledCommonts() + ":" + + sysData[alarm.getShowNum() - 1] + "(" + + alarm.getPoliceUnit() + ") " + sysmbol + "i18n_client.NewPluginResultMerge.warningValue_n81i" + + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() + + ") " + "i18n_client.NewPluginResultMerge.normal_n81i;"; + } + + // 2011-09-29 添加了连续几次达到告警值后主动告警,恢复正常后发送恢复信息 + // 2013-03-26 添加了告警状态控制是否立刻主动告警,如果已经告警则后期不发送告警信息。 + if (maxAlarmLevel > alarm.getPoliceLevel()) {// 保留本次最高告警级别,值越小级别越高 + maxAlarmLevel = alarm.getPoliceLevel(); + maxShowNum = alarm.getShowNum() + ""; + } + + }// for end + for (int i = 0; i < strs.length - 1; i++) { + if (strs[i].length() > 0) { + strs[i] = strs[i].substring(0, strs[i].length() - 1); + } + } + strs[strs.length - 2] = maxAlarmLevel + "";// 本次告警最高级别 + strs[strs.length - 1] = maxShowNum;// 本次告警最高级别对应的序列号showNum + return strs; + } + + private String getAlarmSymbol(String oldSymbol, boolean alarmFlag) { + String symbol = ""; +// if (alarmFlag) { +// if (">".equals(oldSymbol)) { +// symbol = "大于"; +// } else if (">=".equals(oldSymbol)) { +// symbol = "超过"; +// } else if ("<".equals(oldSymbol)) { +// symbol = "小于"; +// } else if ("<=".equals(oldSymbol)) { +// symbol = "未超过"; +// } else if ("=".equals(oldSymbol)) { +// symbol = "等于"; +// } else { +// symbol = oldSymbol; +// } +// } else { +// if (">".equals(oldSymbol)) { +// symbol = "未超过"; +// } else if (">=".equals(oldSymbol)) { +// symbol = "小于"; +// } else if ("<".equals(oldSymbol)) { +// symbol = "超过"; +// } else if ("<=".equals(oldSymbol)) { +// symbol = "大于"; +// } else if ("=".equals(oldSymbol)) { +// symbol = "不等于"; +// } else if ("equals".equalsIgnoreCase(oldSymbol)) { +// symbol = "not equals"; +// } else if ("include".equalsIgnoreCase(oldSymbol)) { +// symbol = "exclude"; +// } else if ("exclude".equalsIgnoreCase(oldSymbol)) { +// symbol = "include"; +// } +// } + if (alarmFlag) { + if (">".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.gt_n81i"; + } else if (">=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.out_n81i"; + } else if ("<".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.lt_n81i"; + } else if ("<=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.in_n81i"; + } else if ("=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.eq_n81i"; + } else { + symbol = oldSymbol; + } + } else { + if (">".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.in_n81i"; + } else if (">=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.lt_n81i"; + } else if ("<".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.out_n81i"; + } else if ("<=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.gt_n81i"; + } else if ("=".equals(oldSymbol)) { + symbol = "i18n_client.GetInfoRun.notEquels_n81i"; + } else if ("equals".equalsIgnoreCase(oldSymbol)) { + symbol = "not equals"; + } else if ("include".equalsIgnoreCase(oldSymbol)) { + symbol = "exclude"; + } else if ("exclude".equalsIgnoreCase(oldSymbol)) { + symbol = "include"; + } + } + return symbol; + } + + private boolean getHistoryAlarmState(Long setInfoId) { + Boolean alarmState = historyAlarmStateMap.get(setInfoId); + return (alarmState != null && alarmState == true); + } + + private int getHistoryAlarmTimes(Long setInfoId) { + Integer alarmTimes = historyAlarmTimesMap.get(setInfoId); + return (alarmTimes != null ? alarmTimes : 0); + } +} diff --git a/src/com/nis/systeminfo/thread/PluginResultMerge.java b/src/com/nis/systeminfo/thread/PluginResultMerge.java new file mode 100644 index 0000000..9d9d245 --- /dev/null +++ b/src/com/nis/systeminfo/thread/PluginResultMerge.java @@ -0,0 +1,451 @@ +package com.nis.systeminfo.thread; + +import java.io.File; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.nis.nmsclient.NmsClient; +import com.nis.nmsclient.common.Common; +import com.nis.nmsclient.common.Contants; +import com.nis.nmsclient.common.SysConfig; +import com.nis.nmsclient.model.AlarmInfo; +import com.nis.nmsclient.model.SetInfo; +import com.nis.nmsclient.thread.alarm.AlarmUtil; +import com.nis.nmsclient.util.DateUtil; +import com.nis.nmsclient.util.FileWrUtil; + +/** + * 临时文件的合并过程替换为NewPluginResultMerge + */ +@Deprecated +public class PluginResultMerge { + + private static final Logger logger = Logger.getLogger(PluginResultMerge.class); + + private static final File srcRootDir = new File(Contants.localTempDataIncomingPath); + private static final File tarRootDir = new File(Contants.localDataFilePath); + + private static HashMap<Long, Boolean> historyAlarmStateMap = new HashMap<Long, Boolean>(); + private static HashMap<Long, Integer> historyAlarmTimesMap = new HashMap<Long, Integer>(); + + public void merge() { + try { + logger.debug("合并临时结果文件开始 ~~~~~~~"); + + Collection<SetInfo> setInfos = Common.getPluginDetecSetInfos(); + System.out.println(setInfos.size()); + for (SetInfo setInfo : setInfos) { + String subDir = setInfo.getCheckTypeName() + "_" + setInfo.getProcessIden(); + File dir = new File(srcRootDir, subDir); + File tarDir = new File(tarRootDir, subDir); + + if (!dir.exists() || dir.listFiles().length == 0) { + continue; + } + + // 监测信息报警相关信息 + System.out.println(Common.detecAlarmInfoMap); + List<AlarmInfo> alarmInfoList = Common.getDetecAlarmInfo(setInfo.getId()); + + // 相邻的连个结果文件超过两个监测周期时,该时间段内出现未生成数据结果的周期 + Long period = setInfo.getCheckGap() * (60 * 1000); // millisecond + Long detecTimeout = period * 2; + + File[] results = dir.listFiles(); + Arrays.sort(results, new Comparator<File>() { // 同一类结果文件按按时间先后排序 + public int compare(File f1, File f2) { + return f1.getName().compareTo(f2.getName()); + } + }); + + for (File srcFile : results) { + // 从文件名获取监测时间毫秒数(YYYYMMDDhhmmss.tmp) + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, Integer.parseInt(srcFile.getName().substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(srcFile.getName().substring(4, 6)) - 1); + cal.set(Calendar.DATE, Integer.parseInt(srcFile.getName().substring(6, 8))); + cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(srcFile.getName().substring(8, 10))); + cal.set(Calendar.MINUTE, Integer.parseInt(srcFile.getName().substring(10, 12))); + cal.set(Calendar.SECOND, Integer.parseInt(srcFile.getName().substring(12, 14))); + + Long detecTime = cal.getTimeInMillis(); + Date writeDate = new Date(detecTime); // 临时文件写入时间 + + while (setInfo.getLastMergeDetecTime() + detecTimeout < detecTime) { + // 存在未生成数据结果的监测周期(每个周期记录一次) + historyAlarmStateMap.put(setInfo.getId(), true); // 数据状态不正常 + + // 未生成监测数据(主动报警AlarmThread连续四次未生成监测数据报警) + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), +// new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "监测数据未生成"); + new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "i18n_client.NewPluginResultMerge.detecateData_n81i"); + + // TODO 存在主动告警发送延时问题,可能会有多次告警连续发送 + setInfo.setLastMergeDetecTime(setInfo.getLastMergeDetecTime() + period); + } + + //读取临时结果文件 + List<String[]> lines = FileWrUtil.csvFileParser(srcFile, Contants.charset); + + /* + * 任务执行失败状态判断(临时文件存在时,告警并删除临时文件): + * 1、公共信息不完整;2、无具体数据信息或具体数据信息为空 + */ + boolean execFail = false; + if(lines.size() < 1 || lines.get(0).length < 3) { // 公共信息不完整 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",公共信息不完整,监测执行错误"); + execFail = true; + } + if(lines.size() < 3) { // 无具体数据信息 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",无具体数据信息,监测执行错误"); + execFail = true; + } + if(lines.size() >= 3) { // 具体数据信息为空字段 + String detailStr = Arrays.toString(lines.get(1)); + String detailReg = "^\\[details, (\\d+)\\]$"; + if(detailStr.matches(detailReg)) { + int endNum = Integer.parseInt(detailStr.replaceAll(detailReg, "$1")); // details格式校验 + if (endNum < 1) { + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息格式错误,监测执行错误"); + execFail = true; + } + for (int r = 0; r < endNum; r++) { + String[] sysData = lines.get(r + 2); + if (Arrays.toString(sysData).matches("^\\[[,|\\s]*\\]$")) { // 空字段 + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息为空字段,监测执行错误"); + execFail = true; + } + } + } else { + logger.info("预设监测 setId: " + setInfo.getId() + " > " + srcFile.getName() + ",具体数据信息格式错误,监测执行错误"); + execFail = true; + } + } + if(execFail) { + historyAlarmStateMap.put(setInfo.getId(), true); // 数据状态不正常 + srcFile.delete(); // 删除错误临时文件,并告警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), +// new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "监测数据未生成"); + new Date(detecTime), new Date(detecTime), 1, Contants.DETECTION_STATUS_FAILURE, "i18n_client.NewPluginResultMerge.detecateData_n81i"); + continue; + } + + + String checkDelayTime = lines.get(0)[0];// 检测时延(秒) + String checkTimes = lines.get(0)[1]; // 尝试次数 + String detectInfo = lines.get(0)[2]; // 状态信息(描述信息) + StringBuffer functionSb = new StringBuffer(); // 性能数据 + + // 执行状态,告警级别 + int totalStatus = Contants.DETECTION_STATUS_ABNORMAL; //监测信息不正常 + int totalAlarmLevel = 99; + String totalShowNum ="";//告警序列号,取告警级别高的showNum add by jinsj for 紧急告警 + if(lines.size() > 1) { + String[] detail = lines.get(1); + if("details".equalsIgnoreCase(detail[0]) && detail[1].trim().matches("\\d+")) { + int endNum = StringUtils.isBlank(detail[1])?0:Integer.parseInt(detail[1].trim()); + + if(endNum > 0) { // 详细信息条数大于0,且所有数据不超过告警值时,监测信息正常 + totalStatus = Contants.DETECTION_STATUS_NORMAL; // 监测信息正常 + + for (int r = 0; r < endNum; r++) { + String[] sysData = lines.get(r + 2); + String[] warninfos = getAlarmState(alarmInfoList, sysData); + String[] combine = new String[sysData.length + 3]; // 组合详细信息 + System.arraycopy(warninfos, 0, combine, 0, 3); + System.arraycopy(sysData, 0, combine, 3, sysData.length); + lines.set(r + 2, combine); + + totalAlarmLevel = Integer.parseInt(warninfos[4]); + totalShowNum = warninfos[5]; + + if(StringUtils.isNotBlank(warninfos[0])) { + totalStatus = Contants.DETECTION_STATUS_ABNORMAL; // 监测信息不正常 + functionSb.append(warninfos[3] + "</br>"); // 组织性能数据 + } else { + if(StringUtils.isNotBlank(warninfos[3])) { + functionSb.append(warninfos[3] + "</br>"); // 组织性能数据 + } + } + } + } + } + } + + // 主动告警 + String totalAlarmInfo = null; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL){ + historyAlarmStateMap.put(setInfo.getId(), false); + historyAlarmTimesMap.put(setInfo.getId(), 0); + + // 本次数据正常,看原本的状态:若是告警状态,则发送恢复通知;若是正常状态,则不变 + if(getHistoryAlarmState(setInfo.getId())){ + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo1_n81i】</br>" + functionSb.toString(); + } + + }else if(totalStatus == Contants.DETECTION_STATUS_ABNORMAL){//状态异常 + historyAlarmStateMap.put(setInfo.getId(), true); + historyAlarmTimesMap.put(setInfo.getId(), getHistoryAlarmTimes(setInfo.getId()) + 1); + + // 本次数据不正常,看原本的状态:若是正常状态,则发送告警,此主动告警也只有一次,除非监测恢复正常,之后又异常 + if(getHistoryAlarmTimes(setInfo.getId()) == 1) {//如果是进程监测 + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo2_n81i】</br>" + functionSb.toString(); + } + if(getHistoryAlarmTimes(setInfo.getId()) == Contants.overAlarmValTimes) {//若原本的状态是告警状态,则判断是否连续几次达到告警值,次数会一直累积,知道监测恢复正常,所以如果一直异常,则也只告警一次连续4次异常 + totalAlarmInfo = "【i18n_client.NewPluginResultMerge.totalAlarmInfo3_n81i】</br>" + functionSb.toString(); + } + } + if(totalAlarmInfo!=null){ + //2014-5-12 add:根据配置的参数,决定是否启用监测数据超过设定值时的主动告警 + Boolean activeAlarmStart = Contants.ACTIIVE_ALARM_START; + if(totalStatus == Contants.DETECTION_STATUS_NORMAL || //数据恢复主动告警 + (activeAlarmStart && totalStatus == Contants.DETECTION_STATUS_ABNORMAL)) { //数据异常主动告警 + AlarmUtil.sendAlarmMsg(setInfo.getId(), setInfo.getCheckTypeName(), setInfo.getProcessIden(), + new Date(), new Date(), totalAlarmLevel, totalStatus, totalAlarmInfo,totalShowNum); + } + } + + // 组织监测数据组织 + List<String[]> dataList = new LinkedList<String[]>(); + // 总数据 + String[] totalData = new String[12]; + int index = 0; + totalData[index++] = Contants.AGENT_HOST_UUID + ""; // UUID + totalData[index++] = setInfo.getId() + ""; // 监测设置ID + totalData[index++] = setInfo.getCheckTypeName(); // 监测类别 + totalData[index++] = setInfo.getProcessIden(); // 进程名称 + totalData[index++] = setInfo.getPlanCheckTime() + ""; // 监测服务启动时间 + totalData[index++] = checkDelayTime; // 检测时延(秒) + totalData[index++] = writeDate.getTime() + ""; // 本次检测时间 + totalData[index++] = checkTimes; // 尝试次数 + totalData[index++] = getNextCheckTime(writeDate, setInfo);// 下次计划监测时间 + totalData[index++] = totalStatus + "";// 执行状态是否成功是否正常 + totalData[index++] = detectInfo; // 状态信息(描述信息) + totalData[index++] = StringUtils.isBlank(functionSb.toString()) ? detectInfo : functionSb.toString();// 性能数据 + + dataList.add(totalData); + // 详细信息 + dataList.addAll(lines.subList(1, lines.size())); + + // 写入文件 + String fileName = DateUtil.getStingDate(DateUtil.YYYYMMDDHH24MMSS, writeDate) + ".csv"; + File tarFile1 = new File(tarDir, fileName + ".tp"); + FileWrUtil.csvFilePrinter(tarFile1, Contants.charset, dataList); + File tarFile2 = new File(tarDir, fileName); + if (tarFile2.exists()) + tarFile2.delete(); + tarFile1.renameTo(tarFile2); + srcFile.delete(); + + logger.info("生成监测结果文件:" + tarFile2.getParentFile().getName() + "/" + tarFile2.getName()); + + // 忽略NC停止时间内的监测周期 + // setInfo.setLastMergeDetecTime(detecTime); + setInfo.setLastMergeDetecTime(Math.max(detecTime, setInfo.getLastMergeDetecTime())); + } + + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + logger.debug("合并临时结果文件结束 ~~~~~~~"); + } + } + + // 下一次检测时间 + private String getNextCheckTime(Date now, SetInfo setInfo) { + Calendar cal = Calendar.getInstance(); + cal.setTime(now); + cal.add(Calendar.MINUTE, setInfo.getCheckGap().intValue()); + return cal.getTimeInMillis() + ""; + } + + public static void main(String[] args) { + NmsClient client = new NmsClient(); + client.initDetecConfig(); + for (SetInfo setInfo : client.setInfos) { + Common.putPluginDetecSetInfo(setInfo.getId(), setInfo); + } + new PluginResultMerge().merge(); + } + + /** + * 获取当前行告警信息 + * @param sysData + * @return + */ + private String[] getAlarmState(List<AlarmInfo> alarmInfos, String[] sysData) { + // strs数组数据依次为:告警序列号、告警级别、告警值、性能数据、本次最高告警级别 + String[] strs = new String[] { "", "", "", "", "", "" }; + if (alarmInfos == null) { + return strs; + } + int maxAlarmLevel = 99; + String maxShowNum = ""; + for (AlarmInfo alarm : alarmInfos) { + if (sysData.length < alarm.getShowNum()) {// 得到的数据个数和告警列数比较 + continue; + } + String data = sysData[alarm.getShowNum() - 1]; + boolean alarmFlag = false; + + /** + * 2014-5-15 add: 1.指定了特定的标识: (1).当前标识非空:不在指定标识内,则不做告警判断;在,则做告警判断 + * (2).当前标识为空:空不在指定标识内,不做告警判断 2.未指定特定的标识:所有标识都进行告警判断 + */ + String marker = alarm.getMarker(); + // Integer markerShowNum = 1;//先默认取第一个 + Integer markerShowNum = alarm.getMarkerFiledShowNum(); + logger.info("告警设置:checkType|" + alarm.getCheckType() + " setInfoId|" + alarm.getSetInfoId() + + " markerShowNum|" + alarm.getMarkerFiledShowNum() + " marker|" + alarm.getMarker()); + if (markerShowNum != null && markerShowNum > 0 // 若未指定标识字段,则从DC传递到NC的json字符串中markerShowNum的值为0 + && StringUtils.isNotBlank(marker)) { + String markerCurVal = sysData[markerShowNum - 1];// 当前条详细监测数据的标识符 + String sperator = SysConfig.getStringVal("alarm.set.marker.separator", "|"); + if (StringUtils.isNotBlank(markerCurVal)) { + if (!(sperator + marker.trim() + sperator).toLowerCase().contains( + (sperator + markerCurVal.trim() + sperator).toLowerCase())) {// 当前标识不在指定的标识里 + continue; + } + } else { + continue; + } + } + + if ("equals".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 相同 + if (data.equals(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else if ("include".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 包含告警值内容 + if (data.contains(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else if ("exclude".equalsIgnoreCase(alarm.getPoliceSysmbols())) {// 不包含告警值内容 + if (!data.contains(alarm.getPoliceValue())) { + alarmFlag = true; + } + } else { + double result = Double.parseDouble(data) + - Double.parseDouble(alarm.getPoliceValue()); + if ((">".equals(alarm.getPoliceSysmbols()) && result > 0) + || ("<".equals(alarm.getPoliceSysmbols()) && result < 0) + || ("=".equals(alarm.getPoliceSysmbols()) && result == 0) + || (">=".equals(alarm.getPoliceSysmbols()) && result >= 0) + || ("<=".equals(alarm.getPoliceSysmbols()) && result <= 0)) { + alarmFlag = true; + } + } + + String sysmbol = getAlarmSymbol(alarm.getPoliceSysmbols(), alarmFlag); + if (alarmFlag) { + strs[0] += alarm.getShowNum() + "|";// 告警序列号 + strs[1] += alarm.getPoliceLevel() + "|"; // 告警级别 + strs[2] += alarm.getPoliceValue() + "|"; // 告警值 + // 性能信息 +// strs[3] += alarm.getFiledCommonts() + ":" +// + sysData[alarm.getShowNum() - 1] + "(" +// + alarm.getPoliceUnit() + ") " + sysmbol + "告警值" +// + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() +// + ") " + "不正常;"; + strs[3] += alarm.getFiledCommonts() + ":" + + sysData[alarm.getShowNum() - 1] + "(" + + alarm.getPoliceUnit() + ") " + sysmbol + "i18n_client.NewPluginResultMerge.warningValue_n81i" + + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() + + ") " + "i18n_client.NewPluginResultMerge.abnormal_n81i;"; + } else { + // 性能信息 + strs[3] += alarm.getFiledCommonts() + ":" + + sysData[alarm.getShowNum() - 1] + "(" + + alarm.getPoliceUnit() + ") " + sysmbol + "i18n_client.NewPluginResultMerge.warningValue_n81i" + + alarm.getPoliceValue() + "(" + alarm.getPoliceUnit() + + ") " + "i18n_client.NewPluginResultMerge.normal_n81i;"; + } + + // 2011-09-29 添加了连续几次达到告警值后主动告警,恢复正常后发送恢复信息 + // 2013-03-26 添加了告警状态控制是否立刻主动告警,如果已经告警则后期不发送告警信息。 + if (maxAlarmLevel > alarm.getPoliceLevel()) {// 保留本次最高告警级别,值越小级别越高 + maxAlarmLevel = alarm.getPoliceLevel(); + maxShowNum = alarm.getShowNum() + ""; + } + + }// for end + for (int i = 0; i < strs.length - 1; i++) { + if (strs[i].length() > 0) { + strs[i] = strs[i].substring(0, strs[i].length() - 1); + } + } + strs[strs.length - 2] = maxAlarmLevel + "";// 本次告警最高级别 + strs[strs.length - 1] = maxShowNum;// 本次告警最高级别对应的序列号showNum + return strs; + } + + private String getAlarmSymbol(String oldSymbol, boolean alarmFlag) { + String symbol = ""; + if (alarmFlag) { +// if (">".equals(oldSymbol)) { +// symbol = "大于"; +// } else if (">=".equals(oldSymbol)) { +// symbol = "超过"; +// } else if ("<".equals(oldSymbol)) { +// symbol = "小于"; +// } else if ("<=".equals(oldSymbol)) { +// symbol = "未超过"; +// } else if ("=".equals(oldSymbol)) { +// symbol = "等于"; +// } else { +// symbol = oldSymbol; +// } + if (">".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.gt_n81i"; + } else if (">=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.out_n81i"; + } else if ("<".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.lt_n81i"; + } else if ("<=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.in_n81i"; + } else if ("=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.eq_n81i"; + } else { + symbol = oldSymbol; + } + } else { + if (">".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.in_n81i"; + } else if (">=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.lt_n81i"; + } else if ("<".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.out_n81i"; + } else if ("<=".equals(oldSymbol)) { + symbol = "i18n_client.NewPluginResultMerge.gt_n81i"; + } else if ("=".equals(oldSymbol)) { + symbol = "i18n_client.GetInfoRun.notEquels_n81i"; + } else if ("equals".equalsIgnoreCase(oldSymbol)) { + symbol = "not equals"; + } else if ("include".equalsIgnoreCase(oldSymbol)) { + symbol = "exclude"; + } else if ("exclude".equalsIgnoreCase(oldSymbol)) { + symbol = "include"; + } + } + return symbol; + } + + private boolean getHistoryAlarmState(Long setInfoId) { + Boolean alarmState = historyAlarmStateMap.get(setInfoId); + return (alarmState != null && alarmState == true); + } + + private int getHistoryAlarmTimes(Long setInfoId) { + Integer alarmTimes = historyAlarmTimesMap.get(setInfoId); + return (alarmTimes != null ? alarmTimes : 0); + } +} |
