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> dateComboBox = null;
private JComboBox<String> hostComboBox = null; private JComboBox<String> hostComboBox = null;
private JCheckBox hostCheckBox = null; private JCheckBox hostCheckBox = null;
private JCheckBox showTrendLineCheckBox = null;
private JCheckBox skipOutliersCheckBox = null;
private JPanel graphPanel = null; private JPanel graphPanel = null;
private JDialog dialog = null; private JDialog dialog = null;
private final Container parentWindow; private final Container parentWindow;
@ -200,7 +202,9 @@ public class HealthMonitorDashboard {
* @return the control panel * @return the control panel
*/ */
@NbBundle.Messages({"HealthMonitorDashboard.createTimingControlPanel.filterByHost=Filter by host", @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() { private JPanel createTimingControlPanel() {
JPanel timingControlPanel = new JPanel(); 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 = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_filterByHost());
hostCheckBox.setSelected(false); hostCheckBox.setSelected(false);
hostComboBox.setEnabled(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 // Add the date range combo box and label to the panel
timingControlPanel.add(new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays())); timingControlPanel.add(new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays()));
timingControlPanel.add(dateComboBox); timingControlPanel.add(dateComboBox);
@ -280,6 +316,18 @@ public class HealthMonitorDashboard {
timingControlPanel.add(hostCheckBox); timingControlPanel.add(hostCheckBox);
timingControlPanel.add(hostComboBox); 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; return timingControlPanel;
} }
@ -327,7 +375,7 @@ public class HealthMonitorDashboard {
// Generate the graph // Generate the graph
TimingMetricGraphPanel singleTimingGraphPanel = new TimingMetricGraphPanel(intermediateTimingDataForDisplay, TimingMetricGraphPanel singleTimingGraphPanel = new TimingMetricGraphPanel(intermediateTimingDataForDisplay,
TimingMetricGraphPanel.TimingMetricType.AVERAGE, hostToDisplay, true, metricName); hostToDisplay, true, metricName, skipOutliersCheckBox.isSelected(), showTrendLineCheckBox.isSelected());
singleTimingGraphPanel.setPreferredSize(new Dimension(700,200)); singleTimingGraphPanel.setPreferredSize(new Dimension(700,200));
graphPanel.add(singleTimingGraphPanel); graphPanel.add(singleTimingGraphPanel);

View File

@ -58,9 +58,10 @@ class TimingMetricGraphPanel extends JPanel {
private int pointWidth = 4; private int pointWidth = 4;
private int numberYDivisions = 10; private int numberYDivisions = 10;
private List<DatabaseTimingResult> timingResults; private List<DatabaseTimingResult> timingResults;
private TimingMetricType timingMetricType;
private String metricName; private String metricName;
private boolean doLineGraph; private boolean doLineGraph;
private boolean skipOutliers;
private boolean showTrendLine;
private String yUnitString; private String yUnitString;
private TrendLine trendLine; private TrendLine trendLine;
private final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24; private final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
@ -70,11 +71,12 @@ class TimingMetricGraphPanel extends JPanel {
private double maxMetricTime; private double maxMetricTime;
private double minMetricTime; private double minMetricTime;
TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull, TimingMetricType timingMetricType, TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull,
String hostName, boolean doLineGraph, String metricName) { String hostName, boolean doLineGraph, String metricName, boolean skipOutliers, boolean showTrendLine) {
this.timingMetricType = timingMetricType;
this.doLineGraph = doLineGraph; this.doLineGraph = doLineGraph;
this.skipOutliers = skipOutliers;
this.showTrendLine = showTrendLine;
this.metricName = metricName; this.metricName = metricName;
if(hostName == null || hostName.isEmpty()) { if(hostName == null || hostName.isEmpty()) {
timingResults = timingResultsFull; timingResults = timingResultsFull;
@ -84,90 +86,49 @@ class TimingMetricGraphPanel extends JPanel {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
try { if(showTrendLine) {
trendLine = new TrendLine(timingResults, timingMetricType); try {
} catch (HealthMonitorException ex) { trendLine = new TrendLine(timingResults);
// Log it, set trendLine to null and continue on } catch (HealthMonitorException ex) {
logger.log(Level.WARNING, "Can not generate a trend line on empty data set"); // Log it, set trendLine to null and continue on
trendLine = null; 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 // Calculate these using the full data set, to make it easier to compare the results for
// individual hosts // individual hosts. Calculate the average at the same time.
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
maxMetricTime = Double.MIN_VALUE; 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; 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; 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; minTimestamp = Long.MAX_VALUE;
for (DatabaseTimingResult score : timingResultsFull) { double averageMetricTime = 0.0;
minTimestamp = Math.min(minTimestamp, score.getTimestamp()); 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: * Setup of the graphics panel:
* Origin (0,0) is at the top left corner * Origin (0,0) is at the top left corner
@ -353,20 +314,7 @@ class TimingMetricGraphPanel extends JPanel {
// Create the points to plot // Create the points to plot
List<Point> graphPoints = new ArrayList<>(); List<Point> graphPoints = new ArrayList<>();
for (int i = 0; i < timingResults.size(); i++) { for (int i = 0; i < timingResults.size(); i++) {
double metricTime; double metricTime = timingResults.get(i).getAverage();
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;
}
int x1 = (int) ((timingResults.get(i).getTimestamp() - minValueOnXAxis) * xScale + leftGraphPadding); int x1 = (int) ((timingResults.get(i).getTimestamp() - minValueOnXAxis) * xScale + leftGraphPadding);
int y1 = (int) ((maxValueOnYAxis - metricTime) * yScale + topGraphPadding); int y1 = (int) ((maxValueOnYAxis - metricTime) * yScale + topGraphPadding);
@ -410,7 +358,7 @@ class TimingMetricGraphPanel extends JPanel {
// Draw the trend line. // Draw the trend line.
// Don't draw anything if we don't have at least two data points. // 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 x0value = minValueOnXAxis;
double y0value = trendLine.getExpectedValueAt(x0value); double y0value = trendLine.getExpectedValueAt(x0value);
if (y0value < minValueOnYAxis) { if (y0value < minValueOnYAxis) {
@ -482,15 +430,6 @@ class TimingMetricGraphPanel extends JPanel {
g2.drawString(titleStr, positionForMetricNameLabel, padding); 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. * Class to generate a linear trend line from timing metric data.
* *
@ -507,7 +446,7 @@ class TimingMetricGraphPanel extends JPanel {
double slope; double slope;
double yInt; double yInt;
TrendLine(List<DatabaseTimingResult> timingResults, TimingMetricGraphPanel.TimingMetricType timingMetricType) throws HealthMonitorException { TrendLine(List<DatabaseTimingResult> timingResults) throws HealthMonitorException {
if((timingResults == null) || timingResults.isEmpty()) { if((timingResults == null) || timingResults.isEmpty()) {
throw new HealthMonitorException("Can not generate trend line for empty/null data set"); throw new HealthMonitorException("Can not generate trend line for empty/null data set");
@ -521,19 +460,7 @@ class TimingMetricGraphPanel extends JPanel {
double sumXsquared = 0; double sumXsquared = 0;
for(int i = 0;i < n;i++) { for(int i = 0;i < n;i++) {
double x = timingResults.get(i).getTimestamp(); double x = timingResults.get(i).getTimestamp();
double y; double y = timingResults.get(i).getAverage();
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;
}
sumX += x; sumX += x;
sumY += y; sumY += y;