/*
* Copyright 2009-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.admin.jmx;
import java.util.Collection;
import java.util.Date;
import org.springframework.batch.admin.domain.JobExecutionHistory;
import org.springframework.batch.admin.service.JobService;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.jmx.export.annotation.ManagedResource;
@ManagedResource
public class SimpleJobExecutionMetrics implements JobExecutionMetrics {
private final JobService jobService;
private final String jobName;
public SimpleJobExecutionMetrics(JobService jobService, String jobName) {
this.jobService = jobService;
this.jobName = jobName;
}
public int getExecutionCount() {
try {
return jobService.countJobExecutionsForJob(jobName);
}
catch (NoSuchJobException e) {
throw new IllegalStateException("Cannot locate job=" + jobName, e);
}
}
public int getFailureCount() {
int pageSize = 100;
int start = 0;
int count = 0;
Collection<JobExecution> jobExecutions;
do {
try {
jobExecutions = jobService.listJobExecutionsForJob(jobName, start, pageSize);
start += pageSize;
}
catch (NoSuchJobException e) {
throw new IllegalStateException("Cannot locate job=" + jobName, e);
}
for (JobExecution jobExecution : jobExecutions) {
if (jobExecution.getStatus().isUnsuccessful()) {
count++;
}
}
} while (!jobExecutions.isEmpty());
return count;
}
public double getLatestDuration() {
JobExecution jobExecution = getLatestJobExecution(jobName);
JobExecutionHistory history = new JobExecutionHistory(jobName);
history.append(jobExecution);
return history.getDuration().getMean();
}
public double getMeanDuration() {
JobExecutionHistory history = computeHistory(jobName);
return history.getDuration().getMean();
}
public double getMaxDuration() {
JobExecutionHistory history = computeHistory(jobName);
return history.getDuration().getMax();
}
public Date getLatestStartTime() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? null : jobExecution.getStartTime();
}
public Date getLatestEndTime() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? null : jobExecution.getEndTime();
}
public String getLatestExitCode() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? "NONE" : jobExecution.getExitStatus().getExitCode();
}
public String getLatestStatus() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? "NONE" : jobExecution.getStatus().toString();
}
public long getLatestExecutionId() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? -1 : jobExecution.getId();
}
public String getLatestStepExitDescription() {
JobExecution jobExecution = getLatestJobExecution(jobName);
StepExecution stepExecution = getLatestStepExecution(jobExecution);
return stepExecution==null ? "" : stepExecution.getExitStatus().getExitDescription();
}
public String getLatestStepName() {
JobExecution jobExecution = getLatestJobExecution(jobName);
StepExecution stepExecution = getLatestStepExecution(jobExecution);
return stepExecution==null ? "" : stepExecution.getStepName();
}
public boolean isJobRunning() {
JobExecution jobExecution = getLatestJobExecution(jobName);
return jobExecution==null ? false : jobExecution.isRunning();
}
private JobExecutionHistory computeHistory(String jobName) {
// Running average over last 10 executions...
return computeHistory(jobName, 10);
}
private JobExecution getLatestJobExecution(String jobName) {
try {
// On the cautious side: grab the last 4 executions by ID and look for
// the one that was last created...
Collection<JobExecution> jobExecutions = jobService.listJobExecutionsForJob(jobName, 0, 4);
if (jobExecutions.isEmpty()) {
return null;
}
long lastUpdated = 0L;
JobExecution result = null;
for (JobExecution jobExecution : jobExecutions) {
long updated = jobExecution.getCreateTime().getTime();
if (updated > lastUpdated) {
result = jobExecution;
lastUpdated = updated;
}
else if (result!=null && updated == lastUpdated && jobExecution.getId() > result.getId()) {
// Tie breaker using ID
result = jobExecution;
}
}
return result;
}
catch (NoSuchJobException e) {
throw new IllegalStateException("Cannot locate job=" + jobName, e);
}
}
private StepExecution getLatestStepExecution(JobExecution jobExecution) {
Collection<StepExecution> stepExecutions = jobExecution.getStepExecutions();
StepExecution stepExecution = null;
if (!stepExecutions.isEmpty()) {
Date latest = new Date(0L);
for (StepExecution candidate : stepExecutions) {
Date stepDate = candidate.getEndTime();
stepDate = stepDate==null ? new Date() : stepDate;
if (stepDate.after(latest)) {
latest = stepDate;
stepExecution = candidate;
}
else if (stepExecution!=null && stepDate.equals(latest) && candidate.getId()>stepExecution.getId()) {
// Tie breaker using ID
stepExecution = candidate;
}
}
}
return stepExecution;
}
private JobExecutionHistory computeHistory(String jobName, int total) {
JobExecutionHistory jobExecutionHistory = new JobExecutionHistory(jobName);
try {
for (JobExecution jobExecution : jobService.listJobExecutionsForJob(jobName, 0, total)) {
jobExecutionHistory.append(jobExecution);
}
}
catch (NoSuchJobException e) {
throw new IllegalStateException("Cannot locate job=" + jobName, e);
}
return jobExecutionHistory;
}
}