
net.anotheria.moskito.webui.accumulators.api.AccumulatorAPIImpl Maven / Gradle / Ivy
package net.anotheria.moskito.webui.accumulators.api;
import net.anotheria.anoplass.api.APIException;
import net.anotheria.moskito.core.accumulation.AccumulatedValue;
import net.anotheria.moskito.core.accumulation.Accumulator;
import net.anotheria.moskito.core.accumulation.AccumulatorDefinition;
import net.anotheria.moskito.core.accumulation.AccumulatorRepository;
import net.anotheria.moskito.core.config.MoskitoConfigurationHolder;
import net.anotheria.moskito.core.stats.TimeUnit;
import net.anotheria.moskito.webui.accumulators.bean.AccumulatedValuesBean;
import net.anotheria.moskito.webui.shared.api.AbstractMoskitoAPIImpl;
import net.anotheria.util.NumberUtils;
import net.anotheria.util.sorter.DummySortType;
import net.anotheria.util.sorter.SortType;
import net.anotheria.util.sorter.StaticQuickSorter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Implementation of the AccumulatorAPI.
*
* @author lrosenberg
* @since 13.02.13 18:13
*/
public class AccumulatorAPIImpl extends AbstractMoskitoAPIImpl implements AccumulatorAPI {
/**
* This constant is used to put different timestamp in context.
*/
private static final long MINUTE = 1000L*60;
/**
* Object for caching of the sort types.
*/
private static final SortType SORT_TYPE = new DummySortType();
@Override
public AccumulatorDefinitionAO createAccumulator(AccumulatorPO po) throws APIException{
if (po.getName() == null || po.getName().equals(""))
throw new APIException("Can't create accumulator without a name.");
AccumulatorDefinition ad = new AccumulatorDefinition();
ad.setName(po.getName());
ad.setProducerName(po.getProducerId());
ad.setStatName(po.getStatName());
ad.setValueName(po.getValueName());
ad.setIntervalName(po.getInterval());
if (po.getUnit()==null || po.getUnit().length()==0)
ad.setTimeUnit(TimeUnit.MILLISECONDS); //set to default
else
ad.setTimeUnit(TimeUnit.fromString(po.getUnit()));
Accumulator acc = AccumulatorRepository.getInstance().createAccumulator(ad);
return getAccumulatorDefinition(acc.getId());
}
@Override
public void removeAccumulator(String id) throws APIException {
AccumulatorRepository.getInstance().removeById(id);
}
@Override public AccumulatorAO getAccumulator(String id) throws APIException{
return new AccumulatorAO(AccumulatorRepository.getInstance().getById(id));
}
@Override public AccumulatorAO getAccumulatorByName(String name) throws APIException{
Accumulator acc = AccumulatorRepository.getInstance().getByName(name);
if (acc==null)
throw new IllegalArgumentException("Attempt to access non existing accumulator with name: '" +name+ '\'');
return new AccumulatorAO(acc);
}
public AccumulatorDefinitionAO getAccumulatorDefinition(String accId) throws APIException{
Accumulator a = AccumulatorRepository.getInstance().getById(accId);
AccumulatorDefinitionAO bean = new AccumulatorDefinitionAO();
bean.setName(a.getName());
bean.setPath(a.getDefinition().describe());
bean.setId(a.getId());
List values = a.getValues();
if (values!=null && values.size()>0){
bean.setNumberOfValues(values.size());
bean.setLastValueTimestamp(values.get(values.size()-1).getISO8601Timestamp());
}else{
bean.setNumberOfValues(0);
bean.setLastValueTimestamp("none");
}
return bean;
}
@Override
public AccumulatedSingleGraphAO getAccumulatorGraphData(String id) throws APIException {
Accumulator accumulator = AccumulatorRepository.getInstance().getById(id);
AccumulatedSingleGraphAO singleGraphDataBean = new AccumulatedSingleGraphAO(accumulator.getName());
singleGraphDataBean.setData(new AccumulatorAO(accumulator).getValues());
singleGraphDataBean.setColor(MoskitoConfigurationHolder.getConfiguration().getAccumulatorsConfig().getAccumulatorColor(accumulator.getName()));
return singleGraphDataBean;
}
@Override
public AccumulatedSingleGraphAO getAccumulatorGraphDataByName(String name) throws APIException {
return getAccumulatorGraphData(AccumulatorRepository.getInstance().getByName(name).getId());
}
@Override
public List getAccumulatorDefinitions() throws APIException {
List accumulators = AccumulatorRepository.getInstance().getAccumulators();
List ret = new ArrayList<>(accumulators.size());
for (Accumulator a : accumulators){
AccumulatorDefinitionAO bean = new AccumulatorDefinitionAO();
bean.setName(a.getName());
bean.setPath(a.getDefinition().describe());
bean.setId(a.getId());
bean.setMaxNumberOfValues(a.getDefinition().getMaxAmountOfAccumulatedItems());
List values = a.getValues();
if (values!=null && values.size()>0){
bean.setNumberOfValues(values.size());
bean.setLastValueTimestamp(values.get(values.size()-1).getISO8601Timestamp());
}else{
bean.setNumberOfValues(0);
bean.setLastValueTimestamp("none");
}
ret.add(bean);
}
ret = StaticQuickSorter.sort(ret, SORT_TYPE);
return ret;
}
@Override
public MultilineChartAO getNormalizedAccumulatorGraphData(List ids) throws APIException {
return getAccumulatorGraphData(ids, true);
}
@Override
public MultilineChartAO getCombinedAccumulatorGraphData(List ids) throws APIException {
return getAccumulatorGraphData(ids, false);
}
public MultilineChartAO getAccumulatorGraphData(List ids, boolean normalized) throws APIException {
int normalizeBase = 100;
//TODO actually this limit is hardcoded, we should make it dynamic.
int maxValues = 200;
int numberOfIds = ids.size();
if (numberOfIds == 0) {
throw new APIException("No accumulators selected");
}
List singleGraphDataBeans = new ArrayList<>(numberOfIds);
//prepare values
Map values = new HashMap<>(numberOfIds);
List accNames = new ArrayList<>(numberOfIds);
for (String id : ids){
AccumulatorAO acc = getAccumulator(id);
AccumulatedSingleGraphAO singleGraphDataBean = getAccumulatorGraphData(id);
singleGraphDataBeans.add(singleGraphDataBean);
accNames.add(acc.getName());
List accValues = acc.getValues();
for (AccumulatedValueAO v : accValues){
long timestamp = v.getNumericTimestamp();
timestamp = timestamp / MINUTE * MINUTE;
AccumulatedValuesBean bean = values.get(timestamp);
if (bean==null){
bean = new AccumulatedValuesBean(timestamp);
values.put(timestamp, bean);
}
bean.setValue(acc.getName(), v.getFirstValue());
}
}
List valuesList = StaticQuickSorter.sort(values.values(), SORT_TYPE);
//now check if the data is complete
//Stores last known values to allow filling in of missing values (combining 1m and 5m values)
Map lastValue = new HashMap<>(accNames.size());
//filling last (or first) values.
for (String accName : accNames){
//first put 'some' initial value.
lastValue.put(accName, "0");
//now search for first non-null value
for(AccumulatedValuesBean accValueBean : valuesList){
String aValue = accValueBean.getValue(accName);
if (aValue!=null){
lastValue.put(accName, aValue);
break;
}
}
}
for(AccumulatedValuesBean accValueBean : valuesList){
for (String accName : accNames){
String value = accValueBean.getValue(accName);
if (value==null){
accValueBean.setValue(accName, lastValue.get(accName));
}else{
lastValue.put(accName, value);
}
}
}
if (normalized){
normalize(valuesList, accNames, normalizeBase);
}
//now create final data
List dataBeans = new ArrayList<>(valuesList.size());
for(AccumulatedValuesBean avb : valuesList){
AccumulatedValueAO bean = new AccumulatedValueAO(avb.getTime());
bean.setIsoTimestamp(NumberUtils.makeISO8601TimestampString(avb.getTimestamp()));
bean.setNumericTimestamp(avb.getTimestamp());
for (String accName : accNames){
bean.addValue(avb.getValue(accName));
}
dataBeans.add(bean);
}
//generally its not always a good idea to use subList, but since that list isn't reused,
//as in subList or subList of subList, its ok.
if (dataBeans.size()>maxValues) {
List shorterList = new ArrayList(dataBeans.subList(dataBeans.size() - maxValues, dataBeans.size()));
dataBeans = shorterList;
}
MultilineChartAO ret = new MultilineChartAO();
ret.setData(dataBeans);
ret.setNames(accNames);
ret.setSingleGraphAOs(singleGraphDataBeans);
return ret;
}
/*test visibility */ static void normalize(List values, List names, int limit){
for (String name : names){
//System.out.println("normalizing "+name);
ArrayList valueCopy = new ArrayList(values.size());
//step1 transform everything to float
float min = Float.MAX_VALUE, max = Float.MIN_VALUE;
for (AccumulatedValuesBean v : values){
float val = Float.parseFloat(v.getValue(name));
if (val>max)
max = val;
if (val getChartsForMultipleAccumulators(List names) throws APIException {
LinkedList ret = new LinkedList<>();
for (String name : names){
ret.add(getAccumulatorGraphDataByName(name));
}
return ret;
}
@Override
public List getAccumulatorIdsTiedToASpecificProducer(String producerId) throws APIException {
return AccumulatorRepository.getInstance().getIdsByProducerId(producerId);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy