19 package org.sleuthkit.autopsy.healthmonitor;
21 import java.awt.Container;
22 import java.awt.Cursor;
23 import java.awt.Dimension;
25 import java.util.HashSet;
26 import java.util.HashMap;
27 import java.util.Arrays;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
33 import javax.swing.Box;
34 import javax.swing.JButton;
35 import javax.swing.JDialog;
36 import javax.swing.JComboBox;
37 import javax.swing.JSeparator;
38 import javax.swing.JCheckBox;
39 import javax.swing.JLabel;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.BorderFactory;
44 import javax.swing.BoxLayout;
45 import java.awt.GridLayout;
46 import java.nio.file.Paths;
47 import java.util.logging.Level;
48 import java.util.stream.Collectors;
49 import org.openide.util.NbBundle;
84 timingData =
new HashMap<>();
85 userData =
new ArrayList<>();
86 parentWindow = parent;
92 @NbBundle.Messages({
"HealthMonitorDashboard.display.errorCreatingDashboard=Error creating health monitor dashboard",
93 "HealthMonitorDashboard.display.dashboardTitle=Health Monitor"})
106 }
catch (HealthMonitorException ex) {
107 logger.log(Level.SEVERE,
"Error creating panels for health monitor dashboard", ex);
113 JPanel mainPanel =
new JPanel();
114 mainPanel.setLayout(
new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
117 mainPanel.add(timingPanel);
120 mainPanel.add(userPanel);
123 File adminFile =
new File(ADMIN_ACCESS_FILE_PATH);
124 if(adminFile.exists()) {
125 mainPanel.add(adminPanel);
129 dialog =
new JDialog();
130 dialog.setTitle(Bundle.HealthMonitorDashboard_display_dashboardTitle());
131 dialog.add(mainPanel);
133 dialog.setLocationRelativeTo(parentWindow);
134 dialog.setVisible(
true);
142 if (dialog != null) {
143 dialog.setVisible(
false);
172 @NbBundle.Messages({
"HealthMonitorDashboard.createTimingPanel.noData=No data to display - monitor is not enabled",
173 "HealthMonitorDashboard.createTimingPanel.timingMetricsTitle=Timing Metrics"})
179 JPanel emptyTimingMetricPanel =
new JPanel();
180 emptyTimingMetricPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createTimingPanel_timingMetricsTitle()));
181 emptyTimingMetricPanel.add(
new JLabel(
" "));
182 emptyTimingMetricPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createTimingPanel_noData()));
184 return emptyTimingMetricPanel;
187 JPanel timingMetricPanel =
new JPanel();
188 timingMetricPanel.setLayout(
new BoxLayout(timingMetricPanel, BoxLayout.PAGE_AXIS));
189 timingMetricPanel.setBorder(BorderFactory.createEtchedBorder());
192 JLabel timingMetricTitle =
new JLabel(Bundle.HealthMonitorDashboard_createTimingPanel_timingMetricsTitle());
193 timingMetricPanel.add(timingMetricTitle);
194 timingMetricPanel.add(
new JSeparator());
198 timingMetricPanel.add(
new JSeparator());
201 timingGraphPanel =
new JPanel();
202 timingGraphPanel.setLayout(
new GridLayout(0,2));
206 JScrollPane scrollPane =
new JScrollPane(timingGraphPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
207 timingMetricPanel.add(scrollPane);
208 timingMetricPanel.revalidate();
209 timingMetricPanel.repaint();
211 return timingMetricPanel;
218 @NbBundle.Messages({
"HealthMonitorDashboard.createTimingControlPanel.filterByHost=Filter by host",
219 "HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display",
220 "HealthMonitorDashboard.createTimingControlPanel.skipOutliers=Do not plot outliers",
221 "HealthMonitorDashboard.createTimingControlPanel.showTrendLine=Show trend line"})
223 JPanel timingControlPanel =
new JPanel();
227 return timingControlPanel;
231 String[] dateOptionStrings = Arrays.stream(
DateRange.values()).map(e -> e.getLabel()).toArray(String[]::
new);
232 timingDateComboBox =
new JComboBox<>(dateOptionStrings);
236 timingDateComboBox.addActionListener(
new ActionListener() {
238 public void actionPerformed(ActionEvent arg0) {
241 }
catch (HealthMonitorException ex) {
242 logger.log(Level.SEVERE,
"Error updating timing metric panel", ex);
248 Set<String> hostNameSet =
new HashSet<>();
249 for(String metricType:timingData.keySet()) {
251 hostNameSet.add(result.getHostName());
256 timingHostComboBox =
new JComboBox<>(hostNameSet.toArray(
new String[hostNameSet.size()]));
259 timingHostComboBox.addActionListener(
new ActionListener() {
261 public void actionPerformed(ActionEvent arg0) {
263 if((timingHostCheckBox != null) && timingHostCheckBox.isSelected()) {
266 }
catch (HealthMonitorException ex) {
267 logger.log(Level.SEVERE,
"Error populating timing metric panel", ex);
273 timingHostCheckBox =
new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_filterByHost());
274 timingHostCheckBox.setSelected(
false);
275 timingHostComboBox.setEnabled(
false);
278 timingHostCheckBox.addActionListener(
new ActionListener() {
280 public void actionPerformed(ActionEvent arg0) {
282 timingHostComboBox.setEnabled(timingHostCheckBox.isSelected());
284 }
catch (HealthMonitorException ex) {
285 logger.log(Level.SEVERE,
"Error populating timing metric panel", ex);
291 timingShowTrendLineCheckBox =
new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_showTrendLine());
292 timingShowTrendLineCheckBox.setSelected(
true);
295 timingShowTrendLineCheckBox.addActionListener(
new ActionListener() {
297 public void actionPerformed(ActionEvent arg0) {
300 }
catch (HealthMonitorException ex) {
301 logger.log(Level.SEVERE,
"Error populating timing metric panel", ex);
307 timingSkipOutliersCheckBox =
new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_skipOutliers());
308 timingSkipOutliersCheckBox.setSelected(
false);
311 timingSkipOutliersCheckBox.addActionListener(
new ActionListener() {
313 public void actionPerformed(ActionEvent arg0) {
316 }
catch (HealthMonitorException ex) {
317 logger.log(Level.SEVERE,
"Error populating timing metric panel", ex);
323 timingControlPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays()));
324 timingControlPanel.add(timingDateComboBox);
327 timingControlPanel.add(Box.createHorizontalStrut(100));
330 timingControlPanel.add(timingHostCheckBox);
331 timingControlPanel.add(timingHostComboBox);
334 timingControlPanel.add(Box.createHorizontalStrut(100));
337 timingControlPanel.add(this.timingShowTrendLineCheckBox);
340 timingControlPanel.add(Box.createHorizontalStrut(100));
343 timingControlPanel.add(this.timingSkipOutliersCheckBox);
345 return timingControlPanel;
352 @NbBundle.Messages({
"HealthMonitorDashboard.updateTimingMetricGraphs.noData=No data to display"})
356 timingGraphPanel.removeAll();
358 if(timingData.keySet().isEmpty()) {
360 timingGraphPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_updateTimingMetricGraphs_noData()));
364 for(String metricName:timingData.keySet()) {
368 if(timingDateComboBox.getSelectedItem() != null) {
370 long threshold = System.currentTimeMillis() - selectedDateRange.
getTimestampRange();
371 intermediateTimingDataForDisplay = timingData.get(metricName).stream()
372 .filter(t -> t.getTimestamp() > threshold)
373 .collect(Collectors.toList());
375 intermediateTimingDataForDisplay = timingData.get(metricName);
381 String hostToDisplay = null;
382 if(timingHostCheckBox.isSelected() && (timingHostComboBox.getSelectedItem() != null)) {
383 hostToDisplay = timingHostComboBox.getSelectedItem().toString();
387 TimingMetricGraphPanel singleTimingGraphPanel =
new TimingMetricGraphPanel(intermediateTimingDataForDisplay,
388 hostToDisplay,
true, metricName, timingSkipOutliersCheckBox.isSelected(), timingShowTrendLineCheckBox.isSelected());
389 singleTimingGraphPanel.setPreferredSize(
new Dimension(700,200));
391 timingGraphPanel.add(singleTimingGraphPanel);
393 timingGraphPanel.revalidate();
394 timingGraphPanel.repaint();
402 @NbBundle.Messages({
"HealthMonitorDashboard.createUserPanel.noData=No data to display - monitor is not enabled",
403 "HealthMonitorDashboard.createUserPanel.userMetricsTitle=User Metrics"})
407 JPanel emptyUserMetricPanel =
new JPanel();
408 emptyUserMetricPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createUserPanel_userMetricsTitle()));
409 emptyUserMetricPanel.add(
new JLabel(
" "));
410 emptyUserMetricPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createUserPanel_noData()));
412 return emptyUserMetricPanel;
415 JPanel userMetricPanel =
new JPanel();
416 userMetricPanel.setLayout(
new BoxLayout(userMetricPanel, BoxLayout.PAGE_AXIS));
417 userMetricPanel.setBorder(BorderFactory.createEtchedBorder());
420 JLabel userMetricTitle =
new JLabel(Bundle.HealthMonitorDashboard_createUserPanel_userMetricsTitle());
421 userMetricPanel.add(userMetricTitle);
422 userMetricPanel.add(
new JSeparator());
426 userMetricPanel.add(
new JSeparator());
429 userGraphPanel =
new JPanel();
430 userGraphPanel.setLayout(
new GridLayout(0,2));
434 JScrollPane scrollPane =
new JScrollPane(userGraphPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
435 userMetricPanel.add(scrollPane);
436 userMetricPanel.revalidate();
437 userMetricPanel.repaint();
439 return userMetricPanel;
446 @NbBundle.Messages({
"HealthMonitorDashboard.createUserControlPanel.maxDays=Max days to display"})
448 JPanel userControlPanel =
new JPanel();
452 return userControlPanel;
456 String[] dateOptionStrings = Arrays.stream(
DateRange.values()).map(e -> e.getLabel()).toArray(String[]::
new);
457 userDateComboBox =
new JComboBox<>(dateOptionStrings);
461 userDateComboBox.addActionListener(
new ActionListener() {
463 public void actionPerformed(ActionEvent arg0) {
466 }
catch (HealthMonitorException ex) {
467 logger.log(Level.SEVERE,
"Error updating user metric panel", ex);
473 userControlPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_createUserControlPanel_maxDays()));
474 userControlPanel.add(userDateComboBox);
476 return userControlPanel;
483 @NbBundle.Messages({
"HealthMonitorDashboard.updateUserMetricGraphs.noData=No data to display"})
487 userGraphPanel.removeAll();
489 if(userData.isEmpty()) {
491 userGraphPanel.add(
new JLabel(Bundle.HealthMonitorDashboard_updateUserMetricGraphs_noData()));
500 long timestampThreshold;
501 if(userDateComboBox.getSelectedItem() != null) {
503 timestampThreshold = System.currentTimeMillis() - selectedDateRange.
getTimestampRange();
510 UserMetricGraphPanel caseGraphPanel =
new UserMetricGraphPanel(userData, timestampThreshold,
true);
511 caseGraphPanel.setPreferredSize(
new Dimension(700,200));
513 UserMetricGraphPanel logonGraphPanel =
new UserMetricGraphPanel(userData, timestampThreshold,
false);
514 logonGraphPanel.setPreferredSize(
new Dimension(700,200));
516 userGraphPanel.add(caseGraphPanel);
517 userGraphPanel.add(logonGraphPanel);
518 userGraphPanel.revalidate();
519 userGraphPanel.repaint();
527 @NbBundle.Messages({
"HealthMonitorDashboard.createAdminPanel.enableButton=Enable monitor",
528 "HealthMonitorDashboard.createAdminPanel.disableButton=Disable monitor"})
531 JPanel adminPanel =
new JPanel();
532 adminPanel.setBorder(BorderFactory.createEtchedBorder());
535 JButton enableButton =
new JButton(Bundle.HealthMonitorDashboard_createAdminPanel_enableButton());
536 JButton disableButton =
new JButton(Bundle.HealthMonitorDashboard_createAdminPanel_disableButton());
539 enableButton.setEnabled(! isEnabled);
540 disableButton.setEnabled(isEnabled);
543 enableButton.addActionListener(
new ActionListener() {
545 public void actionPerformed(ActionEvent arg0) {
547 dialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
550 }
catch (HealthMonitorException ex) {
551 logger.log(Level.SEVERE,
"Error enabling monitoring", ex);
553 dialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
559 disableButton.addActionListener(
new ActionListener() {
561 public void actionPerformed(ActionEvent arg0) {
563 dialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
566 }
catch (HealthMonitorException ex) {
567 logger.log(Level.SEVERE,
"Error disabling monitoring", ex);
569 dialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
575 adminPanel.add(enableButton);
576 adminPanel.add(Box.createHorizontalStrut(25));
577 adminPanel.add(disableButton);
585 @NbBundle.Messages({
"HealthMonitorDashboard.DateRange.oneMonth=One month",
586 "HealthMonitorDashboard.DateRange.twoWeeks=Two weeks",
587 "HealthMonitorDashboard.DateRange.oneWeek=One week",
588 "HealthMonitorDashboard.DateRange.oneDay=One day"})
590 ONE_DAY(Bundle.HealthMonitorDashboard_DateRange_oneDay(), 1),
591 ONE_WEEK(Bundle.HealthMonitorDashboard_DateRange_oneWeek(), 7),
592 TWO_WEEKS(Bundle.HealthMonitorDashboard_DateRange_twoWeeks(), 14),
593 ONE_MONTH(Bundle.HealthMonitorDashboard_DateRange_oneMonth(), 31);
597 private static final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
601 this.numberOfDays = numberOfDays;
619 if (numberOfDays > 0) {
620 return numberOfDays * MILLISECONDS_PER_DAY;
622 return Long.MAX_VALUE;
632 long maxRange = Long.MIN_VALUE;
634 if (dateRange.getTimestampRange() > maxRange) {
635 maxRange = dateRange.getTimestampRange();
643 if (dateRange.label.equalsIgnoreCase(text)) {
JPanel createTimingPanel()
JCheckBox timingSkipOutliersCheckBox
final Container parentWindow
static DateRange fromLabel(String text)
HealthMonitorDashboard(Container parent)
JPanel createTimingControlPanel()
static final String ADMIN_ACCESS_FILE_NAME
JPanel createAdminPanel()
JCheckBox timingShowTrendLineCheckBox
DateRange(String label, long numberOfDays)
void updateTimingMetricGraphs()
JCheckBox timingHostCheckBox
static final String ADMIN_ACCESS_FILE_PATH
JPanel createUserControlPanel()
JComboBox< String > timingHostComboBox
JComboBox< String > timingDateComboBox
JComboBox< String > userDateComboBox
void updateUserMetricGraphs()
synchronized static Logger getLogger(String name)
static final Logger logger
static long getMaximumTimestampRange()
static void error(String message)