计算差值和计算速率的简单实现

对于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);
	}
}

猜你喜欢

转载自blog.csdn.net/zhigang0529/article/details/83183272