Commit bdc99921 authored by Matija Obreza's avatar Matija Obreza
Browse files

KPI display

parent 2698910b
......@@ -72,4 +72,42 @@ public class DimensionKey implements EntityId, Serializable {
public String toString() {
return "{id=" + id + ", key=" + name + ", value=" + value + "}";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DimensionKey other = (DimensionKey) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
......@@ -111,6 +111,13 @@ public class Observation implements EntityId, Serializable {
@Override
public String toString() {
return "value =" + value + " D=" + dimensions;
return "value=" + value + " D=" + dimensions;
}
public boolean hasDimensionKeys(Set<DimensionKey> otherDks) {
if (getDimensions().containsAll(otherDks) && otherDks.containsAll(getDimensions())) {
return true;
}
return false;
}
}
......@@ -17,16 +17,13 @@
package org.genesys2.server.persistence.domain.kpi;
import java.util.List;
import java.util.Map;
import org.genesys2.server.model.kpi.DimensionKey;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface DimensionKeyRepository extends JpaRepository<DimensionKey, Long> {
@Cacheable(unless = "#result == null", value = "hibernate.org.genesys2.server.model.kpi.DimensionKey", key = "'namevalue-' + #name + '-' + #value")
DimensionKey findByNameAndValue(String name, String value);
List<DimensionKey> findByName(String name);
......
......@@ -36,4 +36,5 @@ public interface ExecutionRunRepository extends JpaRepository<ExecutionRun, Long
@Query("delete from ExecutionRun er where er.execution=?1")
void deleteByExecution(Execution execution);
}
......@@ -32,6 +32,8 @@ public interface ObservationRepository extends JpaRepository<Observation, Long>,
@Query("select o from Observation o where o.executionRun=?1")
List<Observation> findByExecutionRun(ExecutionRun executionRun, Pageable page);
List<Observation> findByExecutionRun(ExecutionRun executionRun);
@Query("select o from Observation o where o.executionRun.execution=?1 and ?2 member of o.dimensions order by o.executionRun.timestamp desc")
List<Observation> listObservationsByDimensionKey(Execution execution, DimensionKey next, Pageable page);
......
......@@ -66,8 +66,13 @@ public interface KPIService {
List<Observation> listObservations(ExecutionRun executionRun, Map<String, String> dimensionFilters, Pageable page);
ExecutionRun getLastExecutionRun(Execution execution);
ExecutionRun findLastExecutionRun(Execution execution);
void deleteObservations(ExecutionRun executionRun);
List<ExecutionRun> listExecutionRuns(Execution execution, Pageable pageable);
ExecutionRun getExecutionRun(long runId);
}
......@@ -28,6 +28,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
......@@ -45,6 +46,7 @@ import org.genesys2.server.persistence.domain.kpi.ExecutionRunRepository;
import org.genesys2.server.persistence.domain.kpi.KPIParameterRepository;
import org.genesys2.server.persistence.domain.kpi.ObservationRepository;
import org.genesys2.server.service.KPIService;
import org.hibernate.event.spi.PreInsertEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
......@@ -151,7 +153,7 @@ public class KPIServiceImpl implements KPIService {
}
@Override
public ExecutionRun getLastExecutionRun(Execution execution) {
public ExecutionRun findLastExecutionRun(Execution execution) {
List<ExecutionRun> l = executionRunRepository.findLast(execution, new PageRequest(0, 1));
return l.size() == 1 ? l.get(0) : null;
}
......@@ -235,10 +237,10 @@ public class KPIServiceImpl implements KPIService {
@Override
@Transactional
public List<Observation> save(Execution execution, List<Observation> observations) {
ExecutionRun executionRun = new ExecutionRun();
executionRun.setExecution(execution);
executionRun.setTimestamp(new Date());
executionRunRepository.save(executionRun);
Map<String, Map<String, DimensionKey>> runCache = new HashMap<String, Map<String, DimensionKey>>();
......@@ -252,36 +254,91 @@ public class KPIServiceImpl implements KPIService {
bar.put((String) foo[0], (DimensionKey) foo[1]);
}
LOG.info("Map " + dk.getName() + " size=" + bar.size());
LOG.info(bar);
runCache.put(dk.getName(), bar);
}
}
}
for (Observation obs : observations) {
obs.setExecutionRun(executionRun);
}
LOG.info("Pushing to DB 1");
observationRepository.save(observations);
for (Observation obs : observations) {
Set<DimensionKey> dims = new HashSet<DimensionKey>();
for (DimensionKey dk : obs.getDimensions()) {
try {
if (LOG.isDebugEnabled())
LOG.debug("Finding dk: " + dk);
DimensionKey existing = runCache.get(dk.getName()).get(dk.getValue());
dims.add(existing);
if (existing == null) {
LOG.info("New dk: " + dk);
dims.add(makeDimensionKey(dk));
} else {
dims.add(existing);
}
} catch (Throwable e) {
LOG.error(e.getMessage());
LOG.info("New dk: " + dk);
dims.add(makeDimensionKey(dk));
}
}
obs.setDimensions(dims);
obs.setExecutionRun(executionRun);
}
ExecutionRun previousRun = findLastExecutionRun(execution);
if (previousRun != null) {
LOG.info("Original observations size: " + observations.size());
removeSameResult(previousRun, observations);
LOG.info("Trimmed observations size: " + observations.size());
}
LOG.info("Pushing to DB 2");
if (observations.size() == 0) {
LOG.warn("No observations to save. Not storing execution run.");
return observations;
}
executionRunRepository.save(executionRun);
return observationRepository.save(observations);
}
private void removeSameResult(ExecutionRun previousRun, List<Observation> observations) {
List<Observation> previousObservations = observationRepository.findByExecutionRun(previousRun);
LOG.info("Got previous observations size=" + previousObservations.size());
for (int i = observations.size() - 1; i >= 0; i--) {
if (!observationChanged(observations.get(i), previousObservations)) {
if (LOG.isDebugEnabled())
LOG.debug("Removing unchanged observation: " + observations.get(i));
observations.remove(i);
}
}
}
private boolean observationChanged(Observation observation, List<Observation> observations) {
Set<DimensionKey> dims = observation.getDimensions();
Observation previous = findObservationByDimensionKeys(observations, dims);
if (previous == null) {
// No matching previous observation
if (LOG.isDebugEnabled())
LOG.debug("No match found");
return true;
}
if (previous.getValue() != observation.getValue()) {
// Value is different
if (LOG.isDebugEnabled())
LOG.debug("Values are different " + previous + "!=" + observation);
return true;
}
// No change
return false;
}
private Observation findObservationByDimensionKeys(List<Observation> observations, Set<DimensionKey> dims) {
for (Observation obs : observations) {
if (obs.hasDimensionKeys(dims)) {
return obs;
}
}
return null;
}
@Transactional
private DimensionKey makeDimensionKey(DimensionKey dk) {
return dimensionKeyRepository.save(dk);
......@@ -310,8 +367,9 @@ public class KPIServiceImpl implements KPIService {
private void printRes(long res, Execution paramExec, Object[] array, List<Observation> results) {
KPIParameter parameter = paramExec.getParameter();
if (LOG.isDebugEnabled()) {
LOG.debug("Reporting result\n\n");
LOG.debug("Reporting result");
LOG.debug(parameter.getName() + "=" + res);
LOG.debug("Params:" + ArrayUtils.toString(array));
}
Observation observation = new Observation();
......@@ -319,6 +377,7 @@ public class KPIServiceImpl implements KPIService {
for (int i = 0; i < array.length; i++) {
String name = paramExec.getDimension(i).getName();
String value = array[i].toString();
LOG.debug(" dk name=" + name + " val=" + array[i].toString());
DimensionKey dk = dimensionKeyRepository.findByNameAndValue(name, value);
if (dk == null) {
dk = new DimensionKey();
......@@ -371,4 +430,14 @@ public class KPIServiceImpl implements KPIService {
}
return dks;
}
@Override
public List<ExecutionRun> listExecutionRuns(Execution execution, Pageable pageable) {
return executionRunRepository.findByExecution(execution, pageable);
}
@Override
public ExecutionRun getExecutionRun(long runId) {
return executionRunRepository.findOne(runId);
}
}
package org.genesys2.server.servlet.controller.admin;
import java.util.Map;
import org.genesys2.server.model.kpi.Execution;
import org.genesys2.server.model.kpi.ExecutionRun;
import org.genesys2.server.service.KPIService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller("kpiAdminController")
@RequestMapping(value = "/admin/kpi")
public class KPIController {
@Autowired
private KPIService kpiService;
@Value("${paginator.default.pageSize}")
private int pageSize;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(ModelMap model) {
model.addAttribute("executions", kpiService.listExecutions());
return "/admin/kpi/index";
}
@RequestMapping(value = "/exec/{executionName:.+}", method = RequestMethod.GET)
public String execution(ModelMap model, @PathVariable("executionName") String executionName,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
Execution execution = kpiService.getExecution(executionName);
model.addAttribute("execution", execution);
model.addAttribute("executionRuns", kpiService.listExecutionRuns(execution, new PageRequest(page - 1, pageSize)));
return "/admin/kpi/execution";
}
@RequestMapping(value = "/exec/{executionName}/run/{runId}", method = RequestMethod.GET)
public String executionRun(ModelMap model, @PathVariable("executionName") String executionName, @PathVariable("runId") long runId,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
Execution execution = kpiService.getExecution(executionName);
ExecutionRun executionRun = kpiService.getExecutionRun(runId);
model.addAttribute("execution", execution);
model.addAttribute("executionRun", executionRun);
Map<String, String> dimensionFilters = null;
model.addAttribute("observations", kpiService.listObservations(executionRun, dimensionFilters, new PageRequest(page - 1, pageSize)));
return "/admin/kpi/run";
}
}
......@@ -220,7 +220,7 @@ public class KPIController extends RestController {
@RequestMapping(value = "/observation/{executionName}/", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody List<Observation> listObservations(@PathVariable("executionName") String executionName,
@RequestParam(value = "page", required = false, defaultValue = "1") int page, @RequestBody(required = false) Map<String, String> dimensionFilters) {
return kpiService.listObservations(kpiService.getLastExecutionRun(kpiService.getExecution(executionName)), dimensionFilters, new PageRequest(page - 1,
return kpiService.listObservations(kpiService.findLastExecutionRun(kpiService.getExecution(executionName)), dimensionFilters, new PageRequest(page - 1,
50));
}
......
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<title><spring:message code="admin.kpi.execution.page" /></title>
</head>
<body>
<h1>
<spring:message code="admin.kpi.execution.page" />
</h1>
<div class="main-col-header clearfix">
<div class="nav-header pull-left">
<a class="" href="<c:url value="/admin/cache/" />"><spring:message code="menu.admin.caches" /></a> <a class=""
href="<c:url value="/admin/logger/" />"
><spring:message code="menu.admin.loggers" /></a> <a class="" href="<c:url value="/admin/ds2/" />"><spring:message
code="menu.admin.ds2"
/></a> <a class="" href="<c:url value="/admin/kpi/" />"><spring:message code="menu.admin.kpi" /></a>
</div>
</div>
<div class="crop-details">
<c:forEach items="${executionRuns}" var="executionRun">
<div class="row">
<div class="col-xs-3">
<local:prettyTime date="${executionRun.timestamp}" locale="${pageContext.response.locale}" />
</div>
<div class="col-xs-5">
<a href="<c:url value="/admin/kpi/exec/${execution.name}/run/${executionRun.id}" />"><c:out value="${timestamp}" />
<local:prettyTime date="${executionRun.timestamp}" locale="${pageContext.response.locale}" />
</a>
</div>
</div>
</c:forEach>
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<title><spring:message code="admin.kpi.index.page" /></title>
</head>
<body>
<h1>
<spring:message code="admin.kpi.index.page" />
</h1>
<div class="main-col-header clearfix">
<div class="nav-header pull-left">
<a class="" href="<c:url value="/admin/cache/" />"><spring:message code="menu.admin.caches" /></a> <a class=""
href="<c:url value="/admin/logger/" />"
><spring:message code="menu.admin.loggers" /></a> <a class="" href="<c:url value="/admin/ds2/" />"><spring:message
code="menu.admin.ds2"
/></a> <a class="" href="<c:url value="/admin/kpi/" />"><spring:message code="menu.admin.kpi" /></a>
</div>
</div>
<h2>${execution}</h2>
<div class="crop-details">
<c:forEach items="${executions}" var="execution">
<div class="row">
<div class="col-xs-3">
<c:out value="${execution.name}" />
</div>
<div class="col-xs-5">
<a href="<c:url value="/admin/kpi/exec/${execution.name}" />"><c:out value="${execution.title}" /></a>
</div>
<div class="col-xs-4">
<c:out value="${execution.parameter.title}" />
<small><b><c:out value="${execution.parameter.entity}" /></b>
<c:out value="${execution.parameter.condition}" /></small>
</div>
<div class="col-xs-12">
<c:forEach items="${execution.executionDimensions}" var="dimension">
<div class="col-xs-6">
<c:out value="${dimension.dimension.title}" />
<c:out value="${dimension.dimension.condition}" />
</div>
<div class="col-xs-6">
<c:out value="${dimension.field}" />
<c:out value="${dimension.link}" />
</div>
</c:forEach>
</div>
</div>
</c:forEach>
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<html>
<head>
<title><spring:message code="admin.kpi.execution.page" /></title>
</head>
<body>
<h1>
<spring:message code="admin.kpi.execution.page" />
</h1>
<div class="main-col-header clearfix">
<div class="nav-header pull-left">
<a class="" href="<c:url value="/admin/cache/" />"><spring:message code="menu.admin.caches" /></a> <a class=""
href="<c:url value="/admin/logger/" />"
><spring:message code="menu.admin.loggers" /></a> <a class="" href="<c:url value="/admin/ds2/" />"><spring:message
code="menu.admin.ds2"
/></a> <a class="" href="<c:url value="/admin/kpi/" />"><spring:message code="menu.admin.kpi" /></a>
</div>
</div>
<h2><local:prettyTime date="${executionRun.timestamp}" locale="${pageContext.response.locale}" /></h2>
<div class="crop-details">
<c:forEach items="${observations}" var="obs">
<div class="row">
<div class="col-xs-4 col-sm-2 text-right">
<c:out value="${obs.value}" />
</div>
<div class="col-xs-8 col-sm-10">
<c:forEach items="${obs.dimensions}" var="dim">
<div><c:out value="${dim.value}" /></div>
</c:forEach>
</div>
</div>
</c:forEach>
</div>
</body>
</html>
\ No newline at end of file
......@@ -310,7 +310,7 @@ public class KPIEntitiesTest {
// drop it
log.info("DELETING!!!!");
ExecutionRun executionRun = kpiService.getLastExecutionRun(execution);
ExecutionRun executionRun = kpiService.findLastExecutionRun(execution);
kpiService.deleteObservations(executionRun);
kpiService.delete(execution);
......@@ -320,7 +320,7 @@ public class KPIEntitiesTest {
log.info("DK=" + dk);
}
ExecutionRun executionRun2 = kpiService.getLastExecutionRun(execution2);
ExecutionRun executionRun2 = kpiService.findLastExecutionRun(execution2);
kpiService.deleteObservations(executionRun2);
kpiService.delete(execution2);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment