对于SNMPv1/v2定义的32位计数器(Counter32)是一个非负整数,其值只能增加,但不能减少,达到最大值232-1后回零,主要用于计算收到的分组数或字节数等场合。注意,Counter32没有定义初始值,所以单个Counter32的数据是没有意义的。
对Counter32类型的数据,要做差值计算。
针对某设备的指标A,按周期采集的数据,要用本次值减去上次的值做差值。需要有个缓存上次值的缓存队列,记录采集实例的具体到指标的每次采集值。做本次值减去上次的值计算时,要先判断本次值是否大于或等于上次值,否则本次数据丢弃不处理,但要缓存本次值。
速率计算就是在本次值 – 上次值后,还要再除以两次值的采集时间差的秒数,计算公式:
(本次值 – 上次值) / (本次值采集时间 – 上次值采集时间)
另外,有的采集oid还需要和其它oid的值一起做计算,才能得到有效数据,就要做公式计算,通过一个或多个OID的采集值,计算出新的指标值。
举例某实例的一个指标的值,在3次采集时间中的值是增大的,
值200, 采集时间1536517079401 (2018/9/10 2:17:59)
值210, 采集时间1536520679042 (2018/9/10 3:17:59)
值218, 采集时间1536524279089 (2018/9/10 4:17:59)
计算差值
3:17:59 的差值计算210 – 200,得到结果值是10
4:17:59 的差值计算218 – 210,得到结果值是8
计算速率
3:17:59 的速率计算(210 – 200)/( (1536520679042 – 1536517079401)/1000),得到结果值是0.00277
4:17:59 的差值计算(218 – 210)/( (1536524279089 – 1536520679042)/1000),得到结果值是0.00222
下面通过代码,来做一个通用的类,能把每次采的数据送到这个类中, 直接计算差值或速率。
上代码
import java.util.HashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* @Title: 计算差值和速率
*/
public class PMDataCache {
private Logger log = LogManager.getLogger(PMDataCache.class);
//缓存值不存在时返回这个值
public static final double NULL = -99.99d;
//单实例
private static PMDataCache _instance = null;
/** 计算差值 */
private static HashMap<String, Double> dataMap = null;
/** 计算速率 */
private static HashMap<String, KeyAnyValue> speedMap = null;
private PMDataCache() {
dataMap = new HashMap<String, Double>();
speedMap = new HashMap<String, KeyAnyValue>();
}
/**
* 获得单实例
* @return
*/
public static PMDataCache getInstance() {
if (_instance == null) {
_instance = new PMDataCache();
}
return _instance;
}
/**
* 取上次值
* @param key
* @return
*/
public double getLastData(String key) {
if(dataMap.containsKey(key))
return (Double) dataMap.get(key);
return -1.0d;
}
/**
* 保存上次值
* @param key
* @param value
*/
public void putLastData(String key, double value) {
dataMap.put(key, value);
}
/**
* 保存上次值
* @param key
* @param value
*/
public void putLastData(String key, String value) {
putLastData(key, Double.parseDouble(value));
}
/**
* 当前值-上次值
* @param key
* @param currentValue
* @return
*/
public String delta(String key, double currentValue) {
double deltaValue = 0.0d;
double lastValue = getLastData(key);
try {
if(lastValue != -1.0d) {
if(currentValue >= lastValue) {
deltaValue = currentValue - lastValue;
log.debug("Delta compute " + currentValue + " - " + lastValue + " = " + deltaValue);
} else {
log.warn(key + " " + currentValue + " < " + lastValue);
return null;
}
} else
return null;
} catch(Exception e) {
log.error("Delta compute error " + key, e);
} finally {
putLastData(key, currentValue);
}
return deltaValue + "";
}
/**
* 计算差值
* @param key
* @param value
* @return 如果上次缓存值不存在, 返回-99.99d;
*/
public double getDeltaValue(String key, String value) {
double dValue = 0.0d;
String sValue = delta(key, Double.parseDouble(value));
if(sValue != null)
dValue = Double.parseDouble(sValue);
else
return PMDataCache.NULL;
return dValue;
}
/**
* 保存上次值
* @param key
* @param value 值
* @param dcTime 数据采集时间
*/
public void putLastDataAndTime(String key, String value, long dcTime) {
KeyAnyValue kav = new KeyAnyValue();
kav.setKey(value);
kav.setValue(new Long(dcTime));
speedMap.put(key, kav);
}
/**
* 取上次值
* @param key
* @return
*/
public KeyAnyValue getLastDataAndTime(String key) {
if(speedMap.containsKey(key))
return (KeyAnyValue) speedMap.get(key);
return null;
}
/**
* 速率
* @param key
* @param currentValue
* @param currentTime
* @return
*/
public String speed(String key, double currentValue, long currentTime) {
double speedValue = 0.0d;
KeyAnyValue last = getLastDataAndTime(key);
try {
if(last != null) {
long lastTime = ((Long)last.getValue()).longValue(); //上次采集时间
double lastValue = Double.parseDouble(last.getKey()); //上次值
if(currentValue >= lastValue && currentTime > lastTime) {
double secTime = (currentTime - lastTime) / 1000;
speedValue = (currentValue - lastValue) / secTime;
log.debug("Speed compute (" + currentValue + " - " + lastValue + ")/" + secTime + " = " + speedValue);
} else {
log.warn(key + " " + currentValue + " < " + lastValue);
return null;
}
} else
return null;
} catch(Exception e) {
log.error("Speed compute error " + key, e);
} finally {
putLastDataAndTime(key, currentValue + "", currentTime);
}
return speedValue + "";
}
/**
* 计算速率
* @param key
* @param value
* @param currentTime
* @return 如果上次缓存值不存在, 返回-99.99d;
*/
public double getSpeedValue(String key, String value, long currentTime) {
double dValue = 0.0d;
String sValue = speed(key, Double.parseDouble(value), currentTime);
if(sValue != null)
dValue = Double.parseDouble(sValue);
else
return PMDataCache.NULL;
return dValue;
}
class KeyAnyValue implements java.io.Serializable{
public String key;
public Object value;
public String getKey() {
return this.key;
}
public Object getValue() {
return this.value;
}
public void setKey(String key) {
this.key = key;
}
public void setValue(Object value) {
this.value = value;
}
public String toString() {
return key + " | " + value.toString();
}
}
}
测试类
/**
* @Title:计算差值和计算速率的测试
*/
public class PMDataCacheTest {
/**
* 计算差值
* @param key
* @param value
* @return 如果上次缓存值不存在, 返回-99.99d;
*/
private double getDeltaValue(String key, String value) {
double dValue = 0.0d;
String sValue = PMDataCache.getInstance().delta(key,
Double.parseDouble(value));
if (sValue != null)
dValue = Double.parseDouble(sValue);
else
return PMDataCache.NULL;
return dValue;
}
/**
* 计算速率
* @param key
* @param value
* @param currentTime
* @return 如果上次缓存值不存在, 返回-99.99d;
*/
private double getSpeedValue(String key, String value, long currentTime) {
double dValue = 0.0d;
String sValue = PMDataCache.getInstance().speed(key,
Double.parseDouble(value), currentTime);
if (sValue != null)
dValue = Double.parseDouble(sValue);
else
return PMDataCache.NULL;
return dValue;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
PMDataCacheTest test = new PMDataCacheTest();
String key = "NE-1";
String readIO = "1000";
//取网元设备NE-1的readIO差值
double dReadIODelta = test.getDeltaValue(key + "_readIO", readIO);
//取网元设备NE-1的readIO速率
long thisTime = System.currentTimeMillis();
double dReadIOSpeed = test.getSpeedValue(key + "_readIO", readIO, thisTime);
}
}