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)