/*
* Copyright (C) 2008 Digital Sundhed (SDSD)
*
* All source code and information supplied as part of chronos
* is copyright to its contributers.
*
* The source code has been released under a dual license - meaning you can
* use either licensed version of the library with your code.
*
* It is released under the Common Public License 1.0, a copy of which can
* be found at the link below.
* http://www.opensource.org/licenses/cpl.php
*
* It is released under the LGPL (GNU Lesser General Public License), either
* version 2.1 of the License, or (at your option) any later version. A copy
* of which can be found at the link below.
* http://www.gnu.org/copyleft/lesser.html
*/
package org.codehaus.mojo.chronos;
import java.io.File;
import java.io.IOException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.chronos.gc.GCSamples;
import org.codehaus.mojo.chronos.responsetime.GroupedResponsetimeSamples;
import org.codehaus.mojo.chronos.responsetime.ResponsetimeSamples;
/**
* Checks the latest performancetests to verify that performance targets have been met.
*
* @author ksr@lakeside.dk
* @goal check
* @phase verify
*/
public class CheckMojo extends AbstractMojo {
private static final int DEFAULT_DURATION = 20000;
/**
* The maximum allowed ratio of time spent garbage collecting.
*
* @parameter
*/
protected double gctimeratio;
/**
* The maximum memory (in kb) garbagecollected pr second.
*
* @parameter
*/
protected double collectedprsecond;
/**
* The minimum required maximum throughput (in requests/sec).
*
* @parameter
*/
protected double maxthroughput;
/**
* The maximum acceptable average responsetime (in millis).
*
* @parameter
*/
protected double responsetimeaverage;
/**
* The maximum acceptable a95 percentage responsetime (in millis).
*
* @parameter
*/
protected double responsetime95;
/**
* The maximum acceptable responsetime (in millis).
*
* @parameter
*/
protected double responsetimemax;
/**
* responsetimeDivider may be used when the response time of a single request is so low that the granularity of the
* system timer corrupts the response time measured.
*
* @parameter default-value = 1
*/
protected int responsetimedivider = 1;
/**
* The timeinterval to base moving average calculations on (in millis).
*
* @parameter default-value = 20000
*/
protected int averageduration = DEFAULT_DURATION; // 20 seconds
/**
* @parameter default-value="performancetest"
*/
protected String dataid;
/**
* The current maven project.
*
* @parameter expression="${project}"
*/
private MavenProject project;
public void execute() throws MojoExecutionException, MojoFailureException {
File responsetimeSamples = Utils.getPerformanceSamplesSer(project.getBasedir(), dataid);
if(!responsetimeSamples.exists()) {
throw new MojoExecutionException("File " + responsetimeSamples.getAbsolutePath() + " not found");
}
try {
ResponsetimeSamples rtSamples = (GroupedResponsetimeSamples)Utils.readObject(responsetimeSamples);
long totalTime = rtSamples.getTotalTime();
validateMaxThroughput(rtSamples);
validateAverageResponsetime(rtSamples);
validatePercentile95Responsetime(rtSamples);
validateMaxResponsetime(rtSamples);
GCSamples gcSamples = Utils.readGCSamples(project.getBasedir(), dataid);
if(gcSamples != null) {
validateGCTime(gcSamples, totalTime);
validateCollectedPrSecond(gcSamples, totalTime);
}
} catch (IOException e) {
throw new MojoExecutionException("Failure", e);
}
}
void validateGCTime(GCSamples gcSamples, long totalTime) throws MojoExecutionException {
if(gctimeratio <= 0) {
return;
}
double actualRatio = gcSamples.getGarbageCollectionRatio(totalTime);
if(actualRatio > gctimeratio) {
throw new MojoExecutionException("To much time spent garbagecollection. Ratio of time spent was "
+ actualRatio + " but acceptable level was " + gctimeratio);
}
}
void validateCollectedPrSecond(GCSamples samples, long totalTime) throws MojoExecutionException {
if(collectedprsecond <= 0) {
return;
}
double actual = samples.getCollectedKBPerSecond(totalTime);
if(actual > collectedprsecond) {
throw new MojoExecutionException("To much stuff garbagecollected. Garbagecollected pr second was " + actual
+ "kb but acceptable level was " + collectedprsecond);
}
}
void validateMaxThroughput(ResponsetimeSamples samples) throws MojoExecutionException {
if(maxthroughput <= 0) {
return;
}
double actual = samples.getMaxAverageThroughput(averageduration, responsetimedivider);
if(actual < maxthroughput) {
throw new MojoExecutionException("Throughput too low. Throughput was " + actual
+ " but required throughput was " + maxthroughput);
}
}
void validateAverageResponsetime(ResponsetimeSamples samples) throws MojoExecutionException {
if(responsetimeaverage <= 0) {
return;
}
double actual = samples.getAverage(responsetimedivider);
if(actual > responsetimeaverage) {
throw new MojoExecutionException("Average responsetime too high. Average was " + actual
+ " but acceptable was " + responsetimeaverage);
}
}
void validatePercentile95Responsetime(ResponsetimeSamples samples) throws MojoExecutionException {
if(responsetime95 <= 0) {
return;
}
double actual = samples.getPercentile95(responsetimedivider);
if(actual > responsetime95) {
throw new MojoExecutionException("95 percentile responsetime too high. Measured was " + actual
+ " but acceptable was " + responsetime95);
}
}
void validateMaxResponsetime(ResponsetimeSamples samples) throws MojoExecutionException {
if(responsetimemax <= 0) {
return;
}
double actual = samples.getMax(responsetimedivider);
if(actual > responsetimemax) {
throw new MojoExecutionException("Max responsetime too high. Measured was " + actual
+ " but acceptable was " + responsetimemax);
}
}
}