package nl.codecentric.jenkins.appd;
import hudson.model.AbstractBuild;
import hudson.model.ModelObject;
import hudson.model.TaskListener;
import hudson.util.DataSetBuilder;
import hudson.util.Graph;
import nl.codecentric.jenkins.appd.rest.types.MetricData;
import nl.codecentric.jenkins.appd.rest.types.MetricValues;
import nl.codecentric.jenkins.appd.util.LocalMessages;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import java.awt.*;
import java.io.IOException;
/**
* Root object of a AppDynamics Build Report.
*/
public class BuildActionResultsDisplay implements ModelObject {
/**
* The {@link AppDynamicsBuildAction} that this report belongs to.
*/
private transient AppDynamicsBuildAction buildAction;
private static AbstractBuild<?, ?> currentBuild = null;
private AppDynamicsReport currentReport;
/**
* Parses the reports and build a {@link BuildActionResultsDisplay}.
*
* @throws java.io.IOException If a report fails to parse.
*/
BuildActionResultsDisplay(final AppDynamicsBuildAction buildAction, TaskListener listener)
throws IOException {
this.buildAction = buildAction;
currentReport = this.buildAction.getAppDynamicsReport();
currentReport.setBuildAction(buildAction);
addPreviousBuildReportToExistingReport();
}
public String getDisplayName() {
return LocalMessages.REPORT_DISPLAYNAME.toString();
}
public AbstractBuild<?, ?> getBuild() {
return buildAction.getBuild();
}
public AppDynamicsReport getAppDynamicsReport() {
return currentReport;
}
private void addPreviousBuildReportToExistingReport() {
// Avoid parsing all builds.
if (BuildActionResultsDisplay.currentBuild == null) {
BuildActionResultsDisplay.currentBuild = getBuild();
} else {
if (BuildActionResultsDisplay.currentBuild != getBuild()) {
BuildActionResultsDisplay.currentBuild = null;
return;
}
}
AbstractBuild<?, ?> previousBuild = getBuild().getPreviousBuild();
if (previousBuild == null) {
return;
}
AppDynamicsBuildAction previousPerformanceAction = previousBuild.getAction(AppDynamicsBuildAction.class);
if (previousPerformanceAction == null) {
return;
}
BuildActionResultsDisplay previousBuildActionResults = previousPerformanceAction.getBuildActionResultsDisplay();
if (previousBuildActionResults == null) {
return;
}
AppDynamicsReport lastReport = previousBuildActionResults.getAppDynamicsReport();
getAppDynamicsReport().setLastBuildReport(lastReport);
}
/**
* Graph of metric points over time.
*/
public void doSummarizerGraph(final StaplerRequest request,
final StaplerResponse response) throws IOException {
final String metricKey = request.getParameter("metricDataKey");
final MetricData metricData = this.currentReport.getMetricByKey(metricKey);
final Graph graph = new GraphImpl(metricKey, metricData.getFrequency()) {
protected DataSetBuilder<String, Integer> createDataSet() {
DataSetBuilder<String, Integer> dataSetBuilder = new DataSetBuilder<String, Integer>();
int i = 1;
for (MetricValues value : metricData.getMetricValues()) {
dataSetBuilder.add(value.getValue(), metricKey, i++);
}
return dataSetBuilder;
}
};
graph.doPng(request, response);
}
private abstract class GraphImpl extends Graph {
private final String graphTitle;
private final String xLabel;
protected GraphImpl(final String metricKey, final String frequency) {
super(-1, 400, 300); // cannot use timestamp, since ranges may change
this.graphTitle = stripTitle(metricKey);
this.xLabel = "Time in " + frequency;
}
private String stripTitle(final String metricKey) {
return metricKey.substring(metricKey.lastIndexOf("|") + 1);
}
protected abstract DataSetBuilder<String, Integer> createDataSet();
protected JFreeChart createGraph() {
final CategoryDataset dataset = createDataSet().build();
final JFreeChart chart = ChartFactory.createLineChart(graphTitle, // title
xLabel, // category axis label
null, // value axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
false, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.white);
return chart;
}
}
}