Added checkboxes for showing less data and hiding the trend line.

Removed code to graph the min and max values since it's unlikely to be used.
This commit is contained in:
Ann Priestman 2018-05-01 12:24:10 -04:00
parent 2ff7ccc62b
commit f0c017f35a
2 changed files with 94 additions and 119 deletions

View File

@ -64,6 +64,8 @@ public class HealthMonitorDashboard {
private JComboBox<String> dateComboBox = null;
private JComboBox<String> hostComboBox = null;
private JCheckBox hostCheckBox = null;
private JCheckBox showTrendLineCheckBox = null;
private JCheckBox skipOutliersCheckBox = null;
private JPanel graphPanel = null;
private JDialog dialog = null;
private final Container parentWindow;
@ -200,7 +202,9 @@ public class HealthMonitorDashboard {
* @return the control panel
*/
@NbBundle.Messages({"HealthMonitorDashboard.createTimingControlPanel.filterByHost=Filter by host",
"HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display"})
"HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display",
"HealthMonitorDashboard.createTimingControlPanel.skipOutliers=Do not plot outliers",
"HealthMonitorDashboard.createTimingControlPanel.showTrendLine=Show trend line"})
private JPanel createTimingControlPanel() {
JPanel timingControlPanel = new JPanel();
@ -251,7 +255,7 @@ public class HealthMonitorDashboard {
}
});
// Create the checkbox
// Create the host checkbox
hostCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_filterByHost());
hostCheckBox.setSelected(false);
hostComboBox.setEnabled(false);
@ -269,6 +273,38 @@ public class HealthMonitorDashboard {
}
});
// Create the checkbox for showing the trend line
showTrendLineCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_showTrendLine());
showTrendLineCheckBox.setSelected(true);
// Set up the listener on the checkbox
showTrendLineCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
try {
updateTimingMetricGraphs();
} catch (HealthMonitorException ex) {
logger.log(Level.SEVERE, "Error populating timing metric panel", ex);
}
}
});
// Create the checkbox for omitting outliers
skipOutliersCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_skipOutliers());
skipOutliersCheckBox.setSelected(false);
// Set up the listener on the checkbox
skipOutliersCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
try {
updateTimingMetricGraphs();
} catch (HealthMonitorException ex) {
logger.log(Level.SEVERE, "Error populating timing metric panel", ex);
}
}
});
// Add the date range combo box and label to the panel
timingControlPanel.add(new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays()));
timingControlPanel.add(dateComboBox);
@ -280,6 +316,18 @@ public class HealthMonitorDashboard {
timingControlPanel.add(hostCheckBox);
timingControlPanel.add(hostComboBox);
// Put some space between the elements
timingControlPanel.add(Box.createHorizontalStrut(100));
// Add the skip outliers checkbox
timingControlPanel.add(this.showTrendLineCheckBox);
// Put some space between the elements
timingControlPanel.add(Box.createHorizontalStrut(100));
// Add the skip outliers checkbox
timingControlPanel.add(this.skipOutliersCheckBox);
return timingControlPanel;
}
@ -327,7 +375,7 @@ public class HealthMonitorDashboard {
// Generate the graph
TimingMetricGraphPanel singleTimingGraphPanel = new TimingMetricGraphPanel(intermediateTimingDataForDisplay,
TimingMetricGraphPanel.TimingMetricType.AVERAGE, hostToDisplay, true, metricName);
hostToDisplay, true, metricName, skipOutliersCheckBox.isSelected(), showTrendLineCheckBox.isSelected());
singleTimingGraphPanel.setPreferredSize(new Dimension(700,200));
graphPanel.add(singleTimingGraphPanel);

View File

