Skip to content
This repository has been archived by the owner on Nov 20, 2020. It is now read-only.

Commit

Permalink
extract dashboard statistics calculation in a separate class
Browse files Browse the repository at this point in the history
  • Loading branch information
fmbenhassine committed Oct 31, 2017
1 parent cfc0a79 commit 7ac413e
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 147 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package org.jeasy.jobs.admin.web;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

class DashboardStatistics {

private int registeredJobs;
private int runningExecutions;
private int failedExecutions;
private int totalExecutions;
private int pendingRequests;
private List<LocalDate> lastThreeDays;
private List<Integer> failedExecutionsForTheLastThreeDays;
private List<Integer> succeededExecutionsForTheLastThreeDays;
private List<LocalDateTime> lastTwelveHours;
private List<Integer> receivedRequestsForTheLastTwelveHours;

public int getRegisteredJobs() {
return registeredJobs;
}

public void setRegisteredJobs(int registeredJobs) {
this.registeredJobs = registeredJobs;
}

public int getRunningExecutions() {
return runningExecutions;
}

public void setRunningExecutions(int runningExecutions) {
this.runningExecutions = runningExecutions;
}

public int getFailedExecutions() {
return failedExecutions;
}

public void setFailedExecutions(int failedExecutions) {
this.failedExecutions = failedExecutions;
}

public int getTotalExecutions() {
return totalExecutions;
}

public void setTotalExecutions(int totalExecutions) {
this.totalExecutions = totalExecutions;
}

public int getPendingRequests() {
return pendingRequests;
}

public void setPendingRequests(int pendingRequests) {
this.pendingRequests = pendingRequests;
}

public List<LocalDate> getLastThreeDays() {
return lastThreeDays;
}

public void setLastThreeDays(List<LocalDate> lastThreeDays) {
this.lastThreeDays = lastThreeDays;
}

public List<Integer> getFailedExecutionsForTheLastThreeDays() {
return failedExecutionsForTheLastThreeDays;
}

public void setFailedExecutionsForTheLastThreeDays(List<Integer> failedExecutionsForTheLastThreeDays) {
this.failedExecutionsForTheLastThreeDays = failedExecutionsForTheLastThreeDays;
}

public List<Integer> getSucceededExecutionsForTheLastThreeDays() {
return succeededExecutionsForTheLastThreeDays;
}

public void setSucceededExecutionsForTheLastThreeDays(List<Integer> succeededExecutionsForTheLastThreeDays) {
this.succeededExecutionsForTheLastThreeDays = succeededExecutionsForTheLastThreeDays;
}

public List<LocalDateTime> getLastTwelveHours() {
return lastTwelveHours;
}

public void setLastTwelveHours(List<LocalDateTime> lastTwelveHours) {
this.lastTwelveHours = lastTwelveHours;
}

public List<Integer> getReceivedRequestsForTheLastTwelveHours() {
return receivedRequestsForTheLastTwelveHours;
}

public void setReceivedRequestsForTheLastTwelveHours(List<Integer> receivedRequestsForTheLastTwelveHours) {
this.receivedRequestsForTheLastTwelveHours = receivedRequestsForTheLastTwelveHours;
}

public int getPercentageOfFailedExecutions() {
return ((int)(getFailedExecutions() * 100.0 / getTotalExecutions() + 0.5));
}

/*
* Utility methods to format data
*/

public String getFormattedLastThreeDays() {
return join(getLastThreeDays(), " ");
}

public String getFormattedSucceededExecutionsForTheLastThreeDays() {
return join(getSucceededExecutionsForTheLastThreeDays(), " ");
}

public String getFormattedFailedExecutionsForTheLastThreeDays() {
return join(getFailedExecutionsForTheLastThreeDays(), " ");
}

public String getFormattedLastTwelveHours() {
return join(getLastTwelveHours().stream().map(LocalDateTime::getHour).collect(toList()), "h ");
}

public String getFormattedReceivedRequestsForTheLastTwelveHours() {
return join(getReceivedRequestsForTheLastTwelveHours(), " ");
}

private <T> String join(List<T> elements, String delimiter) {
return elements.stream().map(Object::toString).collect(joining(delimiter));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package org.jeasy.jobs.admin.web;

import org.jeasy.jobs.execution.JobExecution;
import org.jeasy.jobs.execution.JobExecutionRepository;
import org.jeasy.jobs.execution.JobExecutionStatus;
import org.jeasy.jobs.job.JobExitStatus;
import org.jeasy.jobs.job.JobRepository;
import org.jeasy.jobs.request.JobExecutionRequest;
import org.jeasy.jobs.request.JobExecutionRequestRepository;
import org.jeasy.jobs.request.JobExecutionRequestStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

@Component
class DashboardStatisticsCalculator {

@Autowired
private JobRepository jobRepository;

@Autowired
private JobExecutionRepository jobExecutionRepository;

@Autowired
private JobExecutionRequestRepository jobExecutionRequestRepository;

DashboardStatistics calculateStatistics() {

// FIXME optimize queries for stats?
// if stats are calculated on the db level => less code but lot of queries to the db
// if stats are calculated on the app level => more code but only one query to the db

DashboardStatistics statistics = new DashboardStatistics();

// calculate global stats
statistics.setRegisteredJobs(jobRepository.findAll().size());

List<JobExecution> jobExecutions = jobExecutionRepository.findAllJobExecutions();
long runningExecutions = jobExecutions.stream().filter(running()).count();
long failedExecutions = jobExecutions.stream().filter(failed()).count();
int nbExecutions = jobExecutions.size();
statistics.setRunningExecutions((int) runningExecutions);
statistics.setFailedExecutions((int) failedExecutions);
statistics.setTotalExecutions(nbExecutions);

int pendingRequests = jobExecutionRequestRepository.findJobExecutionRequestsByStatus(JobExecutionRequestStatus.PENDING).size();
statistics.setPendingRequests(pendingRequests);

// calculate request number per hour stats
final List<LocalDateTime> lastTwelveHours = getLastTwelveHours();

List<JobExecutionRequest> jobExecutionRequests = jobExecutionRequestRepository.findAllJobExecutionRequests();
List<Integer> jobExecutionRequestsForTheLastTwelveHours = new ArrayList<>();
for (LocalDateTime hour : lastTwelveHours) {
jobExecutionRequestsForTheLastTwelveHours.add((int) jobExecutionRequests.stream().filter(creationDateIsWithin(hour, hour.plusHours(1))).count());
}
statistics.setLastTwelveHours(lastTwelveHours);
statistics.setReceivedRequestsForTheLastTwelveHours(jobExecutionRequestsForTheLastTwelveHours);

// calculate job executions by status
final LocalDateTime today = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS);
final LocalDateTime yesterday = today.minusDays(1).truncatedTo(ChronoUnit.DAYS);
final LocalDateTime twoDaysAgo = today.minusDays(2).truncatedTo(ChronoUnit.DAYS);
final LocalDateTime tomorrow = today.plusDays(1).truncatedTo(ChronoUnit.DAYS);

List<Integer> succeededExecutionsList = new ArrayList<>();
succeededExecutionsList.add((int) jobExecutions.stream().filter(succeeded()).filter(startDateIsWithin(twoDaysAgo, yesterday)).count());
succeededExecutionsList.add((int) jobExecutions.stream().filter(succeeded()).filter(startDateIsWithin(yesterday, today)).count());
succeededExecutionsList.add((int) jobExecutions.stream().filter(succeeded()).filter(startDateIsWithin(today, tomorrow)).count());

List<Integer> failedExecutionsList = new ArrayList<>();
failedExecutionsList.add((int) jobExecutions.stream().filter(failed()).filter(startDateIsWithin(twoDaysAgo, yesterday)).count());
failedExecutionsList.add((int) jobExecutions.stream().filter(failed()).filter(startDateIsWithin(yesterday, today)).count());
failedExecutionsList.add((int) jobExecutions.stream().filter(failed()).filter(startDateIsWithin(today, tomorrow)).count());

statistics.setLastThreeDays(Arrays.asList(twoDaysAgo.toLocalDate(), yesterday.toLocalDate(), today.toLocalDate()));
statistics.setSucceededExecutionsForTheLastThreeDays(succeededExecutionsList);
statistics.setFailedExecutionsForTheLastThreeDays(failedExecutionsList);

return statistics;
}

private Predicate<JobExecution> failed() {
return jobExecution -> jobExecution.getJobExitStatus().equals(JobExitStatus.FAILED);
}

private Predicate<JobExecution> succeeded() {
return jobExecution -> jobExecution.getJobExitStatus().equals(JobExitStatus.SUCCEEDED);
}

private Predicate<JobExecution> running() {
return jobExecution -> jobExecution.getJobExecutionStatus().equals(JobExecutionStatus.RUNNING);
}

private Predicate<JobExecution> startDateIsWithin(LocalDateTime begin, LocalDateTime end) {
return jobExecution -> {
LocalDateTime startDate = jobExecution.getStartDate();
return isWithin(startDate, begin, end);
};
}

private Predicate<JobExecutionRequest> creationDateIsWithin(LocalDateTime begin, LocalDateTime end) {
return jobExecutionRequest -> {
LocalDateTime creationDate = jobExecutionRequest.getCreationDate();
return isWithin(creationDate, begin, end);
};
}

private boolean isWithin(LocalDateTime dateToCheck, LocalDateTime begin, LocalDateTime end) {
return dateToCheck.isAfter(begin) && dateToCheck.isBefore(end);
}

private List<LocalDateTime> getLastTwelveHours() {
LocalDateTime now = LocalDateTime.now();
final List<LocalDateTime> lastTwelveHours = new ArrayList<>();
for (int i = 11; i >= 0; i--) {
lastTwelveHours.add(now.minusHours(i).truncatedTo(ChronoUnit.HOURS));
}
return lastTwelveHours;
}

}
Loading

0 comments on commit 7ac413e

Please sign in to comment.