
cn.patterncat.metrics.network.ProcNetReader Maven / Gradle / Ivy
package cn.patterncat.metrics.network;
import cn.patterncat.metrics.ExtraMetricsProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.system.ApplicationPid;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by patterncat on 2017-01-27.
*/
public class ProcNetReader {
private static final Logger LOGGER = LoggerFactory.getLogger(ProcNetReader.class);
private String pid = new ApplicationPid().toString();
//provide the global basic stat of sockets(tcp/udp inuse, tw count and tcp/udp memory)
//inuse通过snmp的CurrEstab,memory通过netstat的TCPMemoryPressures来替代
private String SOCKSTAT_FILE = "/proc/net/sockstat";
//provide Ip、Icmp、IcmpMsg、Tcp、Udp、UdpLite info
private String SNMP_FILE = "/proc/net/snmp";
//provide TcpExt、IpExt more detail info
private String STAT_FILE = "/proc/" + pid + "/net/netstat";
protected ConcurrentHashMap statData = new ConcurrentHashMap<>();
private final ExtraMetricsProperties extraMetricsProperties;
public ProcNetReader(ExtraMetricsProperties extraMetricsProperties) {
this.extraMetricsProperties = extraMetricsProperties;
}
public Map query() {
updateProcNetData();
return statData;
}
public void updateProcNetData() {
if(extraMetricsProperties.isSnmpEnabled()){
queryFile(SNMP_FILE, extraMetricsProperties.getSnmpCollectPrefixes());
}
if(extraMetricsProperties.isNetstatEnabled()){
queryFile(STAT_FILE, extraMetricsProperties.getNetstatCollectPrefixes());
}
}
protected void queryFile(String file, List prefixes) {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(file));
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] keys = line.trim().split("\\s+");
line = bufferedReader.readLine();
String[] values = line.trim().split("\\s+");
if (!prefixes.contains(keys[0].trim())) {
continue;
}
for (int i = 0; i < keys.length; i++) {
Double value = parseStringNumber(values[i], Double.NaN);
statData.put(keys[i], value);
}
}
} catch (Exception e) {
//ignore
LOGGER.debug(e.getMessage(), e);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception e) {
//ignore
LOGGER.debug(e.getMessage(), e);
}
}
}
}
/**
* A compact and exception free number parser.
*
If the string can be parsed as the specified type, it return the default value
*
* @param toParse The string to parse
* @param defaultVal A default value to use it the string can't be parsed
* @return An Number object using the same type than the default value.
*/
@SuppressWarnings("unchecked")
public static NumberClass parseStringNumber(String toParse, NumberClass defaultVal) {
if (toParse == null || "".equals(toParse))
return defaultVal;
try {
Class clazz = (Class) defaultVal.getClass();
Constructor c = clazz.getConstructor(String.class);
return c.newInstance(toParse);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalArgumentException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return defaultVal;
}
}