@ -58,9 +58,10 @@ class TimingMetricGraphPanel extends JPanel {
private int pointWidth = 4;
private int numberYDivisions = 10;
private List<DatabaseTimingResult> timingResults;
private TimingMetricType timingMetricType;
private String metricName;
private boolean doLineGraph;
private boolean skipOutliers;
private boolean showTrendLine;
private String yUnitString;
private TrendLine trendLine;
private final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
@ -70,11 +71,12 @@ class TimingMetricGraphPanel extends JPanel {
private double maxMetricTime;
private double minMetricTime;
TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull, TimingMetricType timingMetricType,
String hostName, boolean doLineGraph, String metricName) {
TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull,
String hostName, boolean doLineGraph, String metricName, boolean skipOutliers, boolean showTrendLine) {
this.timingMetricType = timingMetricType;
this.doLineGraph = doLineGraph;
this.skipOutliers = skipOutliers;
this.showTrendLine = showTrendLine;
this.metricName = metricName;
if(hostName == null || hostName.isEmpty()) {
timingResults = timingResultsFull;
@ -84,89 +86,48 @@ class TimingMetricGraphPanel extends JPanel {
.collect(Collectors.toList());
}
try {
trendLine = new TrendLine(timingResults, timingMetricType);
} catch (HealthMonitorException ex) {
// Log it, set trendLine to null and continue on
logger.log(Level.WARNING, "Can not generate a trend line on empty data set");
trendLine = null;
if(showTrendLine) {
try {
trendLine = new TrendLine(timingResults);
} catch (HealthMonitorException ex) {
// Log it, set trendLine to null and continue on
logger.log(Level.WARNING, "Can not generate a trend line on empty data set");
trendLine = null;
}
}
// Calculate these using the full data set, to make it easier to compare the results for
// individual hosts
calcMaxTimestamp(timingResultsFull);
calcMinTimestamp(timingResultsFull);
calcMaxMetricTime(timingResultsFull);
calcMinMetricTime(timingResultsFull);
}
/**
* Set the highest metric time for the given type
*/
private void calcMaxMetricTime(List<DatabaseTimingResult> timingResultsFull) {
// Find the highest of the values being graphed
// individual hosts. Calculate the average at the same time.
maxMetricTime = Double.MIN_VALUE;
for (DatabaseTimingResult score : timingResultsFull) {
// Use only the data we're graphing to determing the max
switch (timingMetricType) {
case MAX:
maxMetricTime = Math.max(maxMetricTime, score.getMax());
break;
case MIN:
maxMetricTime = Math.max(maxMetricTime, score.getMin());
break;
case AVERAGE:
default:
maxMetricTime = Math.max(maxMetricTime, score.getAverage());
break;
}
}
}
/**
* Set the lowest metric time for the given type
*/
private void calcMinMetricTime(List<DatabaseTimingResult> timingResultsFull) {
// Find the lowest of the values being graphed
minMetricTime = Double.MAX_VALUE;
for (DatabaseTimingResult result : timingResultsFull) {
// Use only the data we're graphing to determing the min
switch (timingMetricType) {
case MAX:
minMetricTime = Math.min(minMetricTime, result.getMax());
break;
case MIN:
minMetricTime = Math.min(minMetricTime, result.getMin());
break;
case AVERAGE:
default:
minMetricTime = Math.min(minMetricTime, result.getAverage());
break;
}
}
}
/**
* Set the largest timestamp in the data collection
*/
private void calcMaxTimestamp(List<DatabaseTimingResult> timingResultsFull) {
maxTimestamp = Long.MIN_VALUE;
for (DatabaseTimingResult score : timingResultsFull) {
maxTimestamp = Math.max(maxTimestamp, score.getTimestamp());
}
}
/**
* Set the smallest timestamp in the data collection
*/
private void calcMinTimestamp(List<DatabaseTimingResult> timingResultsFull) {
minTimestamp = Long.MAX_VALUE;
for (DatabaseTimingResult score : timingResultsFull) {
minTimestamp = Math.min(minTimestamp, score.getTimestamp());
double averageMetricTime = 0.0;
for (DatabaseTimingResult result : timingResultsFull) {
maxMetricTime = Math.max(maxMetricTime, result.getAverage());
minMetricTime = Math.min(minMetricTime, result.getAverage());
maxTimestamp = Math.max(maxTimestamp, result.getTimestamp());
minTimestamp = Math.min(minTimestamp, result.getTimestamp());
averageMetricTime += result.getAverage();
}
averageMetricTime = averageMetricTime / timingResultsFull.size();
// If we're omitting outliers, we may use a different maxMetricTime.
// If the max time is reasonably close to the average, do nothing
if (this.skipOutliers && (maxMetricTime > (averageMetricTime * 5))) {
// Calculate the standard deviation
double intermediateValue = 0.0;
for (DatabaseTimingResult result : timingResultsFull) {
double diff = result.getAverage() - averageMetricTime;
intermediateValue += diff * diff;
}
double standardDeviation = Math.sqrt(intermediateValue / timingResultsFull.size());
maxMetricTime = averageMetricTime + standardDeviation;
}
}
/**
* Setup of the graphics panel:
@ -353,20 +314,7 @@ class TimingMetricGraphPanel extends JPanel {
// Create the points to plot
List<Point> graphPoints = new ArrayList<>();
for (int i = 0; i < timingResults.size(); i++) {
double metricTime;
switch (timingMetricType) {
case MAX:
metricTime = timingResults.get(i).getMax();
break;
case MIN:
metricTime = timingResults.get(i).getMin();
break;
case AVERAGE:
default:
metricTime = timingResults.get(i).getAverage();
break;
}
double metricTime = timingResults.get(i).getAverage();
int x1 = (int) ((timingResults.get(i).getTimestamp() - minValueOnXAxis) * xScale + leftGraphPadding);
int y1 = (int) ((maxValueOnYAxis - metricTime) * yScale + topGraphPadding);
@ -410,7 +358,7 @@ class TimingMetricGraphPanel extends JPanel {
// Draw the trend line.
// Don't draw anything if we don't have at least two data points.
if(trendLine != null && (timingResults.size() > 1)) {
if(showTrendLine && (trendLine != null) && (timingResults.size() > 1)) {
double x0value = minValueOnXAxis;
double y0value = trendLine.getExpectedValueAt(x0value);
if (y0value < minValueOnYAxis) {
@ -482,15 +430,6 @@ class TimingMetricGraphPanel extends JPanel {
g2.drawString(titleStr, positionForMetricNameLabel, padding);
}
/**
* The metric field we want to graph
*/
enum TimingMetricType {
AVERAGE,
MAX,
MIN;
}
/**
* Class to generate a linear trend line from timing metric data.
*
@ -507,7 +446,7 @@ class TimingMetricGraphPanel extends JPanel {
double slope;
double yInt;
TrendLine(List<DatabaseTimingResult> timingResults, TimingMetricGraphPanel.TimingMetricType timingMetricType) throws HealthMonitorException {
TrendLine(List<DatabaseTimingResult> timingResults) throws HealthMonitorException {
if((timingResults == null) || timingResults.isEmpty()) {
throw new HealthMonitorException("Can not generate trend line for empty/null data set");
@ -521,19 +460,7 @@ class TimingMetricGraphPanel extends JPanel {
double sumXsquared = 0;
for(int i = 0;i < n;i++) {
double x = timingResults.get(i).getTimestamp();
double y;
switch (timingMetricType) {
case MAX:
y = timingResults.get(i).getMax();
break;
case MIN:
y = timingResults.get(i).getMin();
break;
case AVERAGE:
default:
y = timingResults.get(i).getAverage();
break;
}
double y = timingResults.get(i).getAverage();
sumX += x;
sumY += y;