MonitoringAggregator.java
package sk.iway.iwcm.components.monitoring.rest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import sk.iway.iwcm.components.monitoring.jpa.MonitoringEntity;
/**
* 50053-WJ9--monitorovanie-servera-zaznmenaie-hodnoty
* Agregracia dat servera, vráti maximálne hodnoty za určitý časový úsek.
* Autor: Sebastian Ivan
*/
public class MonitoringAggregator {
private Page<MonitoringEntity> data;
private int dateRange;
private HashMap<String, HashMap<Date, MonitoringEntity>> map = new HashMap<String, HashMap<Date, MonitoringEntity>>();
private Calendar calendarInstance = Calendar.getInstance();
//Constructor. Set element data and compute data range in days
public MonitoringAggregator(Page<MonitoringEntity> data, Date fromDate, Date toDate) {
this.data = data;
int diffInDays = (int)( (fromDate.getTime() - toDate.getTime()) / (1000 * 60 * 60 * 24) );
this.dateRange = Math.abs(diffInDays);
this.aggregateData();
}
private void aggregateData() {
MonitoringEntity tmpEntity = new MonitoringEntity();
//Loop MonitoringEntity array data
for(MonitoringEntity entity : data) {
Date dateToRound = new Date();
String nodeName = entity.getNodeName();
//If node name is empty, set nodeName to "empty" (just for FrontEnd use)
if(nodeName == null || nodeName.trim().isEmpty() || nodeName == "") {
nodeName = "empty";
entity.setNodeName("empty");
}
//Call roundDate fn to round date (later data with same round date will be aggregated together)
dateToRound = roundDate(entity);
entity.setDayDate(dateToRound);
/*Set HasMap, where nodeName is key (every key is uniqe) and value is another HashMap.
In fact every nodeName (key) has his own HashMap -> key is round date and value is MonitoringEntity*/
if(map.get(nodeName) == null) {
HashMap<Date, MonitoringEntity> tmpHashMap = new HashMap<Date, MonitoringEntity>();
map.put(nodeName, tmpHashMap);
}
//If nodeName's HashMap already contain this round date as a key combine this two Entities using setEntityWithMaxAtributes fn
tmpEntity = map.get(nodeName).get(dateToRound);
if(tmpEntity == null) {
map.get(nodeName).put(dateToRound, entity);
} else {
setEntityWithMaxAtributes(entity, tmpEntity);
}
}
}
//Use dateRange param to call right date rounding function
private Date roundDate(MonitoringEntity entity) {
if(this.dateRange <= 5) {
return entity.getDayDate();
} else if(this.dateRange > 5 && this.dateRange <= 10) {
return tenMinutesAggregation(entity.getDayDate());
} else if(this.dateRange > 10 && this.dateRange <= 14) {
return thirtyMinutesAggregation(entity.getDayDate());
} else if(this.dateRange > 14 && this.dateRange <= 30) {
return oneHourAggregation(entity.getDayDate());
} else if(this.dateRange > 30 && this.dateRange <= 60) {
return fourHoursAggregation(entity.getDayDate());
} else {
return twelveHoursAggregation(entity.getDayDate());
}
}
//Compare same params from 2 Entities, and return new Entity where every param had set bigger value from this 2 Entiries
private void setEntityWithMaxAtributes(MonitoringEntity entity1, MonitoringEntity entity2 ) {
entity1.setCache(entity1.getCache() > entity2.getCache() ? entity1.getCache() : entity2.getCache());
entity1.setCpuUsage(entity1.getCpuUsage() > entity2.getCpuUsage() ? entity1.getCpuUsage() : entity2.getCpuUsage());
entity1.setDbActive(entity1.getDbActive() > entity2.getDbActive() ? entity1.getDbActive() : entity2.getDbActive());
entity1.setDbIdle(entity1.getDbIdle() > entity2.getDbIdle() ? entity1.getDbIdle() : entity2.getDbIdle());
entity1.setId(entity1.getId() > entity2.getId() ? entity1.getId() : entity2.getId());
entity1.setMemFree(entity1.getMemFree() > entity2.getMemFree() ? entity1.getMemFree() : entity2.getMemFree());
entity1.setMemTotal(entity1.getMemTotal() > entity2.getMemTotal() ? entity1.getMemTotal() : entity2.getMemTotal());
entity1.setProcessUsage(entity1.getProcessUsage() > entity2.getProcessUsage() ? entity1.getProcessUsage() : entity2.getProcessUsage());
entity1.setSessions(entity1.getSessions() > entity2.getSessions() ? entity1.getSessions() : entity2.getSessions());
}
//10 minut date round
private Date tenMinutesAggregation(Date dateToRound) {
Calendar calendar = calendarInstance;
calendar.setTime(dateToRound);
int unroundedMinutes = calendar.get(Calendar.MINUTE);
int mod = unroundedMinutes % 10;
calendar.add(Calendar.MINUTE, mod < 5 ? -mod : (10-mod));
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
//30 minut date round
private Date thirtyMinutesAggregation(Date dateToRound) {
Calendar calendar = calendarInstance;
calendar.setTime(dateToRound);
int actualMinutes = calendar.get(Calendar.MINUTE);
if(actualMinutes < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if(actualMinutes > 15 && actualMinutes < 45) {
calendar.set(Calendar.MINUTE, 30);
} else {
calendar.set(Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY + 1);
calendar.set(Calendar.MINUTE, 0);
}
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
//1 hour date round
private Date oneHourAggregation(Date dateToRound) {
Calendar calendar = calendarInstance;
calendar.setTime(dateToRound);
int actualMinutes = calendar.get(Calendar.MINUTE);
int actualHour = calendar.get(Calendar.HOUR_OF_DAY);
calendar.set(Calendar.HOUR_OF_DAY, actualMinutes < 30 ? actualHour : actualHour + 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
//4 hours date round
private Date fourHoursAggregation(Date dateToRound) {
Calendar calendar = calendarInstance;
calendar.setTime(dateToRound);
int actualHour = calendar.get(Calendar.HOUR_OF_DAY);
int mod = actualHour % 4;
calendar.add(Calendar.HOUR_OF_DAY, mod < 2 ? -mod : (4-mod));
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
//12 hours date round
private Date twelveHoursAggregation(Date dateToRound) {
Calendar calendar = calendarInstance;
calendar.setTime(dateToRound);
int actualHour = calendar.get(Calendar.HOUR_OF_DAY);
calendar.set(Calendar.HOUR_OF_DAY, actualHour < 12 ? actualHour : actualHour + 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
return calendar.getTime();
}
//Transform this data which containt two HashMap into List of MonitoringEntities (we need List format to return this data to FrontEnd)
private List<MonitoringEntity> transformDataToList() {
List<MonitoringEntity> transformedData = new ArrayList<>();
for (Map.Entry<String, HashMap<Date, MonitoringEntity>> entry1 : this.map.entrySet()) {
for(Map.Entry<Date, MonitoringEntity> entry2 : entry1.getValue().entrySet()) {
transformedData.add(entry2.getValue());
}
}
return transformedData;
}
public List<MonitoringEntity> returnAggregatedData() {
return this.transformDataToList();
}
}