package com.yahoo.dtf.stats; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import com.yahoo.dtf.recorder.Attribute; import com.yahoo.dtf.actions.Action; import com.yahoo.dtf.exception.DTFException; import com.yahoo.dtf.exception.QueryException; import com.yahoo.dtf.exception.StatsException; import com.yahoo.dtf.query.Cursor; import com.yahoo.dtf.recorder.Event; import com.yahoo.dtf.util.NumberUtil; public class GenCalcStats { protected final static String SEP_STR = "."; protected final static String AVG_VAL = "avg_val"; protected final static String TOT_VAL = "tot_val"; protected final static String MAX_VAL = "max_val"; protected final static String MIN_VAL = "min_val"; protected final static String MIN_DUR = "min_dur"; protected final static String MAX_DUR = "max_dur"; protected final static String AVG_DUR = "avg_dur"; protected final static String TOT_DUR = "tot_dur"; protected final static String CSV_DUR = "csv_dur"; protected final static String TOT_OCC = "tot_occ"; protected final static String AVG_OCC = "avg_occ"; protected final static String MAX_INT = "max_int"; protected final static String MIN_INT = "min_int"; protected final static String TOT_INT = "tot_int"; protected final static String AVG_INT = "avg_int"; private DecimalFormat formatter = new DecimalFormat("#0.000"); private EventCalc ec = new EventCalc(); private String monitor = null; public GenCalcStats(String monitor) { ec = new EventCalc(); this.monitor = monitor; } protected String formatNumber(String num) { return formatter.format(num); } protected String formatNumber(double num) { return formatter.format(num); } protected String formatNumber(long num) { return formatter.format(num); } public void updateStats(HashMap<String,String> result) { Iterator<Entry<String, String>> fields = result.entrySet().iterator(); while (fields.hasNext()) { Entry<String, String> entry = fields.next(); String fullpropname = entry.getKey(); String keyprop = fullpropname.substring(fullpropname.lastIndexOf(".") + 1, fullpropname.length()); String propValue = entry.getValue(); if (monitor != null && monitor.equals(keyprop)) ec.addMonitorProp(keyprop, propValue); // if its a number then lets handle it // max long is 19 digits long if ( NumberUtil.isLong(propValue) ) { long value = new Long(propValue).longValue(); if (keyprop.equals("start")) { ec.setStart(value); continue; } if (keyprop.equals("stop")) { ec.setStop(value); continue; } ec.addProp(keyprop, value); } } } /* * If we allow more than a single thread to execute in parallel in here we * could lose data because the updates to setStart,setStop, etc. would be * lost */ public synchronized void updateStats(Event event) throws DTFException { ArrayList<Action> attribs = event.children(); ec.setStart(event.getStart()); ec.setStop(event.getStop()); for (int i = 0; i < attribs.size(); i++) { Attribute attribute = (Attribute) attribs.get(i); String keyprop = attribute.getName(); String propValue = attribute.getValue(); if (monitor != null && monitor.equals(keyprop)) ec.addMonitorProp(keyprop, propValue); // if its a number then lets handle it // max long is 19 digits long if ( NumberUtil.isLong(propValue) ) { long value = new Long(propValue).longValue(); ec.addProp(keyprop, value); } } } public LinkedHashMap<String, String> getCurrentStats() { double duration = ec.duration() / 1000.0f; HashMap<String, PropCalc> props = ec.getProps(); Iterator<Entry<String,PropCalc>> propKeys = props.entrySet().iterator(); LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>(); while ( propKeys.hasNext() ) { Entry<String, PropCalc> entry = propKeys.next(); String pkey = entry.getKey(); PropCalc prop = entry.getValue(); double average = (double) prop.getAccValue() / duration; properties.put(pkey + SEP_STR + AVG_VAL, formatNumber(average)); properties.put(pkey + SEP_STR + TOT_VAL, formatNumber(prop.getAccValue())); properties.put(pkey + SEP_STR + MAX_VAL, formatNumber(prop.getMaxValue())); properties.put(pkey + SEP_STR + MIN_VAL, formatNumber(prop.getMinValue())); } properties.put(MIN_DUR, ""+ec.getMinDuration()); properties.put(MAX_DUR, ""+ec.getMaxDuration()); properties.put(AVG_DUR, ""+ec.getAvgDuration()); properties.put(TOT_DUR, ""+ec.duration()); properties.put(TOT_OCC, ""+ec.getOccurences()); properties.put(AVG_OCC, formatNumber(ec.getOccurences() / duration)); if (monitor != null) { Iterator<String> keys = ec.getMonitorKeys(); StringBuffer states = new StringBuffer(); while (keys.hasNext()) { String key = keys.next(); states.append(key + (keys.hasNext() ? "," : "") ); long minInterval = ec.getMinInterval(key); long maxInterval = ec.getMaxInterval(key); long totInterval = ec.getTotInterval(key); long avgInterval = ec.getAvgInterval(key); String aux = monitor + "_" + key + SEP_STR; properties.put(aux + MIN_INT, formatNumber(minInterval)); properties.put(aux + MAX_INT, formatNumber(maxInterval)); properties.put(aux + TOT_INT, formatNumber(totInterval)); properties.put(aux + AVG_INT, formatNumber(avgInterval)); } properties.put(monitor + "_states", states.toString()); } Map<Long, Long> aux = ec.getDurations(); Iterator<Entry<Long,Long>> durations = aux.entrySet().iterator(); StringBuffer data = new StringBuffer(); while ( durations.hasNext() ) { Entry<Long, Long> entry = durations.next(); data.append(entry.getKey() + "," + entry.getValue() + "\n"); } properties.put(CSV_DUR, data.toString()); return properties; } public LinkedHashMap<String, String> calcStats(Cursor cursor) throws StatsException { try { HashMap<String,String> result = null; while ((result = cursor.next(false)) != null) { updateStats(result); } } catch (QueryException e) { throw new StatsException("Error with cursor.", e); } return getCurrentStats(); } }