/*******************************************************************************
* ===========================================================
* Ankush : Big Data Cluster Management Solution
* ===========================================================
*
* (C) Copyright 2014, by Impetus Technologies
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL v3) as
* published by the Free Software Foundation;
*
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
******************************************************************************/
/**
*
*/
package com.impetus.ankush.agent.sigar;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.NetInterfaceStat;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.ProcCpu;
import org.hyperic.sigar.ProcMem;
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.Who;
import com.impetus.ankush.agent.utils.AgentLogger;
import com.impetus.ankush.agent.utils.CommandExecutor;
import com.impetus.ankush.agent.utils.Result;
/**
* The Class SigarNodeInfoProvider.
*
* @author Hokam Chauhan
*/
public class SigarNodeInfoProvider {
/** The log. */
private static final AgentLogger LOGGER = new AgentLogger(
SigarNodeInfoProvider.class);
/** The Constant SLEEP. */
public static final char SLEEP = 'S';
/** The Constant RUN. */
public static final char RUN = 'R';
/** The Constant STOP. */
public static final char STOP = 'T';
/** The Constant ZOMBIE. */
public static final char ZOMBIE = 'Z';
/** The Constant IDLE. */
public static final char IDLE = 'D';
/** The Constant HUNDRED. */
public static final int HUNDRED = 100;
/** The Constant NUMBER_1024. */
public static final int NUMBER_1024 = 1024;
/** The sigar. */
private Sigar sigar;
private DecimalFormat dFormatter = new DecimalFormat("##.##");
/**
* Instantiates a new sigar node info provider.
*/
public SigarNodeInfoProvider() {
sigar = new Sigar();
}
/**
* Method getNodeMemoryInfo.
*
* @return Map<Object,Object>
*/
public Map<Object, Object> getNodeMemoryInfo() {
Map<Object, Object> nodeMemoryInfo = new HashMap<Object, Object>();
Mem mem = null;
try {
mem = sigar.getMem();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
nodeMemoryInfo.put("total", mem.getTotal());
nodeMemoryInfo.put("free", mem.getFree());
nodeMemoryInfo.put("used", mem.getUsed());
nodeMemoryInfo.put("actualFree", mem.getActualFree());
nodeMemoryInfo.put("actualUsed", mem.getActualUsed());
nodeMemoryInfo.put("freePercentage", mem.getFreePercent());
nodeMemoryInfo.put("usedPercentage", mem.getUsedPercent());
return nodeMemoryInfo;
}
/**
* Method getNodeCpuInfos.
*
* @return List<Map<Object,Object>>
*/
public List<Map<Object, Object>> getNodeCpuInfos() {
List<Map<Object, Object>> nodeCpuInfoList = new ArrayList<Map<Object, Object>>();
Cpu[] cpuList = null;
CpuInfo[] cpuInfoList = null;
Map<Object, Object> nodeCpuInfo = null;
try {
cpuList = sigar.getCpuList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
try {
cpuInfoList = sigar.getCpuInfoList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
for (int i = 0; i < cpuList.length; i++) {
nodeCpuInfo = new HashMap<Object, Object>();
nodeCpuInfo.put("vendor", cpuInfoList[i].getVendor());
nodeCpuInfo.put("clock", cpuInfoList[i].getMhz());
nodeCpuInfo.put("model", cpuInfoList[i].getModel());
nodeCpuInfo.put("cores", cpuInfoList[i].getTotalCores());
nodeCpuInfo.put("coresPerSocket",
cpuInfoList[i].getCoresPerSocket());
nodeCpuInfo.put("sockets", cpuInfoList[i].getTotalSockets());
nodeCpuInfo.put("cacheSize", cpuInfoList[i].getCacheSize());
nodeCpuInfo.put("idleTime", cpuList[i].getIdle());
nodeCpuInfo.put("interruptHandlingTime", cpuList[i].getIrq());
nodeCpuInfo.put("niceTime", cpuList[i].getNice());
nodeCpuInfo.put("softRequestTime", cpuList[i].getSoftIrq());
nodeCpuInfo.put("kernelTime", cpuList[i].getSys());
nodeCpuInfo.put("cpuTime", cpuList[i].getTotal());
nodeCpuInfo.put("userTime", cpuList[i].getUser());
nodeCpuInfo.put("waitTime", cpuList[i].getWait());
nodeCpuInfoList.add(nodeCpuInfo);
}
return nodeCpuInfoList;
}
/**
* Method getNodeSwapInfo.
*
* @return Map<Object,Object>
*/
public Map<Object, Object> getNodeSwapInfo() {
Swap swap = null;
Map<Object, Object> nodeSwapInfo = new HashMap<Object, Object>();
try {
swap = sigar.getSwap();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
nodeSwapInfo.put("freeSystemSwap", swap.getFree());
nodeSwapInfo.put("pageIn", swap.getPageIn());
nodeSwapInfo.put("pageOut", swap.getPageOut());
nodeSwapInfo.put("totalSystemSwap", swap.getTotal());
nodeSwapInfo.put("usedSystemSwap", swap.getUsed());
return nodeSwapInfo;
}
/**
* Method getNodeNetworkInfos.
*
* @return List<Map<Object,Object>>
*/
public List<Map<Object, Object>> getNodeNetworkInfos() {
List<Map<Object, Object>> nodeNetworkInfoList = new ArrayList<Map<Object, Object>>();
Map<Object, Object> nodeNetworkInfo = null;
String[] netInterfaceList = null;
NetInterfaceStat netInterfaceStat = null;
try {
netInterfaceList = sigar.getNetInterfaceList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
for (String netInterface : netInterfaceList) {
try {
netInterfaceStat = sigar.getNetInterfaceStat(netInterface);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
nodeNetworkInfo = new HashMap<Object, Object>();
nodeNetworkInfo.put("interfaceName", netInterface);
nodeNetworkInfo.put("receivedBytes", netInterfaceStat.getRxBytes());
nodeNetworkInfo.put("receivedDropped",
netInterfaceStat.getRxDropped());
nodeNetworkInfo.put("receivedErrors",
netInterfaceStat.getRxErrors());
nodeNetworkInfo.put("receivedFrame", netInterfaceStat.getRxFrame());
nodeNetworkInfo.put("receivedOverruns",
netInterfaceStat.getRxOverruns());
nodeNetworkInfo.put("receivedPackets",
netInterfaceStat.getRxPackets());
nodeNetworkInfo.put("transmittedBytes",
netInterfaceStat.getTxBytes());
nodeNetworkInfo.put("transmittedDropped",
netInterfaceStat.getTxDropped());
nodeNetworkInfo.put("transmittedErrors",
netInterfaceStat.getTxErrors());
nodeNetworkInfo.put("transmittedCarrier",
netInterfaceStat.getTxCarrier());
nodeNetworkInfo.put("transmittedCollision",
netInterfaceStat.getTxCollisions());
nodeNetworkInfo.put("transmittedOverruns",
netInterfaceStat.getTxOverruns());
nodeNetworkInfo.put("transmittedPackets",
netInterfaceStat.getTxPackets());
nodeNetworkInfo.put("speed", netInterfaceStat.getSpeed());
nodeNetworkInfoList.add(nodeNetworkInfo);
}
return nodeNetworkInfoList;
}
/**
* Method getNodeOSInfo.
*
* @return Map<Object,Object>
*/
public Map<Object, Object> getNodeOSInfo() {
OperatingSystem os = null;
Map<Object, Object> nodeOSInfo = new HashMap<Object, Object>();
os = OperatingSystem.getInstance();
nodeOSInfo.put("arch", os.getArch());
nodeOSInfo.put("cpuEndian", os.getCpuEndian());
nodeOSInfo.put("dataModel", os.getDataModel());
nodeOSInfo.put("description", os.getDescription());
nodeOSInfo.put("machineName", os.getMachine());
nodeOSInfo.put("patchlevel", os.getPatchLevel());
nodeOSInfo.put("systemVersion", os.getVersion());
nodeOSInfo.put("vendor", os.getVendor());
nodeOSInfo.put("vendorCodeName", os.getVendorCodeName());
nodeOSInfo.put("vendorVersion", os.getVendorVersion());
return nodeOSInfo;
}
/**
* Method getNodeUpTimeInfo.
*
* @return Map<Object,Object>
*/
public Map<Object, Object> getNodeUpTimeInfo() {
Uptime upTime = null;
Who[] who = null;
Map<Object, Object> nodeUpTimeInfo = new HashMap<Object, Object>();
double[] loadAverage = { 0, 0, 0 };
try {
upTime = sigar.getUptime();
nodeUpTimeInfo.put("upTime", upTime.getUptime());
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
try {
who = sigar.getWhoList();
String loggedUsers;
List<String> userList = new ArrayList<String>();
for (Who w : who) {
userList.add(w.getUser());
}
loggedUsers = getDelimitedValues(userList, ",");
nodeUpTimeInfo.put("loggedUsers", loggedUsers);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
try {
loadAverage = sigar.getLoadAverage();
nodeUpTimeInfo.put("loadAverage1", loadAverage[0]);
nodeUpTimeInfo.put("loadAverage2", loadAverage[1]);
nodeUpTimeInfo.put("loadAverage3", loadAverage[2]);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
nodeUpTimeInfo.put("cpuUsage", getCpuUsage());
return nodeUpTimeInfo;
}
/**
* Gets the cpu usage.
*
* @return the cpu usage
*/
private Object getCpuUsage() {
try {
// cpu percentage object.
CpuPerc per = sigar.getCpuPerc();
// getting the string value of percentage.
String p = String.valueOf(per.getCombined() * 100.0);
// getting index of the .
int ix = p.indexOf('.') + 1;
// getting only one digit after .
return p.substring(0, ix) + p.substring(ix, ix + 1);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
return null;
}
/**
* Method getDelimitedValues.
*
* @param list
* List
* @param delimiter
* String
* @return String
*/
private static String getDelimitedValues(List list, String delimiter) {
StringBuffer sBuf = new StringBuffer();
int size = list.size();
for (int index = 0; index < size; ++index) {
if (index != 0) {
sBuf.append(delimiter);
}
sBuf.append(list.get(index));
}
return sBuf.toString();
}
/**
* Method getNodeDiskInfos.
*
* @return List<Map<Object,Object>>
*/
public List<Map<Object, Object>> getNodeDiskInfos() {
List<Map<Object, Object>> nodeInfoList = new ArrayList<Map<Object, Object>>();
Map<Object, Object> nodeDiskInfo;
FileSystem[] fileSystemList = null;
FileSystemUsage fileSystemUsage = null;
try {
fileSystemList = sigar.getFileSystemList();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
for (FileSystem fileSystem : fileSystemList) {
nodeDiskInfo = new HashMap<Object, Object>();
nodeDiskInfo.put("deviceName", fileSystem.getDevName());
nodeDiskInfo.put("dirName", fileSystem.getDirName());
nodeDiskInfo.put("fileSystemEnvironmentType",
fileSystem.getTypeName());
nodeDiskInfo.put("fileSystemType", fileSystem.getSysTypeName());
nodeDiskInfo.put("partitionFlags", fileSystem.getFlags());
nodeDiskInfo.put("options", fileSystem.getOptions());
fileSystemUsage = new FileSystemUsage();
try {
fileSystemUsage.gather(sigar, fileSystem.getDirName());
} catch (SigarException e) {
LOGGER.error(e.getMessage(), e);
}
nodeDiskInfo.put("availableMemory", fileSystemUsage.getAvail());
nodeDiskInfo.put("freeMemory", fileSystemUsage.getFree());
nodeDiskInfo.put("totalMemory", fileSystemUsage.getTotal());
nodeDiskInfo.put("usedMemory", fileSystemUsage.getUsed());
nodeDiskInfo.put("readBytes", fileSystemUsage.getDiskReadBytes());
nodeDiskInfo.put("reads", fileSystemUsage.getDiskReads());
nodeDiskInfo.put("writeBytes", fileSystemUsage.getDiskWriteBytes());
nodeDiskInfo.put("writes", fileSystemUsage.getDiskWrites());
nodeInfoList.add(nodeDiskInfo);
}
return nodeInfoList;
}
/**
* Method getProcessState.
*
* @param state
* char
* @return String
*/
private static String getProcessState(char state) {
String strState;
switch (state) {
case SLEEP:
strState = "Sleeping";
break;
case RUN:
strState = "Running";
break;
case STOP:
strState = "Terminated";
break;
case ZOMBIE:
strState = "Zombie";
break;
case IDLE:
strState = "Idle";
break;
default:
strState = "Unknown";
break;
}
return strState;
}
/**
* Method getNodeProcessInfo.
*
* @return List<Map<Object,Object>>
*/
private List<Map<Object, Object>> getNodeProcessInfo() {
List<Map<Object, Object>> nodeProcessInfos = new ArrayList<Map<Object, Object>>();
try {
long[] procIdList = sigar.getProcList();
Mem mem = sigar.getMem();
float totalMem = mem.getTotal() / NUMBER_1024;
Result rs = new Result();
for (long pid : procIdList) {
try{
ProcCpu procCpu = sigar.getProcCpu(pid);
ProcMem procMem = sigar.getProcMem(pid);
ProcState procState = sigar.getProcState(pid);
String pName = procState.getName();
double cpuUsage = 0;
try {
// executing jps command.
String command = "ps -p " + pid + " -o%cpu";
rs = CommandExecutor.executeCommand(command);
if (rs.getExitVal() == 0) {
String usage = rs.getOutput().split("\n")[1].trim();
cpuUsage = Double.parseDouble(usage);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
cpuUsage = procCpu.getPercent();
}
double residentMemory = procMem.getResident() / NUMBER_1024;
double sharedMemory = procMem.getShare() / NUMBER_1024;
double virtualMemory = procMem.getSize() / NUMBER_1024;
long threads = procState.getThreads();
String state = getProcessState(procState.getState());
double memUsage = (residentMemory / totalMem) * HUNDRED;
Date startSince = new Date(procCpu.getStartTime());
Map<Object, Object> nodeProcInfoStatus = new HashMap<Object, Object>();
nodeProcInfoStatus.put("pid", pid);
nodeProcInfoStatus.put("pName", pName);
nodeProcInfoStatus.put("memUsage", dFormatter.format(memUsage));
nodeProcInfoStatus.put("cpuUsage", cpuUsage);
nodeProcInfoStatus.put("residentMemory", residentMemory);
nodeProcInfoStatus.put("sharedMemory", sharedMemory);
nodeProcInfoStatus.put("virtualMemory", virtualMemory);
nodeProcInfoStatus.put("threads", threads);
nodeProcInfoStatus.put("startSince", startSince);
nodeProcInfoStatus.put("state", state);
nodeProcInfoStatus.put("ioUsage", 0);
nodeProcessInfos.add(nodeProcInfoStatus);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
return nodeProcessInfos;
}
/**
* Method getNodeProcessCPUInfos.
*
* @return List<Map<Object,Object>>
*/
public List<Map<Object, Object>> getSortedListByItem(final String item) {
List<Map<Object, Object>> nodeProcessInfos = getNodeProcessInfo();
try {
Collections.sort(nodeProcessInfos,
new Comparator<Map<Object, Object>>() {
@Override
public int compare(Map<Object, Object> arg1,
Map<Object, Object> arg2) {
Double d2 = Double.parseDouble(arg2.get(item)
.toString());
Double d1 = Double.parseDouble(arg1.get(item)
.toString());
return Double.compare(d2, d1);
}
});
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
return nodeProcessInfos;
}
/**
* Get the Map of all metrics information.
*
* @param topProcessCount
* the top process count
* @return the node info
*/
public Map<String, Object> getNodeInfo(int topProcessCount) {
Map<String, Object> infoMap = new HashMap<String, Object>();
infoMap.put("memory", Collections.singletonList(getNodeMemoryInfo()));
infoMap.put("cpu", getNodeCpuInfos());
infoMap.put("disk", getNodeDiskInfos());
infoMap.put("network", getNodeNetworkInfos());
infoMap.put("swap", Collections.singletonList(getNodeSwapInfo()));
infoMap.put("os", Collections.singletonList(getNodeOSInfo()));
infoMap.put("uptime", Collections.singletonList(getNodeUpTimeInfo()));
infoMap.put("processCPU",
getSortedListByItem("cpuUsage").subList(0, topProcessCount));
infoMap.put("processMemory",
getSortedListByItem("memUsage").subList(0, topProcessCount));
infoMap.put("processIO",
getSortedListByItem("ioUsage").subList(0, topProcessCount));
return infoMap;
}
}