From 6002f31e62bd2cf3fc62b2fd4235df2e68c3c082 Mon Sep 17 00:00:00 2001 From: Alex Borshik Date: Fri, 15 Nov 2024 11:50:02 +0000 Subject: [PATCH] Reduce memory usage, allow selection of multiple metrics in MetricsPane [HZG-208] (#7) This PR reduces the memory footprint while loading large diagnostics files. Previously each individual `DiagnosticFile` contained an index for the metric entries contained within it. Now there is a single index per instance of `InstanceDiagnostics`, this hugely reduces the number of index entries needed and allows the tool to load several gigabytes of diagnostic logs. In addition a number of IDE compiler warnings have been fixed and the `MetricsPane` has been updated to allow selection and comparison of multiple metrics. --- .../hazelcast/diagnostics/AutoCompletion.java | 202 --------- .../hazelcast/diagnostics/BuildInfoPane.java | 11 +- .../hazelcast/diagnostics/ConnectionPane.java | 16 +- .../diagnostics/CpuUtilizationPane.java | 20 +- .../hazelcast/diagnostics/DashboardPane.java | 58 ++- .../hazelcast/diagnostics/HeartbeatPane.java | 16 +- .../diagnostics/InstanceDiagnostics.java | 409 +++++++++--------- .../hazelcast/diagnostics/InstancesPane.java | 20 +- .../diagnostics/InvocationProfilerPane.java | 7 +- .../diagnostics/InvocationsPlane.java | 24 +- .../diagnostics/LatencyDistributionPane.java | 33 +- .../java/com/hazelcast/diagnostics/Main.java | 8 +- .../com/hazelcast/diagnostics/MainWindow.java | 71 +-- .../com/hazelcast/diagnostics/MemberPane.java | 10 +- .../com/hazelcast/diagnostics/MemoryPane.java | 22 +- .../hazelcast/diagnostics/MetricsPane.java | 113 ++--- .../diagnostics/OperationsPlane.java | 24 +- .../hazelcast/diagnostics/PendingPane.java | 18 +- .../diagnostics/SlowOperationsPane.java | 14 +- .../com/hazelcast/diagnostics/StatusBar.java | 25 +- .../diagnostics/SystemPropertiesPane.java | 11 +- .../diagnostics/TimeSelectorPane.java | 15 +- .../com/hazelcast/diagnostics/WANPane.java | 16 +- 23 files changed, 483 insertions(+), 680 deletions(-) delete mode 100644 src/main/java/com/hazelcast/diagnostics/AutoCompletion.java diff --git a/src/main/java/com/hazelcast/diagnostics/AutoCompletion.java b/src/main/java/com/hazelcast/diagnostics/AutoCompletion.java deleted file mode 100644 index 722057f..0000000 --- a/src/main/java/com/hazelcast/diagnostics/AutoCompletion.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.hazelcast.diagnostics; - -import java.awt.event.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.*; -import javax.swing.text.*; - -/* This work is hereby released into the Public Domain. - * To view a copy of the public domain dedication, visit - * http://creativecommons.org/licenses/publicdomain/ - */ -public class AutoCompletion extends PlainDocument { - JComboBox comboBox; - ComboBoxModel model; - JTextComponent editor; - // flag to indicate if setSelectedItem has been called - // subsequent calls to remove/insertString should be ignored - boolean selecting=false; - boolean hidePopupOnFocusLoss; - boolean hitBackspace=false; - boolean hitBackspaceOnSelection; - - KeyListener editorKeyListener; - FocusListener editorFocusListener; - - public AutoCompletion(final JComboBox comboBox) { - this.comboBox = comboBox; - model = comboBox.getModel(); - comboBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (!selecting) highlightCompletedText(0); - } - }); - comboBox.addPropertyChangeListener(new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals("editor")) configureEditor((ComboBoxEditor) e.getNewValue()); - if (e.getPropertyName().equals("model")) model = (ComboBoxModel) e.getNewValue(); - } - }); - editorKeyListener = new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (comboBox.isDisplayable()) comboBox.setPopupVisible(true); - hitBackspace=false; - switch (e.getKeyCode()) { - // determine if the pressed key is backspace (needed by the remove method) - case KeyEvent.VK_BACK_SPACE : hitBackspace=true; - hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd(); - break; - // ignore delete key - case KeyEvent.VK_DELETE : e.consume(); - comboBox.getToolkit().beep(); - break; - } - } - }; - // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out - hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5"); - // Highlight whole text when gaining focus - editorFocusListener = new FocusAdapter() { - public void focusGained(FocusEvent e) { - highlightCompletedText(0); - } - public void focusLost(FocusEvent e) { - // Workaround for Bug 5100422 - Hide Popup on focus loss - if (hidePopupOnFocusLoss) comboBox.setPopupVisible(false); - } - }; - configureEditor(comboBox.getEditor()); - // Handle initially selected object - Object selected = comboBox.getSelectedItem(); - if (selected!=null) setText(selected.toString()); - highlightCompletedText(0); - } - - public static void enable(JComboBox comboBox) { - // has to be editable - comboBox.setEditable(true); - // change the editor's document - new AutoCompletion(comboBox); - } - - void configureEditor(ComboBoxEditor newEditor) { - if (editor != null) { - editor.removeKeyListener(editorKeyListener); - editor.removeFocusListener(editorFocusListener); - } - - if (newEditor != null) { - editor = (JTextComponent) newEditor.getEditorComponent(); - editor.addKeyListener(editorKeyListener); - editor.addFocusListener(editorFocusListener); - editor.setDocument(this); - } - } - - public void remove(int offs, int len) throws BadLocationException { - // return immediately when selecting an item - if (selecting) return; - if (hitBackspace) { - // user hit backspace => move the selection backwards - // old item keeps being selected - if (offs>0) { - if (hitBackspaceOnSelection) offs--; - } else { - // User hit backspace with the cursor positioned on the start => beep - comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox); - } - highlightCompletedText(offs); - } else { - super.remove(offs, len); - } - } - - public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { - // return immediately when selecting an item - if (selecting) return; - // insert the string into the document - super.insertString(offs, str, a); - // lookup and select a matching item - Object item = lookupItem(getText(0, getLength())); - if (item != null) { - setSelectedItem(item); - } else { - // keep old item selected if there is no match - item = comboBox.getSelectedItem(); - // imitate no insert (later on offs will be incremented by str.length(): selection won't move forward) - offs = offs-str.length(); - // provide feedback to the user that his input has been received but can not be accepted - comboBox.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox); - } - setText(item.toString()); - // select the completed part - highlightCompletedText(offs+str.length()); - } - - private void setText(String text) { - try { - // remove all text and insert the completed string - super.remove(0, getLength()); - super.insertString(0, text, null); - } catch (BadLocationException e) { - throw new RuntimeException(e.toString()); - } - } - - private void highlightCompletedText(int start) { - editor.setCaretPosition(getLength()); - editor.moveCaretPosition(start); - } - - private void setSelectedItem(Object item) { - selecting = true; - model.setSelectedItem(item); - selecting = false; - } - - private Object lookupItem(String pattern) { - Object selectedItem = model.getSelectedItem(); - // only search for a different item if the currently selected does not match - if (selectedItem != null && startsWithIgnoreCase(selectedItem.toString(), pattern)) { - return selectedItem; - } else { - // iterate over all items - for (int i=0, n=model.getSize(); i < n; i++) { - Object currentItem = model.getElementAt(i); - // current item starts with the pattern? - if (currentItem != null && startsWithIgnoreCase(currentItem.toString(), pattern)) { - return currentItem; - } - } - } - // no item starts with the pattern => return null - return null; - } - - // checks if str1 starts with str2 - ignores case - private boolean startsWithIgnoreCase(String str1, String str2) { - return str1.toUpperCase().startsWith(str2.toUpperCase()); - } - - private static void createAndShowGUI() { - // the combo box (add/modify items if you like to) - final JComboBox comboBox = new JComboBox(new Object[] {"Ester", "Jordi", "Jordina", "Jorge", "Sergi"}); - enable(comboBox); - - // create and show a window containing the combo box - final JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(3); - frame.getContentPane().add(comboBox); - frame.pack(); frame.setVisible(true); - } - - - public static void main(String[] args) { - javax.swing.SwingUtilities.invokeLater(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } -} diff --git a/src/main/java/com/hazelcast/diagnostics/BuildInfoPane.java b/src/main/java/com/hazelcast/diagnostics/BuildInfoPane.java index f533930..99f3d0f 100644 --- a/src/main/java/com/hazelcast/diagnostics/BuildInfoPane.java +++ b/src/main/java/com/hazelcast/diagnostics/BuildInfoPane.java @@ -1,18 +1,21 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import java.util.Iterator; import java.util.Map; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_BUILD_INFO; + public class BuildInfoPane { - private final JTable table; private final DefaultTableModel model; private final JScrollPane pane; public BuildInfoPane() { - table = new JTable(); + JTable table = new JTable(); model = new DefaultTableModel(); table.setModel(model); model.addColumn("Key"); @@ -31,7 +34,7 @@ public void setInstanceDiagnostics(InstanceDiagnostics diagnostics) { return; } - Iterator> it = diagnostics.between(InstanceDiagnostics.TYPE_BUILD_INFO, 0, Long.MAX_VALUE); + Iterator> it = diagnostics.between(TYPE_BUILD_INFO, 0, Long.MAX_VALUE); if (!it.hasNext()) { System.out.println("No BuildInfo found in directory: " + diagnostics.getDirectory()); return; diff --git a/src/main/java/com/hazelcast/diagnostics/ConnectionPane.java b/src/main/java/com/hazelcast/diagnostics/ConnectionPane.java index 1f97007..0af2dd8 100644 --- a/src/main/java/com/hazelcast/diagnostics/ConnectionPane.java +++ b/src/main/java/com/hazelcast/diagnostics/ConnectionPane.java @@ -1,6 +1,8 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -8,6 +10,8 @@ import java.util.Map; import java.util.TreeMap; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_CONNECTION; + public class ConnectionPane { private final JComponent component; @@ -37,9 +41,9 @@ public void update() { return; } - TreeMap> treeMap = new TreeMap(); + TreeMap> treeMap = new TreeMap<>(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.between(InstanceDiagnostics.TYPE_CONNECTION, startMs, endMs); + Iterator> iterator = diagnostics.between(TYPE_CONNECTION, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -48,11 +52,7 @@ public void update() { while (iterator.hasNext()) { Map.Entry entry = iterator.next(); Long key = entry.getKey(); - List list = treeMap.get(key); - if (list == null) { - list = new ArrayList<>(); - treeMap.put(key, list); - } + List list = treeMap.computeIfAbsent(key, k -> new ArrayList<>()); list.add(entry.getValue()); } } diff --git a/src/main/java/com/hazelcast/diagnostics/CpuUtilizationPane.java b/src/main/java/com/hazelcast/diagnostics/CpuUtilizationPane.java index f77932f..452fcd1 100644 --- a/src/main/java/com/hazelcast/diagnostics/CpuUtilizationPane.java +++ b/src/main/java/com/hazelcast/diagnostics/CpuUtilizationPane.java @@ -10,7 +10,8 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Iterator; @@ -19,8 +20,6 @@ public class CpuUtilizationPane { private final JPanel component; - private final JFreeChart chart; - private final ChartPanel chartPanel; private final TimeSeriesCollection collection; private long startMs = Long.MIN_VALUE; private long endMs = Long.MAX_VALUE; @@ -28,16 +27,10 @@ public class CpuUtilizationPane { public CpuUtilizationPane() { collection = new TimeSeriesCollection(); - chart = ChartFactory.createTimeSeriesChart( - "CPU Utilization", - "Time", - "Utilization", - collection, - true, - true, + JFreeChart chart = ChartFactory.createTimeSeriesChart("CPU Utilization", "Time", "Utilization", collection, true, true, false); - this.chartPanel = new ChartPanel(chart); - XYPlot plot = (XYPlot)chartPanel.getChart().getPlot(); + ChartPanel chartPanel = new ChartPanel(chart); + XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis)plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); this.component = chartPanel; @@ -56,7 +49,8 @@ public void update() { collection.removeAllSeries(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.metricsBetween("[metric=os.processCpuLoad]", startMs, endMs); + Iterator> iterator = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_OS_PROCESS_CPU_LOAD, startMs, endMs); if (!iterator.hasNext()) { continue; diff --git a/src/main/java/com/hazelcast/diagnostics/DashboardPane.java b/src/main/java/com/hazelcast/diagnostics/DashboardPane.java index 141d9ed..889aa79 100644 --- a/src/main/java/com/hazelcast/diagnostics/DashboardPane.java +++ b/src/main/java/com/hazelcast/diagnostics/DashboardPane.java @@ -9,28 +9,26 @@ import org.jfree.data.general.DefaultValueDataset; import org.jfree.data.general.ValueDataset; -import javax.swing.*; -import java.awt.*; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.Label; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Map; public class DashboardPane { - private static final String INVOCATION_PROFILE_MARKER = "InvocationProfiler["; private final JPanel pane; - private final JFreeChart heapChart; - private final JFreeChart cpuChart; + private final MeterPlot heapPlot; + private final MeterPlot cpuPlot; - private final ChartPanel heapChartPanel; - private final ChartPanel cpuChartPanel; - - private MeterPlot heapPlot; - private MeterPlot cpuPlot; - - ValueDataset heapDataset; - ValueDataset cpuDataset; + private ValueDataset heapDataset; + private ValueDataset cpuDataset; private long startMs = Long.MIN_VALUE; private long endMs = Long.MAX_VALUE; private Collection instanceDiagnosticsColl = new ArrayList<>(); @@ -46,18 +44,16 @@ public DashboardPane() { configureCPUPlot(); configureHeapPlot(); - heapChart = new JFreeChart("Heap Memory", JFreeChart.DEFAULT_TITLE_FONT, heapPlot, false); - cpuChart = new JFreeChart("CPU", JFreeChart.DEFAULT_TITLE_FONT, cpuPlot, false); - + JFreeChart heapChart = new JFreeChart("Heap Memory", JFreeChart.DEFAULT_TITLE_FONT, heapPlot, false); + JFreeChart cpuChart = new JFreeChart("CPU", JFreeChart.DEFAULT_TITLE_FONT, cpuPlot, false); JTabbedPane jTabbedPane = new JTabbedPane(); jTabbedPane.setTabPlacement(JTabbedPane.TOP); jTabbedPane.addTab("Heap", new Label("heap")); jTabbedPane.addTab("CPU", new Label("cpu")); - - heapChartPanel = new ChartPanel(heapChart); - cpuChartPanel = new ChartPanel(cpuChart); + ChartPanel heapChartPanel = new ChartPanel(heapChart); + ChartPanel cpuChartPanel = new ChartPanel(cpuChart); JPanel gaugePanel = new JPanel(); gaugePanel.setLayout(new GridLayout(1, 2)); @@ -135,15 +131,19 @@ public JComponent getComponent() { public void update() { Long maxUsedHeap = 0L; - Long maxHeap = 0L; + long maxHeap = 0L; Double maxCPULoad = 0D; - Long totalMemory = 0L; + long totalMemory = 0L; for (InstanceDiagnostics diagnostics : instanceDiagnosticsColl) { - Iterator> iteratorUsedHeap = diagnostics.metricsBetween("[unit=bytes,metric=memory.usedHeap]", startMs, endMs); - Iterator> iteratorMaxHeap = diagnostics.metricsBetween("[unit=bytes,metric=memory.maxHeap]", startMs, endMs); - Iterator> iteratorCPULoad = diagnostics.metricsBetween("[metric=os.processCpuLoad]", startMs, endMs); - Iterator> iteratorTotalMemory = diagnostics.metricsBetween("[metric=runtime.totalMemory]", startMs, endMs); + Iterator> iteratorUsedHeap = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_MEMORY_USED_HEAP, startMs, endMs); + Iterator> iteratorMaxHeap = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_MEMORY_MAX_HEAP, startMs, endMs); + Iterator> iteratorCPULoad = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_OS_PROCESS_CPU_LOAD, startMs, endMs); + Iterator> iteratorTotalMemory = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_RUNTIME_TOTAL_MEMORY, startMs, endMs); while (iteratorUsedHeap.hasNext()) { Map.Entry entry = iteratorUsedHeap.next(); @@ -162,18 +162,14 @@ public void update() { while (iteratorTotalMemory.hasNext()) { Map.Entry entry = iteratorTotalMemory.next(); - totalMemory = entry.getValue().longValue() > totalMemory ? entry.getValue().longValue() : totalMemory; + totalMemory = Math.max(entry.getValue().longValue(), totalMemory); } } - heapDataset = new DefaultValueDataset(maxUsedHeap); updateHeapPlot(heapDataset, totalMemory); cpuDataset = new DefaultValueDataset(maxCPULoad); updateCPUPlot(cpuDataset); - } - - -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/HeartbeatPane.java b/src/main/java/com/hazelcast/diagnostics/HeartbeatPane.java index e502d71..950a45e 100644 --- a/src/main/java/com/hazelcast/diagnostics/HeartbeatPane.java +++ b/src/main/java/com/hazelcast/diagnostics/HeartbeatPane.java @@ -1,6 +1,8 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -8,6 +10,8 @@ import java.util.Map; import java.util.TreeMap; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_HEARTBEAT; + public class HeartbeatPane { private final JComponent component; private final JTextArea textArea; @@ -36,9 +40,9 @@ public void update() { return; } - TreeMap> treeMap = new TreeMap(); + TreeMap> treeMap = new TreeMap<>(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.between(InstanceDiagnostics.TYPE_HEARTBEAT, startMs, endMs); + Iterator> iterator = diagnostics.between(TYPE_HEARTBEAT, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -47,11 +51,7 @@ public void update() { while (iterator.hasNext()) { Map.Entry entry = iterator.next(); Long key = entry.getKey(); - List list = treeMap.get(key); - if (list == null) { - list = new ArrayList<>(); - treeMap.put(key, list); - } + List list = treeMap.computeIfAbsent(key, k -> new ArrayList<>()); list.add(entry.getValue()); } } diff --git a/src/main/java/com/hazelcast/diagnostics/InstanceDiagnostics.java b/src/main/java/com/hazelcast/diagnostics/InstanceDiagnostics.java index fe2ef66..abd07cd 100644 --- a/src/main/java/com/hazelcast/diagnostics/InstanceDiagnostics.java +++ b/src/main/java/com/hazelcast/diagnostics/InstanceDiagnostics.java @@ -12,34 +12,30 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.SortedMap; import java.util.TreeMap; public class InstanceDiagnostics { - public static final int TYPE_UNKNOWN = 0; - public static final int TYPE_METRIC = 1; - public static final int TYPE_BUILD_INFO = 2; - public static final int TYPE_SYSTEM_PROPERTIES = 3; - public static final int TYPE_CONFIG_PROPERTIES = 4; - public static final int TYPE_SLOW_OPERATIONS = 5; - public static final int TYPE_INVOCATIONS = 6; - public static final int TYPE_INVOCATION_PROFILER = 7; - public static final int TYPE_OPERATION_PROFILER = 8; - public static final int TYPE_OPERATION_THREAD_SAMPLES = 9; - public static final int TYPE_CONNECTION = 10; - public static final int TYPE_HAZELCAST_INSTANCE = 11; - public static final int TYPE_MEMBER = 12; - public static final int TYPE_CLUSTER_VERSION_CHANGE = 13; - public static final int TYPE_LIFECYCLE = 14; - public static final int TYPE_WAN = 15; - public static final int TYPE_HEARTBEAT = 16; - public static final int TYPES = TYPE_HEARTBEAT + 1; - - private File directory; - private List diagnosticsFiles; + + public static final String METRIC_OPERATION_INVOCATIONS_PENDING = "[unit=count,metric=operation.invocations.pending]"; + public static final String METRIC_OPERATION_QUEUE_SIZE = "[unit=count,metric=operation.queueSize]"; + public static final String METRIC_RUNTIME_USED_MEMORY = "[metric=runtime.usedMemory]"; + public static final String METRIC_OPERATION_INVOCATIONS_LAST_CALL_ID = "[unit=count,metric=operation.invocations.lastCallId]"; + public static final String METRIC_OPERATION_COMPLETED_COUNT = "[unit=count,metric=operation.completedCount]"; + public static final String METRIC_MEMORY_USED_HEAP = "[unit=bytes,metric=memory.usedHeap]"; + public static final String METRIC_MEMORY_MAX_HEAP = "[unit=bytes,metric=memory.maxHeap]"; + public static final String METRIC_OS_PROCESS_CPU_LOAD = "[metric=os.processCpuLoad]"; + public static final String METRIC_RUNTIME_TOTAL_MEMORY = "[metric=runtime.totalMemory]"; + + private final File directory; + private final Set availableMetrics = new HashSet<>(); + private long startMs = Long.MAX_VALUE; private long endMs = Long.MIN_VALUE; - private Set availableMetrics = new HashSet<>(); + + private final SortedMap metricsIndices = new TreeMap<>(); public InstanceDiagnostics(File directory) { this.directory = directory; @@ -55,7 +51,7 @@ public File getDirectory() { public InstanceDiagnostics analyze() { try { - diagnosticsFiles = diagnosticsFiles(); + List diagnosticsFiles = diagnosticsFiles(); for (DiagnosticsFile diagnosticsFile : diagnosticsFiles) { analyze(diagnosticsFile); } @@ -67,7 +63,6 @@ public InstanceDiagnostics analyze() { private void analyze(DiagnosticsFile file) throws IOException { FileReader fr = new FileReader(file.file); - int depth = 0; int offset = 0; int startOffset = 0; @@ -79,7 +74,6 @@ private void analyze(DiagnosticsFile file) throws IOException { if (read == -1) { break; } - for (int k = 0; k < read; k++) { char c = buffer[k]; sb.append(c); @@ -96,7 +90,6 @@ private void analyze(DiagnosticsFile file) throws IOException { sb.setLength(0); } } - offset++; } } @@ -105,88 +98,64 @@ private void analyze(DiagnosticsFile file) throws IOException { private void analyze(StringBuilder sb, DiagnosticsFile file, int offset, int startOffset) { int spaces = 0; long timestamp = 0; - for (int k = 0; k < sb.length(); k++) { + int k; + for (k = 0; k < sb.length(); k++) { char c = sb.charAt(k); if (c == ' ') { spaces++; } else if (spaces == 2) { timestamp = timestamp * 10 + Character.getNumericValue(c); + } else if (spaces == 3) { + break; } } - int type; - // very inefficient. - if (sb.indexOf("Metric[") != -1) { - type = TYPE_METRIC; - } else if (sb.indexOf("BuildInfo[") != -1) { - type = TYPE_BUILD_INFO; - } else if (sb.indexOf("SystemProperties[") != -1) { - type = TYPE_SYSTEM_PROPERTIES; - } else if (sb.indexOf("ConfigProperties[") != -1) { - type = TYPE_CONFIG_PROPERTIES; - } else if (sb.indexOf("SlowOperations[") != -1) { - type = TYPE_SLOW_OPERATIONS; - } else if (sb.indexOf("Invocations[") != -1) { - type = TYPE_INVOCATIONS; - } else if (sb.indexOf("InvocationProfiler[") != -1) { - type = TYPE_INVOCATION_PROFILER; - } else if (sb.indexOf("OperationsProfiler[") != -1) { - type = TYPE_OPERATION_PROFILER; - } else if (sb.indexOf("ConnectionRemoved[") != -1) { - type = TYPE_CONNECTION; - } else if (sb.indexOf("OperationThreadSamples[") != -1) { - type = TYPE_OPERATION_THREAD_SAMPLES; - } else if (sb.indexOf("HazelcastInstance[") != -1) { - type = TYPE_HAZELCAST_INSTANCE; - } else if (sb.indexOf("MemberRemoved[") != -1) { - type = TYPE_MEMBER; - } else if (sb.indexOf("MemberAdded[") != -1) { - type = TYPE_MEMBER; - } else if (sb.indexOf("ClusterVersionChanged[") != -1) { - type = TYPE_CLUSTER_VERSION_CHANGE; - } else if (sb.indexOf("Lifecycle[") != -1) { - type = TYPE_LIFECYCLE; - } else if (sb.indexOf("ConnectionAdded[") != -1) { - type = TYPE_CONNECTION; - } else if (sb.indexOf("WAN[") != -1) { - type = TYPE_WAN; - } else if (sb.indexOf("OperationHeartbeat[") != -1) { - type = TYPE_HEARTBEAT; - } else if (sb.indexOf("MemberHeartbeats[") != -1) { - type = TYPE_HEARTBEAT; + int closeType = sb.indexOf("["); + DiagnosticType type; + if (closeType == -1) { + type = DiagnosticType.TYPE_UNKNOWN; } else { + type = DiagnosticType.from(sb.substring(k, closeType)); + } + + if (type == DiagnosticType.TYPE_UNKNOWN) { System.out.println("------------------------------------"); - System.out.println(sb.toString()); + System.out.println(sb); System.out.println("------------------------------------"); - type = TYPE_UNKNOWN; } - if (timestamp > file.endMs) file.endMs = timestamp; - if (timestamp > endMs) endMs = timestamp; - if (timestamp < file.startMs) file.startMs = timestamp; - if (timestamp < startMs) startMs = timestamp; + if (timestamp > file.endMs) { + file.endMs = timestamp; + } + if (timestamp > endMs) { + endMs = timestamp; + } + if (timestamp < file.startMs) { + file.startMs = timestamp; + } + if (timestamp < startMs) { + startMs = timestamp; + } - DiagnosticsIndexEntry fragment = new DiagnosticsIndexEntry(); - fragment.offset = startOffset; - fragment.length = (offset - startOffset) + 1; + DiagnosticsIndexEntry fragment = new DiagnosticsIndexEntry(file, startOffset, (offset - startOffset) + 1); - if (type == TYPE_METRIC) { + DiagnosticKey diagnosticKey; + if (DiagnosticType.TYPE_METRIC.equals(type)) { int indexLastEquals = sb.lastIndexOf("="); int indexFirstSquareBracket = sb.indexOf("["); - String key = sb.substring(indexFirstSquareBracket + 1, indexLastEquals); - - // System.out.println(key); - availableMetrics.add(key); - - DiagnosticsIndex index = file.metricsIndices.get(key); - if (index == null) { - index = new DiagnosticsIndex(file); - file.metricsIndices.put(key, index); - } - index.treeMap.put(timestamp, fragment); + String metricName = sb.substring(indexFirstSquareBracket + 1, indexLastEquals).intern(); + availableMetrics.add(metricName); + diagnosticKey = new DiagnosticKey(type, metricName); } else { - file.indices[type].treeMap.put(timestamp, fragment); + diagnosticKey = new DiagnosticKey(type); + } + + DiagnosticsIndex index = metricsIndices.get(timestamp); + if (index == null) { + index = new DiagnosticsIndex(); + metricsIndices.put(timestamp, index); } + index.add(diagnosticKey, fragment); } private List diagnosticsFiles() { @@ -208,7 +177,7 @@ public long endMs() { return endMs; } - public Iterator> between(int type, long startMs, long endMs) { + public Iterator> between(DiagnosticType type, long startMs, long endMs) { return new IteratorImpl(type, startMs, endMs); } @@ -220,49 +189,73 @@ public String fixMetricName(String metricName) { if (availableMetrics.contains(metricName)) { return metricName; } - - if (metricName.equals("[metric=os.processCpuLoad]")) { - return "os.processCpuLoad"; - } - - if(metricName.equals("[metric=runtime.usedMemory]")){ - return "runtime.usedMemory"; - } - - if(metricName.equals("[unit=count,metric=operation.completedCount]")){ - return "operation.completedCount"; + switch (metricName) { + case METRIC_OS_PROCESS_CPU_LOAD: + return "os.processCpuLoad"; + case METRIC_RUNTIME_USED_MEMORY: + return "runtime.usedMemory"; + case METRIC_OPERATION_COMPLETED_COUNT: + return "operation.completedCount"; + case METRIC_OPERATION_INVOCATIONS_PENDING: + return "operation.invocations.pending"; + case METRIC_OPERATION_QUEUE_SIZE: + return "operation.queueSize"; + case METRIC_OPERATION_INVOCATIONS_LAST_CALL_ID: + return "operation.invocations.lastCallId"; } + return metricName; + } - if(metricName.equals("[unit=count,metric=operation.invocations.pending]")){ - return "operation.invocations.pending"; + public enum DiagnosticType { + TYPE_UNKNOWN("!!Unknown!!"), + TYPE_METRIC("Metric"), + TYPE_BUILD_INFO("BuildInfo"), + TYPE_SYSTEM_PROPERTIES("SystemProperties"), + TYPE_CONFIG_PROPERTIES("ConfigProperties"), + TYPE_SLOW_OPERATIONS("SlowOperations"), + TYPE_INVOCATIONS("Invocations"), + TYPE_INVOCATION_PROFILER("InvocationProfiler"), + TYPE_OPERATION_PROFILER("OperationsProfiler"), + TYPE_OPERATION_THREAD_SAMPLES("OperationThreadSamples"), + TYPE_CONNECTION("ConnectionAdded", "ConnectionRemoved"), + TYPE_HAZELCAST_INSTANCE("HazelcastInstance"), + TYPE_MEMBER("MemberAdded", "MemberRemoved"), + TYPE_CLUSTER_VERSION_CHANGE("ClusterVersionChanged"), + TYPE_LIFECYCLE("Lifecycle"), + TYPE_WAN("WAN"), + TYPE_HEARTBEAT("OperationHeartbeat"); + + private final String[] logPrefixes; + + private static final Map byPrefix = new HashMap<>(); + + DiagnosticType(String... logPrefixes) { + this.logPrefixes = logPrefixes; } - if(metricName.equals("[unit=count,metric=operation.queueSize]")){ - return "operation.queueSize"; + static { + for (DiagnosticType value : DiagnosticType.values()) { + for (String logPrefix : value.logPrefixes) { + if (byPrefix.put(logPrefix, value) != null) { + throw new IllegalArgumentException("Duplicate logPrefix! " + logPrefix); + } + } + } } - if(metricName.equals("[unit=count,metric=operation.invocations.lastCallId]")){ - return "operation.invocations.lastCallId"; + public static DiagnosticType from(String prefix) { + return byPrefix.getOrDefault(prefix, TYPE_UNKNOWN); } - - return metricName; } - - private class LongMetricsIterator implements Iterator> { - private final String name; - private final long startMs; - private final long endMs; - private Map.Entry entry; - private Iterator> iterator; - private Iterator diagnosticsFileIterator = diagnosticsFiles.iterator(); - private DiagnosticsFile diagnosticsFile; - - public LongMetricsIterator(String name, long startMs, long endMs) { - this.name = name; - this.startMs = startMs; - this.endMs = endMs; + private final Iterator> iterator; + private final DiagnosticKey diagnosticKey; + private Map.Entry entry; + + public LongMetricsIterator(String metricName, long startMs, long endMs) { + this.diagnosticKey = new DiagnosticKey(DiagnosticType.TYPE_METRIC, metricName); + iterator = metricsIndices.subMap(startMs, endMs).entrySet().iterator(); } @Override @@ -270,63 +263,49 @@ public boolean hasNext() { if (entry != null) { return true; } - for (; ; ) { - if (iterator != null && iterator.hasNext()) { - Map.Entry e = iterator.next(); - DiagnosticsIndexEntry indexEntry = e.getValue(); - String s = diagnosticsFile.load(indexEntry.offset, indexEntry.length); - int indexOfLastEquals = s.lastIndexOf('='); - String value = s.substring(indexOfLastEquals + 1).replace("]", ""); - int indexDot = value.indexOf('.'); - Number n; - if(indexDot == -1){ - n = Long.parseLong(value); - }else{ - n = Double.parseDouble(value); + if (iterator.hasNext()) { + Map.Entry e = iterator.next(); + DiagnosticsIndexEntry indexEntry = e.getValue().metricsMap.get(diagnosticKey); + if (indexEntry != null) { + entry = e; + return true; } - entry = new AbstractMap.SimpleEntry<>(e.getKey(), n); - return true; - } - - if (!diagnosticsFileIterator.hasNext()) { + } else { return false; } - - diagnosticsFile = diagnosticsFileIterator.next(); - DiagnosticsIndex diagnosticsIndex = diagnosticsFile.metricsIndices.get(name); - if (diagnosticsIndex == null) { - continue; - } - iterator = diagnosticsIndex.treeMap.subMap(startMs, true, endMs, true).entrySet().iterator(); } } @Override public Map.Entry next() { - if (hasNext()) { - Map.Entry tmp = entry; - entry = null; - return tmp; + Map.Entry next = entry; + DiagnosticsIndex index = next.getValue(); + DiagnosticsIndexEntry indexEntry = index.metricsMap.get(diagnosticKey); + + String s = indexEntry.file.load(indexEntry.offset, indexEntry.length); + int indexOfLastEquals = s.lastIndexOf('='); + String value = s.substring(indexOfLastEquals + 1).replace("]", ""); + int indexDot = value.indexOf('.'); + Number n; + if (indexDot == -1) { + n = Long.parseLong(value); + } else { + n = Double.parseDouble(value); } - return null; + entry = null; + return new AbstractMap.SimpleEntry<>(next.getKey(), n); } } - private class IteratorImpl implements Iterator> { - private final int type; - private final long startMs; - private final long endMs; - private Map.Entry entry; - private Iterator> iterator; - private Iterator diagnosticsFileIterator = diagnosticsFiles.iterator(); - private DiagnosticsFile diagnosticsFile; - - public IteratorImpl(int type, long startMs, long endMs) { - this.type = type; - this.startMs = startMs; - this.endMs = endMs; + private Map.Entry entry; + private final Iterator> iterator; + private final DiagnosticKey diagnosticKey; + + public IteratorImpl(DiagnosticType type, long startMs, long endMs) { + this.diagnosticKey = new DiagnosticKey(type); + this.iterator = metricsIndices.subMap(startMs, endMs).entrySet().iterator(); } @Override @@ -334,39 +313,31 @@ public boolean hasNext() { if (entry != null) { return true; } - for (; ; ) { - if (iterator != null && iterator.hasNext()) { - Map.Entry e = iterator.next(); - DiagnosticsIndexEntry indexEntry = e.getValue(); - String value = diagnosticsFile.load(indexEntry.offset, indexEntry.length); - entry = new AbstractMap.SimpleEntry<>(e.getKey(), value); - return true; - } - - if (!diagnosticsFileIterator.hasNext()) { + if (iterator.hasNext()) { + Map.Entry e = iterator.next(); + DiagnosticsIndexEntry indexEntry = e.getValue().metricsMap.get(diagnosticKey); + if (indexEntry != null) { + entry = e; + return true; + } + } else { return false; } - - diagnosticsFile = diagnosticsFileIterator.next(); - iterator = diagnosticsFile.indices[type].treeMap.subMap(startMs, true, endMs, true).entrySet().iterator(); } } @Override public Map.Entry next() { - if (hasNext()) { - Map.Entry tmp = entry; - entry = null; - return tmp; - } - return null; + DiagnosticsIndexEntry indexEntry = entry.getValue().metricsMap.get(diagnosticKey); + String value = indexEntry.file.load(indexEntry.offset, indexEntry.length); + Long key = entry.getKey(); + entry = null; + return new AbstractMap.SimpleEntry<>(key, value); } } private static class DiagnosticsFile { - private final DiagnosticsIndex[] indices = new DiagnosticsIndex[TYPES]; - private final Map metricsIndices = new HashMap<>(); private final File file; private final RandomAccessFile randomAccessFile; private long startMs = Long.MIN_VALUE; @@ -374,9 +345,6 @@ private static class DiagnosticsFile { public DiagnosticsFile(File file) { this.file = file; - for (int k = 0; k < indices.length; k++) { - indices[k] = new DiagnosticsIndex(this); - } try { randomAccessFile = new RandomAccessFile(file, "r"); } catch (FileNotFoundException e) { @@ -398,25 +366,64 @@ public String load(int offset, int length) { } } + private static class DiagnosticKey { + private final DiagnosticType type; + private final String name; + + private DiagnosticKey(DiagnosticType type, String name) { + this.type = type; + this.name = name; + } + + private DiagnosticKey(DiagnosticType type) { + this(type, null); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DiagnosticKey that = (DiagnosticKey) o; + return type == that.type && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(type, name); + } + + @Override + public String toString() { + return "DiagnosticKey{" + "type=" + type + ", name='" + name + '\'' + '}'; + } + } + private static class DiagnosticsIndex { - private final DiagnosticsFile diagnosticsFile; - private final TreeMap treeMap = new TreeMap<>(); + private final Map metricsMap = new HashMap<>(); - public DiagnosticsIndex(DiagnosticsFile diagnosticsFile) { - this.diagnosticsFile = diagnosticsFile; + public void add(DiagnosticKey key, DiagnosticsIndexEntry indexEntry) { + metricsMap.put(key, indexEntry); } } private static class DiagnosticsIndexEntry { - private int offset; - private int length; + private final DiagnosticsFile file; + private final int offset; + private final int length; + + private DiagnosticsIndexEntry(DiagnosticsFile file, int offset, int length) { + this.file = file; + this.offset = offset; + this.length = length; + } @Override public String toString() { - return "DiagnosticsIndexEntry{" + - "offset=" + offset + - ", length=" + length + - '}'; + return "DiagnosticsIndexEntry{" + "file=" + file.file + ", offset=" + offset + ", length=" + length + '}'; } } -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/InstancesPane.java b/src/main/java/com/hazelcast/diagnostics/InstancesPane.java index d5f1349..26c290f 100644 --- a/src/main/java/com/hazelcast/diagnostics/InstancesPane.java +++ b/src/main/java/com/hazelcast/diagnostics/InstancesPane.java @@ -1,10 +1,20 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.AbstractListModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.filechooser.FileFilter; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Point; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -34,11 +44,11 @@ public InstancesPane(MainWindow window) { JPanel panel = new JPanel(new BorderLayout(), true); - JPanel buttonsPanel = new JPanel(); + JPanel buttonsPanel = new JPanel(new BorderLayout()); buttonsPanel.add(createAddInstanceButton(buttonsPanel, listModel), BorderLayout.WEST); buttonsPanel.add(createClearInstancesButton(listModel), BorderLayout.EAST); - panel.add(buttonsPanel, BorderLayout.NORTH); + panel.add(buttonsPanel, BorderLayout.NORTH); panel.add(list, BorderLayout.CENTER); this.component = panel; @@ -198,4 +208,4 @@ public void valueChanged(ListSelectionEvent e) { } } } -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/InvocationProfilerPane.java b/src/main/java/com/hazelcast/diagnostics/InvocationProfilerPane.java index 95aa7c8..9d8108d 100644 --- a/src/main/java/com/hazelcast/diagnostics/InvocationProfilerPane.java +++ b/src/main/java/com/hazelcast/diagnostics/InvocationProfilerPane.java @@ -9,8 +9,8 @@ import org.jfree.chart.renderer.AbstractRenderer; import org.jfree.data.xy.DefaultXYDataset; -import javax.swing.*; -import java.awt.*; +import javax.swing.JComponent; +import java.awt.BasicStroke; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; @@ -43,6 +43,7 @@ public InvocationProfilerPane() { true, false); pane = new ChartPanel(latencyChart); + XYPlot plot = latencyChart.getXYPlot(); ValueAxis xAxis = plot.getDomainAxis(); xAxis.setRange(0, 8); @@ -69,7 +70,7 @@ public JComponent getComponent() { public void update() { for (InstanceDiagnostics profile : instanceDiagnosticsColl) { Iterator> iter = profile - .between(InstanceDiagnostics.TYPE_INVOCATION_PROFILER, startMs, endMs); + .between(InstanceDiagnostics.DiagnosticType.TYPE_INVOCATION_PROFILER, startMs, endMs); if (!iter.hasNext()) { continue; } diff --git a/src/main/java/com/hazelcast/diagnostics/InvocationsPlane.java b/src/main/java/com/hazelcast/diagnostics/InvocationsPlane.java index f7ae5d1..1894fa1 100644 --- a/src/main/java/com/hazelcast/diagnostics/InvocationsPlane.java +++ b/src/main/java/com/hazelcast/diagnostics/InvocationsPlane.java @@ -10,7 +10,8 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Iterator; @@ -19,8 +20,6 @@ public class InvocationsPlane { private final JPanel component; - private final JFreeChart chart; - private final ChartPanel chartPanel; private final TimeSeriesCollection collection; private Collection diagnosticsList; private long startMs = Long.MIN_VALUE; @@ -28,16 +27,10 @@ public class InvocationsPlane { public InvocationsPlane() { collection = new TimeSeriesCollection(); - chart = ChartFactory.createTimeSeriesChart( - "Invocation Throughput", - "Time", - "Throughput", - collection, - true, - true, - false); - this.chartPanel = new ChartPanel(chart); - XYPlot plot = (XYPlot)chartPanel.getChart().getPlot(); + JFreeChart chart = ChartFactory.createTimeSeriesChart("Invocation Throughput", "Time", "Throughput", collection, true, + true, false); + ChartPanel chartPanel = new ChartPanel(chart); + XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis)plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); this.component = chartPanel; @@ -59,7 +52,8 @@ public void update() { } for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.metricsBetween("[unit=count,metric=operation.invocations.lastCallId]", startMs, endMs); + Iterator> iterator = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_OPERATION_INVOCATIONS_LAST_CALL_ID, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -91,4 +85,4 @@ public void update() { public JComponent getComponent() { return component; } -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/LatencyDistributionPane.java b/src/main/java/com/hazelcast/diagnostics/LatencyDistributionPane.java index bce55ab..8777447 100644 --- a/src/main/java/com/hazelcast/diagnostics/LatencyDistributionPane.java +++ b/src/main/java/com/hazelcast/diagnostics/LatencyDistributionPane.java @@ -6,8 +6,11 @@ import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; -import javax.swing.*; -import java.awt.*; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; @@ -27,21 +30,20 @@ public class LatencyDistributionPane { private static final String INVOCATION_PROFILE_MARKER = "InvocationProfiler["; private final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - private final ChartPanel chart; private final JPanel component; - private final DefaultComboBoxModel comboBoxModel; private long startMs = Long.MIN_VALUE; private long endMs = Long.MAX_VALUE; private Collection instanceDiagnosticsColl = new ArrayList<>(); - private JComboBox comboBox; - private Map>> distributionMap = new HashMap<>(); + private final DefaultComboBoxModel comboBoxModel; + private final JComboBox comboBox; + private final Map>> distributionMap = new HashMap<>(); + private final InstanceDiagnostics.DiagnosticType type; private String active; - private int type; - public LatencyDistributionPane(int type) { + public LatencyDistributionPane(InstanceDiagnostics.DiagnosticType type) { this.type = type; comboBoxModel = new DefaultComboBoxModel<>(); - comboBox = new JComboBox(comboBoxModel); + comboBox = new JComboBox<>(comboBoxModel); comboBox.addActionListener(e -> { active = (String) comboBox.getSelectedItem(); render(); @@ -55,7 +57,7 @@ public LatencyDistributionPane(int type) { dataset, PlotOrientation.VERTICAL, true, true, false); - chart = new ChartPanel(barChart); + ChartPanel chart = new ChartPanel(barChart); panel.add(comboBox, BorderLayout.NORTH); panel.add(chart, BorderLayout.CENTER); component = panel; @@ -138,7 +140,6 @@ private Map> calc(String startProfileStr, String end Map> endLatencies = extractOperationToLatencyProfile(parseProfile(endProfileStr)); subtractStartFromEnd(startLatencies, endLatencies); - Map> result = new HashMap<>(); for (Entry> endLatency : endLatencies.entrySet()) { @@ -164,16 +165,8 @@ private Map> calc(String startProfileStr, String end long delta = endValue - startValue; SortedMap exist = result.computeIfAbsent(operation, k -> new TreeMap<>()); - Long finalValue = exist.get(key); - if (finalValue == null) { - exist.put(key, delta); - } else { - exist.put(key, finalValue + delta); - } + exist.merge(key, delta, Long::sum); } - -// double[][] percentilePlot = transposeToPercentilePlot(endProfile); -// dataset.addSeries(operation, percentilePlot); } return result; diff --git a/src/main/java/com/hazelcast/diagnostics/Main.java b/src/main/java/com/hazelcast/diagnostics/Main.java index 4f71f25..74a31ec 100644 --- a/src/main/java/com/hazelcast/diagnostics/Main.java +++ b/src/main/java/com/hazelcast/diagnostics/Main.java @@ -1,8 +1,9 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.FontUIResource; -import java.awt.*; +import java.awt.Font; import java.util.Enumeration; public class Main { @@ -22,8 +23,7 @@ private static void enableAntiAliasing() { public static void incFontSize(float multiplier) { UIDefaults defaults = UIManager.getDefaults(); - int i = 0; - for (Enumeration e = defaults.keys(); e.hasMoreElements(); i++) { + for (Enumeration e = defaults.keys(); e.hasMoreElements(); ) { Object key = e.nextElement(); Object value = defaults.get(key); if (value instanceof Font) { diff --git a/src/main/java/com/hazelcast/diagnostics/MainWindow.java b/src/main/java/com/hazelcast/diagnostics/MainWindow.java index df51bac..e49ee18 100644 --- a/src/main/java/com/hazelcast/diagnostics/MainWindow.java +++ b/src/main/java/com/hazelcast/diagnostics/MainWindow.java @@ -1,7 +1,16 @@ package com.hazelcast.diagnostics; -import javax.swing.*; -import java.awt.*; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.WindowConstants; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; import java.io.File; import java.util.Collection; import java.util.HashMap; @@ -9,30 +18,30 @@ public class MainWindow { - private JFrame window; - private Map machines = new HashMap<>(); - - private DashboardPane dashboardPane = new DashboardPane(); - private SystemPropertiesPane systemPropertiesPane = new SystemPropertiesPane(); - private BuildInfoPane buildInfoPane = new BuildInfoPane(); - private InstancesPane machinesPane; - private InvocationProfilerPane invocationProfilerPane = new InvocationProfilerPane(); - private LatencyDistributionPane invocationLatencyDistributionPane = new LatencyDistributionPane(InstanceDiagnostics.TYPE_INVOCATION_PROFILER); - private LatencyDistributionPane operationLatencyDistributionPane = new LatencyDistributionPane(InstanceDiagnostics.TYPE_OPERATION_PROFILER); - private MemoryPane memoryPane = new MemoryPane(); - private CpuUtilizationPane cpuUtilizationPane = new CpuUtilizationPane(); - private MetricsPane metricsPane = new MetricsPane(); - private TimeSelectorPane timeSelectorPane = new TimeSelectorPane(); - private InvocationsPlane invocationsPlane = new InvocationsPlane(); - private OperationsPlane operationsPlane = new OperationsPlane(); - private PendingPane invocationsPendingPane = new PendingPane("[unit=count,metric=operation.invocations.pending]", "Invocations Pending"); - private PendingPane operationsPendingPane = new PendingPane("[unit=count,metric=operation.queueSize]", "Operations Pending"); - private StatusBar statusBar = new StatusBar(); - private SlowOperationsPane slowOperationsPane = new SlowOperationsPane(); - private ConnectionPane connectionPane = new ConnectionPane(); - private MemberPane memberPane = new MemberPane(); - private WANPane wanPane = new WANPane(); - private HeartbeatPane heartbeatPane = new HeartbeatPane(); + private final JFrame window; + private final Map machines = new HashMap<>(); + + private final DashboardPane dashboardPane = new DashboardPane(); + private final SystemPropertiesPane systemPropertiesPane = new SystemPropertiesPane(); + private final BuildInfoPane buildInfoPane = new BuildInfoPane(); + private final InvocationProfilerPane invocationProfilerPane = new InvocationProfilerPane(); + private final LatencyDistributionPane invocationLatencyDistributionPane = new LatencyDistributionPane( + InstanceDiagnostics.DiagnosticType.TYPE_INVOCATION_PROFILER); + private final LatencyDistributionPane operationLatencyDistributionPane = new LatencyDistributionPane( + InstanceDiagnostics.DiagnosticType.TYPE_OPERATION_PROFILER); + private final MemoryPane memoryPane = new MemoryPane(); + private final CpuUtilizationPane cpuUtilizationPane = new CpuUtilizationPane(); + private final MetricsPane metricsPane = new MetricsPane(); + private final TimeSelectorPane timeSelectorPane = new TimeSelectorPane(); + private final InvocationsPlane invocationsPlane = new InvocationsPlane(); + private final OperationsPlane operationsPlane = new OperationsPlane(); + private final PendingPane invocationsPendingPane = new PendingPane(InstanceDiagnostics.METRIC_OPERATION_INVOCATIONS_PENDING, "Invocations Pending"); + private final PendingPane operationsPendingPane = new PendingPane(InstanceDiagnostics.METRIC_OPERATION_QUEUE_SIZE, "Operations Pending"); + private final SlowOperationsPane slowOperationsPane = new SlowOperationsPane(); + private final ConnectionPane connectionPane = new ConnectionPane(); + private final MemberPane memberPane = new MemberPane(); + private final WANPane wanPane = new WANPane(); + private final HeartbeatPane heartbeatPane = new HeartbeatPane(); public JFrame getJFrame() { return window; @@ -120,7 +129,7 @@ public MainWindow() { window.setLocationRelativeTo(null); window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - machinesPane = new InstancesPane(this); + InstancesPane machinesPane = new InstancesPane(this); machinesPane.addDirectories(new File("data/member"), new File("data/litemember")); buildMenu(window); @@ -192,6 +201,7 @@ public MainWindow() { JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.add(splitPane, BorderLayout.CENTER); + StatusBar statusBar = new StatusBar(); mainPanel.add(statusBar.getComponent(), BorderLayout.SOUTH); window.setContentPane(mainPanel); @@ -229,11 +239,12 @@ private static void buildMenu(JFrame window) { menuBar.add(fileMenu); window.setJMenuBar(menuBar); -// JMenuItem menuItem = new JMenuItem("Load"); -// fileMenu.add(menuItem); - JMenuItem exitItem = new JMenuItem("Exit"); exitItem.addActionListener(e -> System.exit(0)); fileMenu.add(exitItem); + + JMenuItem gcItem = new JMenuItem("GC"); + gcItem.addActionListener(e -> System.gc()); + fileMenu.add(gcItem); } } diff --git a/src/main/java/com/hazelcast/diagnostics/MemberPane.java b/src/main/java/com/hazelcast/diagnostics/MemberPane.java index b64bd0c..0bec3f0 100644 --- a/src/main/java/com/hazelcast/diagnostics/MemberPane.java +++ b/src/main/java/com/hazelcast/diagnostics/MemberPane.java @@ -1,6 +1,8 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -8,6 +10,8 @@ import java.util.Map; import java.util.TreeMap; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_MEMBER; + public class MemberPane { private final JComponent component; @@ -37,9 +41,9 @@ public void update() { return; } - TreeMap> treeMap = new TreeMap(); + TreeMap> treeMap = new TreeMap<>(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.between(InstanceDiagnostics.TYPE_MEMBER, startMs, endMs); + Iterator> iterator = diagnostics.between(TYPE_MEMBER, startMs, endMs); if (!iterator.hasNext()) { continue; diff --git a/src/main/java/com/hazelcast/diagnostics/MemoryPane.java b/src/main/java/com/hazelcast/diagnostics/MemoryPane.java index 1149580..0c1f1d4 100644 --- a/src/main/java/com/hazelcast/diagnostics/MemoryPane.java +++ b/src/main/java/com/hazelcast/diagnostics/MemoryPane.java @@ -10,7 +10,8 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; @@ -20,8 +21,6 @@ public class MemoryPane { private final JPanel component; - private final JFreeChart chart; - private final ChartPanel chartPanel; private final TimeSeriesCollection collection; private Collection diagnosticsList = new ArrayList<>(); private long startMs = Long.MIN_VALUE; @@ -29,16 +28,10 @@ public class MemoryPane { public MemoryPane() { collection = new TimeSeriesCollection(); - chart = ChartFactory.createTimeSeriesChart( - "Memory Usage", - "Time", - "Memory Usage", - collection, - true, - true, + JFreeChart chart = ChartFactory.createTimeSeriesChart("Memory Usage", "Time", "Memory Usage", collection, true, true, false); - this.chartPanel = new ChartPanel(chart); - XYPlot plot = (XYPlot)chartPanel.getChart().getPlot(); + ChartPanel chartPanel = new ChartPanel(chart); + XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis)plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); this.component = chartPanel; @@ -57,7 +50,8 @@ public void update() { collection.removeAllSeries(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.metricsBetween("[metric=runtime.usedMemory]", startMs, endMs); + Iterator> iterator = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_RUNTIME_USED_MEMORY, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -81,4 +75,4 @@ public void update() { public JComponent getComponent() { return component; } -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/MetricsPane.java b/src/main/java/com/hazelcast/diagnostics/MetricsPane.java index bcb476d..71c89e9 100644 --- a/src/main/java/com/hazelcast/diagnostics/MetricsPane.java +++ b/src/main/java/com/hazelcast/diagnostics/MetricsPane.java @@ -10,10 +10,16 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import java.awt.BorderLayout; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; @@ -21,45 +27,41 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; public class MetricsPane { - private final JComboBox comboBox; - private final DefaultComboBoxModel comboBoxModel; - private LinkedHashSet metricsNames = new LinkedHashSet<>(); - - private JPanel component; - private JTextField filterTextField; - private final JFreeChart chart; - private final ChartPanel chartPanel; + + private final JList metricsList; + private final DefaultListModel metricsListModel; + private final LinkedHashSet metricsNames = new LinkedHashSet<>(); + private final JPanel component; + private final JTextField filterTextField; + private final Set activeMetrics = new LinkedHashSet<>(); private final TimeSeriesCollection collection; private Collection diagnosticsList; private long startMs = Long.MIN_VALUE; private long endMs = Long.MAX_VALUE; - private String activeMetric; public MetricsPane() { - this.comboBox = new JComboBox<>(); - this.comboBox.grabFocus(); - this.comboBox.addActionListener(e -> { - activeMetric = (String) comboBox.getSelectedItem(); + this.metricsList = new JList<>(); + JScrollPane metricsScrollPane = new JScrollPane(metricsList); + this.metricsList.grabFocus(); + this.metricsListModel = new DefaultListModel<>(); + this.metricsList.addListSelectionListener(e -> { + activeMetrics.clear(); + for (int selectedIndex : metricsList.getSelectedIndices()) { + activeMetrics.add(metricsListModel.elementAt(selectedIndex)); + } update(); }); - this.comboBoxModel = new DefaultComboBoxModel(); - comboBox.setModel(comboBoxModel); + metricsList.setModel(metricsListModel); this.collection = new TimeSeriesCollection(); - this.chart = ChartFactory.createTimeSeriesChart( - "Metrics", - "Time", - "Whatever", - collection, - true, - true, - false); - this.chartPanel = new ChartPanel(chart); + JFreeChart chart = ChartFactory.createTimeSeriesChart("Metrics", "Time", "Whatever", collection, true, true, false); + ChartPanel chartPanel = new ChartPanel(chart); XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis) plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); @@ -69,10 +71,23 @@ public MetricsPane() { filterTextField.setToolTipText("A regex based filter over the metrics."); filterTextField.addActionListener(e -> updateCombobox()); + JButton clearButton = new JButton("Clear"); + clearButton.addActionListener(e -> { + filterTextField.setText(".*"); + activeMetrics.clear(); + metricsList.setSelectedIndices(new int[] {}); + updateCombobox(); + }); + + JPanel filterPanel = new JPanel(); + filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.X_AXIS)); + filterPanel.add(filterTextField); + filterPanel.add(clearButton); + JPanel selectionPanel = new JPanel(); selectionPanel.setLayout(new BoxLayout(selectionPanel, BoxLayout.Y_AXIS)); - selectionPanel.add(filterTextField); - selectionPanel.add(comboBox); + selectionPanel.add(filterPanel); + selectionPanel.add(metricsScrollPane); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); @@ -98,7 +113,7 @@ public void setInstanceDiagnostics(Collection diagnosticsLi metricsNames.addAll(diagnostics.getAvailableMetrics()); } if (diagnosticsList.isEmpty()) { - activeMetric = null; + activeMetrics.clear(); } updateCombobox(); @@ -124,37 +139,37 @@ private void updateCombobox() { Collections.sort(filteredMetrics); - comboBoxModel.removeAllElements(); + metricsListModel.removeAllElements(); for (String metricName : filteredMetrics) { - comboBoxModel.addElement(metricName); + metricsListModel.addElement(metricName); } } public void update() { collection.removeAllSeries(); - if (activeMetric == null) { + if (activeMetrics.isEmpty()) { return; } for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.metricsBetween(activeMetric, startMs, endMs); - - if (!iterator.hasNext()) { - continue; - } + for (String activeMetric : activeMetrics) { + Iterator> iterator = diagnostics.metricsBetween(activeMetric, startMs, endMs); + if (!iterator.hasNext()) { + continue; + } - TimeSeries series = new TimeSeries(diagnostics.getDirectory().getName()); + TimeSeries series = new TimeSeries(diagnostics.getDirectory().getName() + ":" + activeMetric); - while (iterator.hasNext()) { - try { - Map.Entry entry = iterator.next(); - series.add(new FixedMillisecond(entry.getKey()), entry.getValue()); - } catch (SeriesException e) { - System.err.println("Error adding to series"); + while (iterator.hasNext()) { + try { + Map.Entry entry = iterator.next(); + series.add(new FixedMillisecond(entry.getKey()), entry.getValue()); + } catch (SeriesException e) { + System.err.println("Error adding to series"); + } } + collection.addSeries(series); } - collection.addSeries(series); } } - -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/OperationsPlane.java b/src/main/java/com/hazelcast/diagnostics/OperationsPlane.java index 72b8880..f937509 100644 --- a/src/main/java/com/hazelcast/diagnostics/OperationsPlane.java +++ b/src/main/java/com/hazelcast/diagnostics/OperationsPlane.java @@ -10,7 +10,8 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Iterator; @@ -19,8 +20,6 @@ public class OperationsPlane { private final JPanel component; - private final JFreeChart chart; - private final ChartPanel chartPanel; private final TimeSeriesCollection collection; private Collection diagnosticsList; private long startMs = Long.MIN_VALUE; @@ -28,16 +27,10 @@ public class OperationsPlane { public OperationsPlane() { collection = new TimeSeriesCollection(); - chart = ChartFactory.createTimeSeriesChart( - "Operation Throughput", - "Time", - "Throughput", - collection, - true, - true, - false); - this.chartPanel = new ChartPanel(chart); - XYPlot plot = (XYPlot)chartPanel.getChart().getPlot(); + JFreeChart chart = ChartFactory.createTimeSeriesChart("Operation Throughput", "Time", "Throughput", collection, true, + true, false); + ChartPanel chartPanel = new ChartPanel(chart); + XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis)plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); this.component = chartPanel; @@ -59,7 +52,8 @@ public void update() { } for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.metricsBetween("[unit=count,metric=operation.completedCount]", startMs, endMs); + Iterator> iterator = diagnostics.metricsBetween( + InstanceDiagnostics.METRIC_OPERATION_COMPLETED_COUNT, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -91,4 +85,4 @@ public void update() { public JComponent getComponent() { return component; } -} +} \ No newline at end of file diff --git a/src/main/java/com/hazelcast/diagnostics/PendingPane.java b/src/main/java/com/hazelcast/diagnostics/PendingPane.java index 7f07a6e..9117e3a 100644 --- a/src/main/java/com/hazelcast/diagnostics/PendingPane.java +++ b/src/main/java/com/hazelcast/diagnostics/PendingPane.java @@ -10,7 +10,8 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JPanel; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Iterator; @@ -19,8 +20,6 @@ public class PendingPane { private final JPanel component; - private final JFreeChart chart; - private final ChartPanel chartPanel; private final TimeSeriesCollection collection; private final String metric; private Collection diagnosticsList; @@ -30,16 +29,9 @@ public class PendingPane { public PendingPane(String metric, String title) { this.collection = new TimeSeriesCollection(); this.metric = metric; - this.chart = ChartFactory.createTimeSeriesChart( - title, - "Time", - "Pending", - collection, - true, - true, - false); - this.chartPanel = new ChartPanel(chart); - XYPlot plot = (XYPlot)chartPanel.getChart().getPlot(); + JFreeChart chart = ChartFactory.createTimeSeriesChart(title, "Time", "Pending", collection, true, true, false); + ChartPanel chartPanel = new ChartPanel(chart); + XYPlot plot = (XYPlot) chartPanel.getChart().getPlot(); DateAxis axis = (DateAxis)plot.getDomainAxis(); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss")); this.component = chartPanel; diff --git a/src/main/java/com/hazelcast/diagnostics/SlowOperationsPane.java b/src/main/java/com/hazelcast/diagnostics/SlowOperationsPane.java index 8a3f683..6045a1f 100644 --- a/src/main/java/com/hazelcast/diagnostics/SlowOperationsPane.java +++ b/src/main/java/com/hazelcast/diagnostics/SlowOperationsPane.java @@ -1,6 +1,8 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -37,9 +39,9 @@ public void update() { return; } - TreeMap> treeMap = new TreeMap(); + TreeMap> treeMap = new TreeMap<>(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.between(InstanceDiagnostics.TYPE_SLOW_OPERATIONS, startMs, endMs); + Iterator> iterator = diagnostics.between(InstanceDiagnostics.DiagnosticType.TYPE_SLOW_OPERATIONS, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -48,11 +50,7 @@ public void update() { while (iterator.hasNext()) { Map.Entry entry = iterator.next(); Long key = entry.getKey(); - List list = treeMap.get(key); - if (list == null) { - list = new ArrayList<>(); - treeMap.put(key, list); - } + List list = treeMap.computeIfAbsent(key, k -> new ArrayList<>()); list.add(entry.getValue()); } } diff --git a/src/main/java/com/hazelcast/diagnostics/StatusBar.java b/src/main/java/com/hazelcast/diagnostics/StatusBar.java index f57197f..0f7dc07 100644 --- a/src/main/java/com/hazelcast/diagnostics/StatusBar.java +++ b/src/main/java/com/hazelcast/diagnostics/StatusBar.java @@ -1,15 +1,15 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.Timer; import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.BorderLayout; public class StatusBar { private final JComponent component; - private final Timer timer; public StatusBar(){ JPanel statusPanel = new JPanel(); @@ -22,15 +22,12 @@ public StatusBar(){ this.component = statusPanel; - timer = new Timer(1000, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Runtime runtime = Runtime.getRuntime(); - long totalMemory = runtime.totalMemory(); - long freeMemory = runtime.freeMemory(); - long usedMemory = totalMemory-freeMemory; - label.setText(toMegabytes(usedMemory)+" of "+toMegabytes(totalMemory)+"M"); - } + Timer timer = new Timer(1000, e -> { + Runtime runtime = Runtime.getRuntime(); + long totalMemory = runtime.totalMemory(); + long freeMemory = runtime.freeMemory(); + long usedMemory = totalMemory - freeMemory; + label.setText(toMegabytes(usedMemory) + " of " + toMegabytes(totalMemory) + "M"); }); timer.setInitialDelay(0); timer.start(); diff --git a/src/main/java/com/hazelcast/diagnostics/SystemPropertiesPane.java b/src/main/java/com/hazelcast/diagnostics/SystemPropertiesPane.java index c386f06..e83f39d 100644 --- a/src/main/java/com/hazelcast/diagnostics/SystemPropertiesPane.java +++ b/src/main/java/com/hazelcast/diagnostics/SystemPropertiesPane.java @@ -1,18 +1,21 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import java.util.Iterator; import java.util.Map; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_SYSTEM_PROPERTIES; + public class SystemPropertiesPane { - private final JTable table; private final DefaultTableModel model; private final JScrollPane panel; public SystemPropertiesPane() { - table = new JTable(); + JTable table = new JTable(); model = new DefaultTableModel(); table.setModel(model); model.addColumn("Key"); @@ -30,7 +33,7 @@ public void setInstanceDiagnostics(InstanceDiagnostics machine) { return; } - Iterator> it = machine.between(InstanceDiagnostics.TYPE_SYSTEM_PROPERTIES, 0, Long.MAX_VALUE); + Iterator> it = machine.between(TYPE_SYSTEM_PROPERTIES, 0, Long.MAX_VALUE); if(!it.hasNext()){ System.out.println("No System Properties found in directory: "+machine.getDirectory()); return; diff --git a/src/main/java/com/hazelcast/diagnostics/TimeSelectorPane.java b/src/main/java/com/hazelcast/diagnostics/TimeSelectorPane.java index b76b191..d090fdf 100644 --- a/src/main/java/com/hazelcast/diagnostics/TimeSelectorPane.java +++ b/src/main/java/com/hazelcast/diagnostics/TimeSelectorPane.java @@ -2,7 +2,8 @@ import com.jidesoft.swing.RangeSlider; -import javax.swing.*; +import javax.swing.BoundedRangeModel; +import javax.swing.JComponent; import javax.swing.event.ChangeListener; import java.util.Collection; @@ -10,8 +11,6 @@ public class TimeSelectorPane { private final JComponent component; private final RangeSlider rangeSlider; - private long durationMs; - private long endMs; private long startMs; public TimeSelectorPane() { @@ -37,24 +36,24 @@ public JComponent getComponent() { } public void setInstanceDiagnostics(Collection instanceDiagnosticsList) { + long durationMs; + long endMs; if (instanceDiagnosticsList.isEmpty()) { startMs = 0; - endMs = 0; - durationMs = 0; return; } this.startMs = Long.MAX_VALUE; - this.endMs = Long.MIN_VALUE; + endMs = Long.MIN_VALUE; for (InstanceDiagnostics instanceDiagnostics : instanceDiagnosticsList) { if (instanceDiagnostics.startMs() < startMs) { this.startMs = instanceDiagnostics.startMs(); } if (instanceDiagnostics.endMs() > endMs) { - this.endMs = instanceDiagnostics.endMs(); + endMs = instanceDiagnostics.endMs(); } } - this.durationMs = endMs - startMs; + durationMs = endMs - startMs; BoundedRangeModel model = rangeSlider.getModel(); model.setMinimum(0); diff --git a/src/main/java/com/hazelcast/diagnostics/WANPane.java b/src/main/java/com/hazelcast/diagnostics/WANPane.java index 38c01e8..11349b6 100644 --- a/src/main/java/com/hazelcast/diagnostics/WANPane.java +++ b/src/main/java/com/hazelcast/diagnostics/WANPane.java @@ -1,6 +1,8 @@ package com.hazelcast.diagnostics; -import javax.swing.*; +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -8,6 +10,8 @@ import java.util.Map; import java.util.TreeMap; +import static com.hazelcast.diagnostics.InstanceDiagnostics.DiagnosticType.TYPE_WAN; + public class WANPane { private final JComponent component; @@ -37,9 +41,9 @@ public void update() { return; } - TreeMap> treeMap = new TreeMap(); + TreeMap> treeMap = new TreeMap<>(); for (InstanceDiagnostics diagnostics : diagnosticsList) { - Iterator> iterator = diagnostics.between(InstanceDiagnostics.TYPE_WAN, startMs, endMs); + Iterator> iterator = diagnostics.between(TYPE_WAN, startMs, endMs); if (!iterator.hasNext()) { continue; @@ -48,11 +52,7 @@ public void update() { while (iterator.hasNext()) { Map.Entry entry = iterator.next(); Long key = entry.getKey(); - List list = treeMap.get(key); - if (list == null) { - list = new ArrayList<>(); - treeMap.put(key, list); - } + List list = treeMap.computeIfAbsent(key, k -> new ArrayList<>()); list.add(entry.getValue()); } }