From 6f4e0da744b5118cad2b7b6607dcd8f492cf279e Mon Sep 17 00:00:00 2001 From: teetangh Date: Mon, 11 Sep 2023 15:29:35 +0530 Subject: [PATCH 1/7] initial prototype of the dialog box --- build.gradle.kts | 5 + .../tools/dialog/MctimingsDialog.java | 260 ++++++++++++++++++ .../intellij/tree/TreeRightClickListener.java | 13 +- src/main/java/utils/ProcessUtils.java | 18 ++ src/main/java/utils/TemplateUtil.java | 7 + 5 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java diff --git a/build.gradle.kts b/build.gradle.kts index f309986b..97d91849 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,10 @@ plugins { group = "com.couchbase" version = "1.0.3" +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} sourceSets["main"].java.srcDirs("src/main/gen") @@ -19,6 +23,7 @@ dependencies { implementation("com.couchbase.client:java-client:3.4.9") implementation("org.slf4j:slf4j-simple:2.0.7") implementation("org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r") + implementation("org.jfree:jfreechart:1.5.3") testImplementation("org.mockito:mockito-core:5.2.0") testImplementation("org.mockito:mockito-inline:5.2.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1") diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java new file mode 100644 index 00000000..3308553d --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -0,0 +1,260 @@ +package com.couchbase.intellij.tools.dialog; + +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.tools.CBTools; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.Nullable; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +import utils.ProcessUtils; +import utils.TemplateUtil; + +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.util.List; +import java.util.*; + +public class MctimingsDialog extends DialogWrapper { + + private JComboBox bucketComboBox; + private JComboBox outputFormatComboBox; + private JPanel outputPanel; + private JPanel dialogPanel; + private GridBagConstraints c; + private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); + + public MctimingsDialog() { + super(true); + init(); + setTitle("Couchbase Mctimings Dialog"); + getWindow().setMinimumSize(new Dimension(800, 600)); + setResizable(true); + setOKButtonText("Display Timings"); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + dialogPanel = new JPanel(new GridBagLayout()); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.NORTH; + + // Line 1: Bucket + c.gridx = 0; + c.gridy = 0; + c.insets = JBUI.insets(5); + JPanel bucketLabel = TemplateUtil.getLabelWithHelp("Bucket:", "Select the bucket to display mctimings for"); + dialogPanel.add(bucketLabel, c); + + c.gridx = 1; + c.gridy = 0; + bucketComboBox = new JComboBox<>(); + Set bucketSet = ActiveCluster.getInstance().get().buckets().getAllBuckets().keySet(); + String[] buckets = bucketSet.toArray(new String[0]); + bucketComboBox.addItem("All buckets"); + for (String bucket : buckets) { + bucketComboBox.addItem(bucket); + } + dialogPanel.add(bucketComboBox, c); + // Line 2: Output format + c.gridx = 0; + c.gridy = 1; + JPanel outputFormatLabel = TemplateUtil.getLabelWithHelp("Output format:", + "Select the output format for mctimings"); + dialogPanel.add(outputFormatLabel, c); + + c.gridx = 1; + c.gridy = 1; + outputFormatComboBox = new JComboBox<>(); + outputFormatComboBox.addItem("Histogram"); + outputFormatComboBox.addItem("Json"); + outputFormatComboBox.addItem("Json pretty printed"); + dialogPanel.add(outputFormatComboBox, c); + + // Line 3: Optional parameters + c.gridx = 0; + c.gridy = 2; + JPanel optionalParametersLabel = TemplateUtil.getLabelWithHelp("Optional parameters:", + "Select the optional parameters for mctimings"); + dialogPanel.add(optionalParametersLabel, c); + + c.gridx = 1; + c.gridy = 2; + + String[] optionalParameters = { "Get", "Set", "Add", "Replace", "Delete", "Increment", "Decrement", "Quit", + "Flush", "GetQ", "No-op", "Version", "GetK", "GetKQ", "Append", "Prepend" }; + + List optionalParametersList = new ArrayList<>(Arrays.asList(optionalParameters)); + optionalParametersComboCheckBox.removeAllItems(); + optionalParametersComboCheckBox.setHint("Select some or none optional parameters"); + optionalParametersList.forEach(optionalParametersComboCheckBox::addItem); + dialogPanel.add(optionalParametersComboCheckBox, c); + + // Line 4: Output + c.gridx = 0; + c.gridy = 3; + JPanel outputLabel = TemplateUtil.getLabelWithHelp("Output:", ""); + dialogPanel.add(outputLabel, c); + + c.gridx = 0; + c.gridy = 4; + c.weightx = 1; + c.weighty = 1; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + outputPanel = new JPanel(new BorderLayout()); + + return dialogPanel; + } + + @Override + protected JComponent createSouthPanel() { + JButton displayTimingsButton; + JButton cancelButton; + JPanel southPanel; + southPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(e -> doCancelAction()); + southPanel.add(cancelButton); + displayTimingsButton = new JButton("Display Timings"); + displayTimingsButton.addActionListener(e -> doOKAction()); + southPanel.add(displayTimingsButton); + + return southPanel; + } + + public static class ChartGenerator { + protected JPanel generateBarChart(String[] labels, int[] values) { + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + + for (int i = 0; i < labels.length; i++) { + dataset.addValue(values[i], "Occurrences", labels[i]); + } + + JFreeChart barChart = ChartFactory.createBarChart( + "Bar Chart for Specified Period", + "Time Buckets", + "Occurrences", + dataset, + PlotOrientation.VERTICAL, + true, true, false); + + // Set dynamic range for Y-axis + NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); + rangeAxis.setRange(0, Arrays.stream(values).max().getAsInt()); + + // Rotate X-axis labels + CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); + domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); + + ChartPanel chartPanel = new ChartPanel(barChart); + chartPanel.setDisplayToolTips(true); // Enable tooltips + + return chartPanel; + } + } + + @Override + protected void doOKAction() { + dialogPanel.add(outputPanel, c); + getWindow().setMinimumSize(new Dimension(1800, 1000)); + + String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); + if (Objects.equals(selectedOutputFormat, "Histogram")) { + // Generate a bar chart using the hardcoded values + final String[] labels = { "[0.00 - 2.00]us", "[2.00 - 6.00]us", "[6.00 - 7.00]us", "[7.00 - 9.00]us", + "[9.00 - 11.00]us", "[11.00 - 13.00]us", "[13.00 - 15.00]us", "[15.00 - 16.00]us", + "[16.00 - 18.00]us", "[18.00 - 20.00]us", "[20.00 - 22.00]us", "[22.00 - 23.00]us", + "[23.00 - 25.00]us", "[25.00 - 26.00]us", "[26.00 - 28.00]us", "[28.00 - 30.00]us", + "[30.00 - 31.00]us", "[31.00 - 33.00]us", "[33.00 - 35.00]us", "[35.00 - 37.00]us", + "[37.00 - 39.00]us", "[39.00 - 39.00]us", "[39.00 - 41.00]us", "[41.00 - 41.00]us", + "[41.00 - 43.00]us", "[43.00 - 45.00]us", "[45.00 - 47.00]us", "[47.00 - 49.00]us", + "[49.00 - 51.00]us", "[51.00 - 53.00]us", "[53.00 - 57.00]us", "[57.00 - 57.00]us", + "[57.00 - 59.00]us", "[59.00 - 63.00]us", "[63.00 - 67.00]us", "[67.00 - 71.00]us", + "[71.00 - 75.00]us", "[75.00 - 75.00]us", "[75.00 - 79.00]us", "[79.00 - 83.00]us", + "[83.00 - 91.00]us", "[91.00 - 95.00]us", "[95.00 - 95.00]us", "[95.00 - 103.00]us", + "[103.00 - 111.00]us", "[111.00 - 123.00]us", "[123.00 - 127.00]us", "[127.00 - 135.00]us", + "[135.00 - 151.00]us", "[151.00 - 167.00]us", "[167.00 - 199.00]us", "[199.00 - 199.00]us", + "[199.00 - 215.00]us", "[215.00 - 215.00]us", "[215.00 - 231.00]us", "[231.00 - 287.00]us", + "[287.00 - 335.00]us", "[335.00 - 399.00]us", "[399.00 - 431.00]us", "[431.00 - 479.00]us", + "[479.00 - 479.00]us", "[479.00 - 543.00]us", "[543.00 - 831.00]us", "[831.00 - 831.00]us", + "[831.00 - 895.00]us", "[895.00 - 895.00]us", "[0.89 - 1.09]ms", "[1.09 - 1.09]ms", + "[1.09 - 1.09]ms", "[1.09 - 1.15]ms", "[1.15 - 1.15]ms", "[1.15 - 1.15]ms", "[1.15 - 1.15]ms", + "[1.15 - 1.15]ms", "[1.15 - 2.17]ms", "[2.17 - 2.17]ms", }; + + final int[] values = { 3, 3909, 1596, 2727, 2698, 2013, 1664, 766, 1336, 1237, 1016, 512, 892, 394, 672, + 645, 274, 453, 424, 310, 259, 0, 234, 0, 197, 134, 91, 96, 76, 60, 91, 0, 38, 56, 39, 36, 36, 0, 20, + 11, 25, 13, 0, 14, 9, 10, 1, 6, 5, 5, 6, 0, 5, 0, 4, 1, 1, 2, 1, 2, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, + 0, 0, 0, 1, 0 }; + + ChartGenerator chartGenerator = new ChartGenerator(); + JPanel chartPanel = chartGenerator.generateBarChart(labels, values); + outputPanel.removeAll(); + outputPanel.add(chartPanel, BorderLayout.CENTER); + outputPanel.revalidate(); + outputPanel.repaint(); + } else if (Objects.requireNonNull(selectedOutputFormat).startsWith("Json")) { + // Generate an empty text area + JTextArea outputTextArea = new JTextArea(); + + outputTextArea.setEditable(false); + JScrollPane scrollPane = new JScrollPane(outputTextArea); + outputPanel.removeAll(); + outputPanel.add(scrollPane, BorderLayout.CENTER); + outputPanel.revalidate(); + outputPanel.repaint(); + + // TODO: Impplement Text area + } + + } + + public void executeCommand(JTextArea outputTextArea) { + List command = new ArrayList<>(); + command.add(CBTools.getTool(CBTools.Type.MCTIMINGS).getPath()); + + // Add the selected bucket to the command + String selectedBucket = (String) bucketComboBox.getSelectedItem(); + if (!"All buckets".equals(selectedBucket)) { + command.add("-b"); + command.add(selectedBucket); + } else { + command.add("-a"); + } + + // Add the selected output format to the command + String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); + if ("Json".equals(selectedOutputFormat)) { + command.add("-o"); + command.add("json"); + } else if ("Json pretty printed".equals(selectedOutputFormat)) { + command.add("-o"); + command.add("jsonpretty"); + } + + // Add the selected optional parameters to the command + List selectedOptionalParameters = optionalParametersComboCheckBox.getSelectedItems(); + for (String parameter : selectedOptionalParameters) { + command.add("--" + parameter.toLowerCase()); + } + + ProcessBuilder processBuilder = new ProcessBuilder(command); + try { + Process process = processBuilder.start(); + ProcessUtils.printOutput(process, outputTextArea); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java index 6dfb780f..8a3bd6aa 100644 --- a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java +++ b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java @@ -12,7 +12,7 @@ import com.couchbase.intellij.tools.PillowFightDialog; import com.couchbase.intellij.tools.dialog.DDLExportDialog; import com.couchbase.intellij.tools.dialog.ExportDialog; -import com.couchbase.intellij.tree.NewEntityCreationDialog.EntityType; +import com.couchbase.intellij.tools.dialog.MctimingsDialog; import com.couchbase.intellij.tree.docfilter.DocumentFilterDialog; import com.couchbase.intellij.tree.node.*; import com.couchbase.intellij.tree.overview.IndexOverviewDialog; @@ -151,6 +151,17 @@ public void actionPerformed(@NotNull AnActionEvent e) { // tools.add(cbimport); // } + if (CBTools.getTool(CBTools.Type.MCTIMINGS).isAvailable()) { + AnAction cbmctimings = new AnAction("Mctimings") { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + MctimingsDialog dialog = new MctimingsDialog(); + dialog.show(); + } + }; + tools.add(cbmctimings); + } + DefaultActionGroup settings = new DefaultActionGroup("Settings", true); DefaultActionGroup colors = new DefaultActionGroup("Connection Colors", true); diff --git a/src/main/java/utils/ProcessUtils.java b/src/main/java/utils/ProcessUtils.java index a1e81ea5..1ad2013e 100644 --- a/src/main/java/utils/ProcessUtils.java +++ b/src/main/java/utils/ProcessUtils.java @@ -6,6 +6,8 @@ import java.io.IOException; import java.io.InputStreamReader; +import javax.swing.JTextArea; + public class ProcessUtils { public static void printOutput(Process process, String message) throws IOException { @@ -24,4 +26,20 @@ public static void printOutput(Process process, String message) throws IOExcepti } } } + + public static void printOutput(Process process, JTextArea textArea) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + textArea.append(line + "\n"); + } + } + // Consume and print the standard error + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + textArea.append(line + "\n"); + } + } + } } diff --git a/src/main/java/utils/TemplateUtil.java b/src/main/java/utils/TemplateUtil.java index 7c154408..a744e7fe 100644 --- a/src/main/java/utils/TemplateUtil.java +++ b/src/main/java/utils/TemplateUtil.java @@ -184,4 +184,11 @@ public static JPanel getLabelWithHelp(String text, String help) { panel.add(HelpIcon.createHelpIcon(help, 5)); return panel; } + + public static JPanel getLabelWithHelp(JLabel label, String help) { + JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + panel.add(label); + panel.add(HelpIcon.createHelpIcon(help, 5)); + return panel; + } } From 021d85eec8fc5898261e6326d1f677fcd067aaf8 Mon Sep 17 00:00:00 2001 From: teetangh Date: Mon, 11 Sep 2023 17:41:28 +0530 Subject: [PATCH 2/7] updated output text area in mctimings dialog box --- build.gradle.kts | 4 -- .../tools/dialog/MctimingsDialog.java | 52 ++++++++++++------- .../intellij/tree/TreeRightClickListener.java | 4 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 97d91849..e5ac5fe9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,10 +5,6 @@ plugins { group = "com.couchbase" version = "1.0.3" -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} sourceSets["main"].java.srcDirs("src/main/gen") diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index 3308553d..69759100 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -2,6 +2,7 @@ import com.couchbase.intellij.database.ActiveCluster; import com.couchbase.intellij.tools.CBTools; +import com.couchbase.intellij.workbench.Log; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.Nullable; @@ -13,7 +14,6 @@ import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; - import utils.ProcessUtils; import utils.TemplateUtil; @@ -76,6 +76,7 @@ protected JComponent createCenterPanel() { c.gridx = 1; c.gridy = 1; outputFormatComboBox = new JComboBox<>(); + outputFormatComboBox.addItem("Summary of All Operations"); outputFormatComboBox.addItem("Histogram"); outputFormatComboBox.addItem("Json"); outputFormatComboBox.addItem("Json pretty printed"); @@ -133,6 +134,7 @@ protected JComponent createSouthPanel() { return southPanel; } + public static class ChartGenerator { protected JPanel generateBarChart(String[] labels, int[] values) { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); @@ -151,7 +153,7 @@ protected JPanel generateBarChart(String[] labels, int[] values) { // Set dynamic range for Y-axis NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); - rangeAxis.setRange(0, Arrays.stream(values).max().getAsInt()); + rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); // Rotate X-axis labels CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); @@ -159,15 +161,18 @@ protected JPanel generateBarChart(String[] labels, int[] values) { ChartPanel chartPanel = new ChartPanel(barChart); chartPanel.setDisplayToolTips(true); // Enable tooltips + chartPanel.setMouseWheelEnabled(true); // Enable zooming using mouse wheel + chartPanel.setMouseZoomable(true); // Enable zooming using mouse drag return chartPanel; } } + @Override protected void doOKAction() { dialogPanel.add(outputPanel, c); - getWindow().setMinimumSize(new Dimension(1800, 1000)); + getWindow().setMinimumSize(new Dimension(1600, 800)); String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); if (Objects.equals(selectedOutputFormat, "Histogram")) { @@ -201,27 +206,37 @@ protected void doOKAction() { JPanel chartPanel = chartGenerator.generateBarChart(labels, values); outputPanel.removeAll(); outputPanel.add(chartPanel, BorderLayout.CENTER); - outputPanel.revalidate(); - outputPanel.repaint(); - } else if (Objects.requireNonNull(selectedOutputFormat).startsWith("Json")) { - // Generate an empty text area + + } else { JTextArea outputTextArea = new JTextArea(); outputTextArea.setEditable(false); + outputTextArea.setLineWrap(true); // Enable line wrapping + outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries + JScrollPane scrollPane = new JScrollPane(outputTextArea); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); // Disable horizontal scrolling + + executeCommand(outputTextArea); outputPanel.removeAll(); outputPanel.add(scrollPane, BorderLayout.CENTER); - outputPanel.revalidate(); - outputPanel.repaint(); - - // TODO: Impplement Text area } + outputPanel.revalidate(); + outputPanel.repaint(); } public void executeCommand(JTextArea outputTextArea) { List command = new ArrayList<>(); command.add(CBTools.getTool(CBTools.Type.MCTIMINGS).getPath()); + command.add("-h"); + command.add(ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")); + command.add("-p"); + command.add(ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210"); + command.add("-u"); + command.add(ActiveCluster.getInstance().getUsername()); + command.add("-P"); + command.add(ActiveCluster.getInstance().getPassword()); // Add the selected bucket to the command String selectedBucket = (String) bucketComboBox.getSelectedItem(); @@ -234,18 +249,17 @@ public void executeCommand(JTextArea outputTextArea) { // Add the selected output format to the command String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); - if ("Json".equals(selectedOutputFormat)) { - command.add("-o"); - command.add("json"); - } else if ("Json pretty printed".equals(selectedOutputFormat)) { - command.add("-o"); - command.add("jsonpretty"); + if (Objects.equals(selectedOutputFormat, "Json")){ + command.add("-j"); + } else if (Objects.equals(selectedOutputFormat, "Json pretty printed")){ + command.add("-j"); + command.add("-v"); } // Add the selected optional parameters to the command List selectedOptionalParameters = optionalParametersComboCheckBox.getSelectedItems(); for (String parameter : selectedOptionalParameters) { - command.add("--" + parameter.toLowerCase()); + command.add(" " + parameter.toLowerCase()); } ProcessBuilder processBuilder = new ProcessBuilder(command); @@ -253,7 +267,7 @@ public void executeCommand(JTextArea outputTextArea) { Process process = processBuilder.start(); ProcessUtils.printOutput(process, outputTextArea); } catch (IOException e) { - e.printStackTrace(); + Log.error("Exception Occurred: ",e); } } diff --git a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java index 8a3bd6aa..6f5a2862 100644 --- a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java +++ b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java @@ -151,7 +151,7 @@ public void actionPerformed(@NotNull AnActionEvent e) { // tools.add(cbimport); // } - if (CBTools.getTool(CBTools.Type.MCTIMINGS).isAvailable()) { + if (CBTools.getTool(CBTools.Type.MCTIMINGS).isAvailable()) { AnAction cbmctimings = new AnAction("Mctimings") { @Override public void actionPerformed(@NotNull AnActionEvent e) { @@ -160,7 +160,7 @@ public void actionPerformed(@NotNull AnActionEvent e) { } }; tools.add(cbmctimings); - } + } DefaultActionGroup settings = new DefaultActionGroup("Settings", true); DefaultActionGroup colors = new DefaultActionGroup("Connection Colors", true); From d7e1c2b5ad7b552032ac52b345933521171ebfb4 Mon Sep 17 00:00:00 2001 From: teetangh Date: Wed, 13 Sep 2023 08:30:57 +0530 Subject: [PATCH 3/7] All output formats working but sometimes out of memory on chart generation --- .../tools/dialog/MctimingsDialog.java | 250 ++++++++++++------ 1 file changed, 163 insertions(+), 87 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index 69759100..f00ed852 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -19,18 +19,27 @@ import javax.swing.*; import java.awt.*; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.util.List; import java.util.*; public class MctimingsDialog extends DialogWrapper { + private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); + private GridBagConstraints c; private JComboBox bucketComboBox; private JComboBox outputFormatComboBox; private JPanel outputPanel; private JPanel dialogPanel; - private GridBagConstraints c; - private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); + + private static final String SUMMARY_OF_ALL_OPERATIONS = "Summary of All Operations"; + private static final String HISTOGRAM = "Histogram"; + private static final String JSON = "Json"; + private static final String JSON_PRETTY_PRINTED = "Json pretty printed"; + + private JTextArea outputTextArea; public MctimingsDialog() { super(true); @@ -66,6 +75,7 @@ protected JComponent createCenterPanel() { bucketComboBox.addItem(bucket); } dialogPanel.add(bucketComboBox, c); + // Line 2: Output format c.gridx = 0; c.gridy = 1; @@ -76,10 +86,11 @@ protected JComponent createCenterPanel() { c.gridx = 1; c.gridy = 1; outputFormatComboBox = new JComboBox<>(); - outputFormatComboBox.addItem("Summary of All Operations"); - outputFormatComboBox.addItem("Histogram"); - outputFormatComboBox.addItem("Json"); - outputFormatComboBox.addItem("Json pretty printed"); + outputFormatComboBox.addItem(SUMMARY_OF_ALL_OPERATIONS); + outputFormatComboBox.addItem(HISTOGRAM); + outputFormatComboBox.addItem(JSON); + outputFormatComboBox.addItem(JSON_PRETTY_PRINTED); + dialogPanel.add(outputFormatComboBox, c); // Line 3: Optional parameters @@ -113,7 +124,6 @@ protected JComponent createCenterPanel() { c.weighty = 1; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; - outputPanel = new JPanel(new BorderLayout()); return dialogPanel; } @@ -134,99 +144,45 @@ protected JComponent createSouthPanel() { return southPanel; } - - public static class ChartGenerator { - protected JPanel generateBarChart(String[] labels, int[] values) { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - for (int i = 0; i < labels.length; i++) { - dataset.addValue(values[i], "Occurrences", labels[i]); - } - - JFreeChart barChart = ChartFactory.createBarChart( - "Bar Chart for Specified Period", - "Time Buckets", - "Occurrences", - dataset, - PlotOrientation.VERTICAL, - true, true, false); - - // Set dynamic range for Y-axis - NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); - rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - - // Rotate X-axis labels - CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); - domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); - - ChartPanel chartPanel = new ChartPanel(barChart); - chartPanel.setDisplayToolTips(true); // Enable tooltips - chartPanel.setMouseWheelEnabled(true); // Enable zooming using mouse wheel - chartPanel.setMouseZoomable(true); // Enable zooming using mouse drag - - return chartPanel; - } - } - - @Override protected void doOKAction() { - dialogPanel.add(outputPanel, c); + getWindow().setMinimumSize(new Dimension(1600, 800)); + if (outputPanel != null) { + outputPanel.removeAll(); + dialogPanel.remove(outputPanel); + } String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); - if (Objects.equals(selectedOutputFormat, "Histogram")) { - // Generate a bar chart using the hardcoded values - final String[] labels = { "[0.00 - 2.00]us", "[2.00 - 6.00]us", "[6.00 - 7.00]us", "[7.00 - 9.00]us", - "[9.00 - 11.00]us", "[11.00 - 13.00]us", "[13.00 - 15.00]us", "[15.00 - 16.00]us", - "[16.00 - 18.00]us", "[18.00 - 20.00]us", "[20.00 - 22.00]us", "[22.00 - 23.00]us", - "[23.00 - 25.00]us", "[25.00 - 26.00]us", "[26.00 - 28.00]us", "[28.00 - 30.00]us", - "[30.00 - 31.00]us", "[31.00 - 33.00]us", "[33.00 - 35.00]us", "[35.00 - 37.00]us", - "[37.00 - 39.00]us", "[39.00 - 39.00]us", "[39.00 - 41.00]us", "[41.00 - 41.00]us", - "[41.00 - 43.00]us", "[43.00 - 45.00]us", "[45.00 - 47.00]us", "[47.00 - 49.00]us", - "[49.00 - 51.00]us", "[51.00 - 53.00]us", "[53.00 - 57.00]us", "[57.00 - 57.00]us", - "[57.00 - 59.00]us", "[59.00 - 63.00]us", "[63.00 - 67.00]us", "[67.00 - 71.00]us", - "[71.00 - 75.00]us", "[75.00 - 75.00]us", "[75.00 - 79.00]us", "[79.00 - 83.00]us", - "[83.00 - 91.00]us", "[91.00 - 95.00]us", "[95.00 - 95.00]us", "[95.00 - 103.00]us", - "[103.00 - 111.00]us", "[111.00 - 123.00]us", "[123.00 - 127.00]us", "[127.00 - 135.00]us", - "[135.00 - 151.00]us", "[151.00 - 167.00]us", "[167.00 - 199.00]us", "[199.00 - 199.00]us", - "[199.00 - 215.00]us", "[215.00 - 215.00]us", "[215.00 - 231.00]us", "[231.00 - 287.00]us", - "[287.00 - 335.00]us", "[335.00 - 399.00]us", "[399.00 - 431.00]us", "[431.00 - 479.00]us", - "[479.00 - 479.00]us", "[479.00 - 543.00]us", "[543.00 - 831.00]us", "[831.00 - 831.00]us", - "[831.00 - 895.00]us", "[895.00 - 895.00]us", "[0.89 - 1.09]ms", "[1.09 - 1.09]ms", - "[1.09 - 1.09]ms", "[1.09 - 1.15]ms", "[1.15 - 1.15]ms", "[1.15 - 1.15]ms", "[1.15 - 1.15]ms", - "[1.15 - 1.15]ms", "[1.15 - 2.17]ms", "[2.17 - 2.17]ms", }; - - final int[] values = { 3, 3909, 1596, 2727, 2698, 2013, 1664, 766, 1336, 1237, 1016, 512, 892, 394, 672, - 645, 274, 453, 424, 310, 259, 0, 234, 0, 197, 134, 91, 96, 76, 60, 91, 0, 38, 56, 39, 36, 36, 0, 20, - 11, 25, 13, 0, 14, 9, 10, 1, 6, 5, 5, 6, 0, 5, 0, 4, 1, 1, 2, 1, 2, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, - 0, 0, 0, 1, 0 }; - - ChartGenerator chartGenerator = new ChartGenerator(); - JPanel chartPanel = chartGenerator.generateBarChart(labels, values); - outputPanel.removeAll(); - outputPanel.add(chartPanel, BorderLayout.CENTER); + if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { + outputPanel = new JPanel(); + outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.Y_AXIS)); + executeCommand(); } else { - JTextArea outputTextArea = new JTextArea(); + outputTextArea = new JTextArea(); outputTextArea.setEditable(false); - outputTextArea.setLineWrap(true); // Enable line wrapping - outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries + outputTextArea.setLineWrap(true); // Enable line wrapping + outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries JScrollPane scrollPane = new JScrollPane(outputTextArea); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); // Disable horizontal scrolling + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - executeCommand(outputTextArea); - outputPanel.removeAll(); + outputPanel = new JPanel(new BorderLayout()); + executeCommand(); outputPanel.add(scrollPane, BorderLayout.CENTER); + outputPanel.revalidate(); + outputPanel.repaint(); + dialogPanel.add(outputPanel, c); } - outputPanel.revalidate(); - outputPanel.repaint(); + dialogPanel.revalidate(); + dialogPanel.repaint(); + } - public void executeCommand(JTextArea outputTextArea) { + public void executeCommand() { List command = new ArrayList<>(); command.add(CBTools.getTool(CBTools.Type.MCTIMINGS).getPath()); command.add("-h"); @@ -249,9 +205,11 @@ public void executeCommand(JTextArea outputTextArea) { // Add the selected output format to the command String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); - if (Objects.equals(selectedOutputFormat, "Json")){ + if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { + command.add("-v"); + } else if (Objects.equals(selectedOutputFormat, JSON)) { command.add("-j"); - } else if (Objects.equals(selectedOutputFormat, "Json pretty printed")){ + } else if (Objects.equals(selectedOutputFormat, JSON_PRETTY_PRINTED)) { command.add("-j"); command.add("-v"); } @@ -265,9 +223,127 @@ public void executeCommand(JTextArea outputTextArea) { ProcessBuilder processBuilder = new ProcessBuilder(command); try { Process process = processBuilder.start(); - ProcessUtils.printOutput(process, outputTextArea); + if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { + Map>> histogramData = parseHistogram(process); + generateHistograms(histogramData); + } else + ProcessUtils.printOutput(process, outputTextArea); } catch (IOException e) { - Log.error("Exception Occurred: ",e); + Log.error("Exception Occurred: ", e); + } + } + + public static Map>> parseHistogram(Process process) throws IOException { + Map>> histogramData = new HashMap<>(); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + String currentBucket = ""; + String currentOperation = ""; + String bucketTag = "Bucket:"; + String operationTag = "The following data is collected for "; + while ((line = reader.readLine()) != null) { + if (line.startsWith(bucketTag)) { + currentBucket = line.substring(bucketTag.length()).trim().replaceAll("[\"']", ""); + histogramData.put(currentBucket, new HashMap<>()); + } else if (line.startsWith(operationTag)) { + currentOperation = line.substring(operationTag.length()).trim().replaceAll("[\"']", ""); + histogramData.get(currentBucket).put(currentOperation, new HashMap<>()); + } else if (histogramData.containsKey(currentBucket) + && histogramData.get(currentBucket).containsKey(currentOperation)) { + String label; + String value; + + int labelStartIndex = line.indexOf(" ("); + int valueStartIndex = line.indexOf("%)"); + int pipeIndex = line.indexOf("|"); + + if (labelStartIndex != -1 && valueStartIndex != -1 && pipeIndex != -1) { + label = line.substring(0, labelStartIndex).trim(); + value = line.substring(valueStartIndex + 3, pipeIndex).trim(); + histogramData.get(currentBucket).get(currentOperation).put(label, value); + } + } + } + } + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + Log.error(line); + } + } + + return histogramData; + } + + public void generateHistograms(Map>> histogramData) { + // For each bucket in the histogram data + for (Map.Entry>> bucketEntry : histogramData.entrySet()) { + String bucket = bucketEntry.getKey(); + Map> operationsData = bucketEntry.getValue(); + + // For each operation in the bucket + for (Map.Entry> operationEntry : operationsData.entrySet()) { + String operation = operationEntry.getKey(); + Map operationData = operationEntry.getValue(); + + // Get the labels and values for this operation + String[] labels = operationData.keySet().toArray(new String[0]); + int[] values = operationData.values().stream().mapToInt(Integer::parseInt).toArray(); + + // Generate a bar chart using the labels and values + ChartGenerator chartGenerator = new ChartGenerator(); + JPanel chartPanel = chartGenerator.generateBarChart(bucket, operation, labels, values); + + // Set preferred size for the chart panel + chartPanel.setPreferredSize(new Dimension(1600, 800)); + + // Add the chart to the output panel + outputPanel.add(chartPanel); + } + } + + // Create a JScrollPane containing the output panel + JScrollPane scrollPane = new JScrollPane(outputPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + // Replace output panel with scroll pane in dialog panel + dialogPanel.remove(outputPanel); + dialogPanel.add(scrollPane, c); + } + + public static class ChartGenerator { + protected JPanel generateBarChart(String bucket, String operation, String[] labels, int[] values) { + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + + for (int i = 0; i < labels.length; i++) { + dataset.addValue(values[i], "Occurrences", labels[i]); + } + + JFreeChart barChart = ChartFactory.createBarChart( + "Operaton Duration Histogram for " + bucket + "with operation " + operation, + "Operation Duration", + "Occurrences", + dataset, + PlotOrientation.VERTICAL, + true, true, false); + + // Set dynamic range for Y-axis + NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); + rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); + + // Rotate X-axis labels + CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); + domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); + + ChartPanel chartPanel = new ChartPanel(barChart); + chartPanel.setDisplayToolTips(true); // Enable tooltips + chartPanel.setMouseWheelEnabled(true); // Enable zooming using mouse wheel + chartPanel.setMouseZoomable(true); // Enable zooming using mouse drag + + return chartPanel; } } From f6e45afd7130021bf724826d7e04184fbfc2c267 Mon Sep 17 00:00:00 2001 From: teetangh Date: Wed, 13 Sep 2023 09:39:38 +0530 Subject: [PATCH 4/7] added all optional parameters + optimised generating histograms + added all optional parameters in one line --- .../tools/dialog/MctimingsDialog.java | 90 +++++++++++++++---- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index f00ed852..21c7c05d 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -1,10 +1,30 @@ package com.couchbase.intellij.tools.dialog; -import com.couchbase.intellij.database.ActiveCluster; -import com.couchbase.intellij.tools.CBTools; -import com.couchbase.intellij.workbench.Log; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.util.ui.JBUI; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; + import org.jetbrains.annotations.Nullable; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; @@ -14,17 +34,16 @@ import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; + +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.tools.CBTools; +import com.couchbase.intellij.workbench.Log; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.util.ui.JBUI; + import utils.ProcessUtils; import utils.TemplateUtil; -import javax.swing.*; -import java.awt.*; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; -import java.util.*; - public class MctimingsDialog extends DialogWrapper { private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); @@ -104,7 +123,29 @@ protected JComponent createCenterPanel() { c.gridy = 2; String[] optionalParameters = { "Get", "Set", "Add", "Replace", "Delete", "Increment", "Decrement", "Quit", - "Flush", "GetQ", "No-op", "Version", "GetK", "GetKQ", "Append", "Prepend" }; + "Flush", "GetQ", "No-op", "Version", "GetK", "GetKQ", "Append", "Prepend", "Stat", "SetQ", "AddQ", + "ReplaceQ", "DeleteQ", "IncrementQ", "DecrementQ", "QuitQ", "FlushQ", "AppendQ", "PrependQ", + "Verbosity", "Touch", "GAT", "GATQ", "HELO", "SASL list mechs", "SASL Auth", "SASL Step", "Ioctl get", + "Ioctl set", "Config validate", "Config reload", "Audit put", "Audit config reload", "Shutdown", "RGet", + "RSet", "RSetQ", "RAppend", "RAppendQ", "RPrepend", "RPrependQ", "RDelete", "RDeleteQ", "RIncr", + "RIncrQ", "RDecr", "RDecrQ", "Set VBucket", "Get VBucket", "Del VBucket", "TAP Connect", "TAP Mutation", + "TAP Delete", "TAP Flush", "TAP Opaque", "TAP VBucket Set", "TAP Checkout Start", "TAP Checkpoint End", + "Get all vb seqnos", "Dcp Open", "Dcp add stream", "Dcp close stream", "Dcp stream req", + "Dcp get failover log", "Dcp stream end", "Dcp snapshot marker", "Dcp mutation", "Dcp deletion", + "Dcp expiration", "Dcp flush", "Dcp set vbucket state", "Dcp noop", "Dcp buffer acknowledgement", + "Dcp control", "Dcp reserved4", "Stop persistence", "Start persistence", "Set param", "Get replica", + "Create bucket", "Delete bucket", "List buckets", "Select bucket", "Assume role", "Observe seqno", + "Observe", "Evict key", "Get locked", "Unlock key", "Last closed checkpoint", "Deregister tap client", + "Reset replication chain", "Get meta", "Getq meta", "Set with meta", "Setq with meta", "Add with meta", + "Addq with meta", "Snapshot vb states", "Vbucket batch count", "Del with meta", "Delq with meta", + "Create checkpoint", "Notify vbucket update", "Enable traffic", "Disable traffic", "Change vb filter", + "Checkpoint persistence", "Return meta", "Compact db", "Set cluster config", "Get cluster config", + "Get random key", "Seqno persistence", "Get keys", "Set drift counter state", "Get adjusted time", + "Subdoc get", "Subdoc exists", "Subdoc dict add", "Subdoc dict upsert", "Subdoc delete", + "Subdoc replace", "Subdoc array push last", "Subdoc array push first", "Subdoc array insert", + "Subdoc array add unique", "Subdoc counter", "Subdoc multi lookup", "Subdoc multi mutation", "Scrub", + "Isasl refresh", "Ssl certs refresh", "Get cmd timer", "Set ctrl token", "Get ctrl token", + "Init complete" }; List optionalParametersList = new ArrayList<>(Arrays.asList(optionalParameters)); optionalParametersComboCheckBox.removeAllItems(); @@ -216,10 +257,13 @@ public void executeCommand() { // Add the selected optional parameters to the command List selectedOptionalParameters = optionalParametersComboCheckBox.getSelectedItems(); - for (String parameter : selectedOptionalParameters) { - command.add(" " + parameter.toLowerCase()); + if (!selectedOptionalParameters.isEmpty()) { + String parameters = String.join(" ", selectedOptionalParameters).toLowerCase(); + command.add(parameters); } + Log.debug("Command is" + command); + ProcessBuilder processBuilder = new ProcessBuilder(command); try { Process process = processBuilder.start(); @@ -289,8 +333,16 @@ public void generateHistograms(Map>> his Map operationData = operationEntry.getValue(); // Get the labels and values for this operation - String[] labels = operationData.keySet().toArray(new String[0]); - int[] values = operationData.values().stream().mapToInt(Integer::parseInt).toArray(); + int size = operationData.size(); + String[] labels = new String[size]; + int[] values = new int[size]; + int index = 0; + + for (Map.Entry entry : operationData.entrySet()) { + labels[index] = entry.getKey(); + values[index] = Integer.parseInt(entry.getValue()); + index++; + } // Generate a bar chart using the labels and values ChartGenerator chartGenerator = new ChartGenerator(); @@ -323,7 +375,7 @@ protected JPanel generateBarChart(String bucket, String operation, String[] labe } JFreeChart barChart = ChartFactory.createBarChart( - "Operaton Duration Histogram for " + bucket + "with operation " + operation, + "Operation Duration Histogram for " + bucket + "with operation " + operation, "Operation Duration", "Occurrences", dataset, From 220eb1795ad72d462940dd5c0a034a88f9a4890c Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 14 Sep 2023 12:42:54 +0530 Subject: [PATCH 5/7] seperated UI from Api --- .../couchbase/intellij/tools/Mctimings.java | 236 +++++++++++++++++ .../tools/dialog/MctimingsDialog.java | 248 ++---------------- src/main/java/utils/ProcessUtils.java | 16 +- 3 files changed, 274 insertions(+), 226 deletions(-) create mode 100644 src/main/java/com/couchbase/intellij/tools/Mctimings.java diff --git a/src/main/java/com/couchbase/intellij/tools/Mctimings.java b/src/main/java/com/couchbase/intellij/tools/Mctimings.java new file mode 100644 index 00000000..aa2d7a04 --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tools/Mctimings.java @@ -0,0 +1,236 @@ +package com.couchbase.intellij.tools; + +import java.awt.Dimension; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.swing.BoxLayout; +import javax.swing.JPanel; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.category.DefaultCategoryDataset; + +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.workbench.Log; + +import utils.ProcessUtils; + +public class Mctimings { + + private static final String HISTOGRAM = "Histogram"; + private static final String JSON = "Json"; + private static final String JSON_PRETTY_PRINTED = "Json pretty printed"; + + private final String selectedBucket; + private final String selectedOutputFormat; + private final List selectedOptionalParameters; + + public Mctimings(String selectedBucket, String selectedOutputFormat, List selectedOptionalParameters) { + this.selectedBucket = selectedBucket; + this.selectedOutputFormat = selectedOutputFormat; + this.selectedOptionalParameters = selectedOptionalParameters; + + } + + public JPanel executeCommandAndReturnPanel() { + JPanel outputPanel = new JPanel(); + outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.Y_AXIS)); + List command = executeCommand(); + + ProcessBuilder processBuilder = new ProcessBuilder(command); + try { + Process process = processBuilder.start(); + Map>> histogramData = parseHistogram(process); + outputPanel = generateHistograms(histogramData); + + } catch (IOException e) { + Log.error("Exception Occurred: ", e); + } + return outputPanel; + } + + public String executeCommandAndReturnString() { + String output = ""; + List command = executeCommand(); + + ProcessBuilder processBuilder = new ProcessBuilder(command); + try { + Process process = processBuilder.start(); + output = ProcessUtils.returnOutput(process); + } catch (IOException e) { + Log.error("Exception Occurred: ", e); + } + return output; + } + + public List executeCommand() { + List command = new ArrayList<>(); + command.add(CBTools.getTool(CBTools.Type.MCTIMINGS).getPath()); + command.add("-h"); + command.add(ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")); + command.add("-p"); + command.add(ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210"); + command.add("-u"); + command.add(ActiveCluster.getInstance().getUsername()); + command.add("-P"); + command.add(ActiveCluster.getInstance().getPassword()); + + // Add the selected bucket to the command + if (!"All buckets".equals(selectedBucket)) { + command.add("-b"); + command.add(selectedBucket); + } else { + command.add("-a"); + } + + // Add the selected output format to the command + if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { + command.add("-v"); + } else if (Objects.equals(selectedOutputFormat, JSON)) { + command.add("-j"); + } else if (Objects.equals(selectedOutputFormat, JSON_PRETTY_PRINTED)) { + command.add("-j"); + command.add("-v"); + } + + // Add the selected optional parameters to the command + if (!selectedOptionalParameters.isEmpty()) { + String parameters = String.join(" ", selectedOptionalParameters).toLowerCase(); + command.add(parameters); + } + + Log.debug("Command is" + command); + return command; + } + + public static Map>> parseHistogram(Process process) throws IOException { + Map>> histogramData = new HashMap<>(); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + String currentBucket = ""; + String currentOperation = ""; + String bucketTag = "Bucket:"; + String operationTag = "The following data is collected for "; + while ((line = reader.readLine()) != null) { + if (line.startsWith(bucketTag)) { + currentBucket = line.substring(bucketTag.length()).trim().replaceAll("[\"']", ""); + histogramData.put(currentBucket, new HashMap<>()); + } else if (line.startsWith(operationTag)) { + currentOperation = line.substring(operationTag.length()).trim().replaceAll("[\"']", ""); + histogramData.get(currentBucket).put(currentOperation, new HashMap<>()); + } else if (histogramData.containsKey(currentBucket) + && histogramData.get(currentBucket).containsKey(currentOperation)) { + String label; + String value; + + int labelStartIndex = line.indexOf(" ("); + int valueStartIndex = line.indexOf("%)"); + int pipeIndex = line.indexOf("|"); + + if (labelStartIndex != -1 && valueStartIndex != -1 && pipeIndex != -1) { + label = line.substring(0, labelStartIndex).trim(); + value = line.substring(valueStartIndex + 3, pipeIndex).trim(); + histogramData.get(currentBucket).get(currentOperation).put(label, value); + } + } + } + } + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + Log.error(line); + } + } + + return histogramData; + } + + public JPanel generateHistograms(Map>> histogramData) { + JPanel outputPanel = new JPanel(); + outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.Y_AXIS)); + + // For each bucket in the histogram data + for (Map.Entry>> bucketEntry : histogramData.entrySet()) { + String bucket = bucketEntry.getKey(); + Map> operationsData = bucketEntry.getValue(); + + // For each operation in the bucket + for (Map.Entry> operationEntry : operationsData.entrySet()) { + String operation = operationEntry.getKey(); + Map operationData = operationEntry.getValue(); + + // Get the labels and values for this operation + int size = operationData.size(); + String[] labels = new String[size]; + int[] values = new int[size]; + int index = 0; + + for (Map.Entry entry : operationData.entrySet()) { + labels[index] = entry.getKey(); + values[index] = Integer.parseInt(entry.getValue()); + index++; + } + + // Generate a bar chart using the labels and values + ChartGenerator chartGenerator = new ChartGenerator(); + JPanel chartPanel = chartGenerator.generateBarChart(bucket, operation, labels, values); + + // Set preferred size for the chart panel + chartPanel.setPreferredSize(new Dimension(1600, 800)); + + // Add the chart to the output panel + outputPanel.add(chartPanel); + } + } + + return outputPanel; + + } + + public static class ChartGenerator { + protected JPanel generateBarChart(String bucket, String operation, String[] labels, int[] values) { + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + + for (int i = 0; i < labels.length; i++) { + dataset.addValue(values[i], "Occurrences", labels[i]); + } + + JFreeChart barChart = ChartFactory.createBarChart( + "Operation Duration Histogram for " + bucket + "with operation " + operation, + "Operation Duration", + "Occurrences", + dataset, + PlotOrientation.VERTICAL, + true, true, false); + + // Set dynamic range for Y-axis + NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); + rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); + + // Rotate X-axis labels + CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); + domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); + + ChartPanel chartPanel = new ChartPanel(barChart); + chartPanel.setDisplayToolTips(true); // Enable tooltips + chartPanel.setMouseWheelEnabled(true); // Enable zooming using mouse wheel + chartPanel.setMouseZoomable(true); // Enable zooming using mouse drag + + return chartPanel; + } + } +} diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index 21c7c05d..380f7c3c 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -1,49 +1,17 @@ package com.couchbase.intellij.tools.dialog; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.ScrollPaneConstants; - -import org.jetbrains.annotations.Nullable; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.data.category.DefaultCategoryDataset; - import com.couchbase.intellij.database.ActiveCluster; -import com.couchbase.intellij.tools.CBTools; -import com.couchbase.intellij.workbench.Log; +import com.couchbase.intellij.tools.Mctimings; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.util.ui.JBUI; - -import utils.ProcessUtils; +import org.jetbrains.annotations.Nullable; import utils.TemplateUtil; +import javax.swing.*; +import java.awt.*; +import java.util.List; +import java.util.*; + public class MctimingsDialog extends DialogWrapper { private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); @@ -58,8 +26,6 @@ public class MctimingsDialog extends DialogWrapper { private static final String JSON = "Json"; private static final String JSON_PRETTY_PRINTED = "Json pretty printed"; - private JTextArea outputTextArea; - public MctimingsDialog() { super(true); init(); @@ -194,14 +160,25 @@ protected void doOKAction() { dialogPanel.remove(outputPanel); } + String selectedBucket = (String) bucketComboBox.getSelectedItem(); String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); + List selectedOptionalParameters = optionalParametersComboCheckBox.getSelectedItems(); + if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { - outputPanel = new JPanel(); - outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.Y_AXIS)); - executeCommand(); + Mctimings mctimings = new Mctimings(selectedBucket, selectedOutputFormat, selectedOptionalParameters); + outputPanel = mctimings.executeCommandAndReturnPanel(); + + // Create a JScrollPane containing the output panel + JScrollPane scrollPane = new JScrollPane(outputPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + + // Replace output panel with scroll pane in dialog panel + dialogPanel.remove(outputPanel); + dialogPanel.add(scrollPane, c); } else { - outputTextArea = new JTextArea(); + JTextArea outputTextArea = new JTextArea(); outputTextArea.setEditable(false); outputTextArea.setLineWrap(true); // Enable line wrapping @@ -211,7 +188,10 @@ protected void doOKAction() { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); outputPanel = new JPanel(new BorderLayout()); - executeCommand(); + Mctimings mctimings = new Mctimings(selectedBucket, selectedOutputFormat, selectedOptionalParameters); + String output = mctimings.executeCommandAndReturnString(); + outputTextArea.setText(output); + outputPanel.add(scrollPane, BorderLayout.CENTER); outputPanel.revalidate(); outputPanel.repaint(); @@ -223,180 +203,4 @@ protected void doOKAction() { } - public void executeCommand() { - List command = new ArrayList<>(); - command.add(CBTools.getTool(CBTools.Type.MCTIMINGS).getPath()); - command.add("-h"); - command.add(ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")); - command.add("-p"); - command.add(ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210"); - command.add("-u"); - command.add(ActiveCluster.getInstance().getUsername()); - command.add("-P"); - command.add(ActiveCluster.getInstance().getPassword()); - - // Add the selected bucket to the command - String selectedBucket = (String) bucketComboBox.getSelectedItem(); - if (!"All buckets".equals(selectedBucket)) { - command.add("-b"); - command.add(selectedBucket); - } else { - command.add("-a"); - } - - // Add the selected output format to the command - String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); - if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { - command.add("-v"); - } else if (Objects.equals(selectedOutputFormat, JSON)) { - command.add("-j"); - } else if (Objects.equals(selectedOutputFormat, JSON_PRETTY_PRINTED)) { - command.add("-j"); - command.add("-v"); - } - - // Add the selected optional parameters to the command - List selectedOptionalParameters = optionalParametersComboCheckBox.getSelectedItems(); - if (!selectedOptionalParameters.isEmpty()) { - String parameters = String.join(" ", selectedOptionalParameters).toLowerCase(); - command.add(parameters); - } - - Log.debug("Command is" + command); - - ProcessBuilder processBuilder = new ProcessBuilder(command); - try { - Process process = processBuilder.start(); - if (Objects.equals(selectedOutputFormat, HISTOGRAM)) { - Map>> histogramData = parseHistogram(process); - generateHistograms(histogramData); - } else - ProcessUtils.printOutput(process, outputTextArea); - } catch (IOException e) { - Log.error("Exception Occurred: ", e); - } - } - - public static Map>> parseHistogram(Process process) throws IOException { - Map>> histogramData = new HashMap<>(); - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line; - String currentBucket = ""; - String currentOperation = ""; - String bucketTag = "Bucket:"; - String operationTag = "The following data is collected for "; - while ((line = reader.readLine()) != null) { - if (line.startsWith(bucketTag)) { - currentBucket = line.substring(bucketTag.length()).trim().replaceAll("[\"']", ""); - histogramData.put(currentBucket, new HashMap<>()); - } else if (line.startsWith(operationTag)) { - currentOperation = line.substring(operationTag.length()).trim().replaceAll("[\"']", ""); - histogramData.get(currentBucket).put(currentOperation, new HashMap<>()); - } else if (histogramData.containsKey(currentBucket) - && histogramData.get(currentBucket).containsKey(currentOperation)) { - String label; - String value; - - int labelStartIndex = line.indexOf(" ("); - int valueStartIndex = line.indexOf("%)"); - int pipeIndex = line.indexOf("|"); - - if (labelStartIndex != -1 && valueStartIndex != -1 && pipeIndex != -1) { - label = line.substring(0, labelStartIndex).trim(); - value = line.substring(valueStartIndex + 3, pipeIndex).trim(); - histogramData.get(currentBucket).get(currentOperation).put(label, value); - } - } - } - } - - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - String line; - while ((line = reader.readLine()) != null) { - Log.error(line); - } - } - - return histogramData; - } - - public void generateHistograms(Map>> histogramData) { - // For each bucket in the histogram data - for (Map.Entry>> bucketEntry : histogramData.entrySet()) { - String bucket = bucketEntry.getKey(); - Map> operationsData = bucketEntry.getValue(); - - // For each operation in the bucket - for (Map.Entry> operationEntry : operationsData.entrySet()) { - String operation = operationEntry.getKey(); - Map operationData = operationEntry.getValue(); - - // Get the labels and values for this operation - int size = operationData.size(); - String[] labels = new String[size]; - int[] values = new int[size]; - int index = 0; - - for (Map.Entry entry : operationData.entrySet()) { - labels[index] = entry.getKey(); - values[index] = Integer.parseInt(entry.getValue()); - index++; - } - - // Generate a bar chart using the labels and values - ChartGenerator chartGenerator = new ChartGenerator(); - JPanel chartPanel = chartGenerator.generateBarChart(bucket, operation, labels, values); - - // Set preferred size for the chart panel - chartPanel.setPreferredSize(new Dimension(1600, 800)); - - // Add the chart to the output panel - outputPanel.add(chartPanel); - } - } - - // Create a JScrollPane containing the output panel - JScrollPane scrollPane = new JScrollPane(outputPanel); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - - // Replace output panel with scroll pane in dialog panel - dialogPanel.remove(outputPanel); - dialogPanel.add(scrollPane, c); - } - - public static class ChartGenerator { - protected JPanel generateBarChart(String bucket, String operation, String[] labels, int[] values) { - DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - for (int i = 0; i < labels.length; i++) { - dataset.addValue(values[i], "Occurrences", labels[i]); - } - - JFreeChart barChart = ChartFactory.createBarChart( - "Operation Duration Histogram for " + bucket + "with operation " + operation, - "Operation Duration", - "Occurrences", - dataset, - PlotOrientation.VERTICAL, - true, true, false); - - // Set dynamic range for Y-axis - NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); - rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - - // Rotate X-axis labels - CategoryAxis domainAxis = barChart.getCategoryPlot().getDomainAxis(); - domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); - - ChartPanel chartPanel = new ChartPanel(barChart); - chartPanel.setDisplayToolTips(true); // Enable tooltips - chartPanel.setMouseWheelEnabled(true); // Enable zooming using mouse wheel - chartPanel.setMouseZoomable(true); // Enable zooming using mouse drag - - return chartPanel; - } - } - } diff --git a/src/main/java/utils/ProcessUtils.java b/src/main/java/utils/ProcessUtils.java index 1ad2013e..b9129614 100644 --- a/src/main/java/utils/ProcessUtils.java +++ b/src/main/java/utils/ProcessUtils.java @@ -2,6 +2,7 @@ import com.couchbase.intellij.workbench.Log; +import java.awt.TextArea; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -27,19 +28,26 @@ public static void printOutput(Process process, String message) throws IOExcepti } } - public static void printOutput(Process process, JTextArea textArea) throws IOException { + public static String returnOutput(Process process) throws IOException { + StringBuilder output = new StringBuilder(); + + // Process standard output try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { - textArea.append(line + "\n"); + output.append(line).append("\n"); } } - // Consume and print the standard error + + // Process standard error try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { String line; while ((line = reader.readLine()) != null) { - textArea.append(line + "\n"); + output.append(line).append("\n"); } } + + return output.toString(); } + } From 27c841d3dee50ebd6ac3c8f1d629b48de52de02b Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 14 Sep 2023 13:42:16 +0530 Subject: [PATCH 6/7] minor edit in optional parameter fetching --- .../tools/dialog/MctimingsDialog.java | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index 380f7c3c..2f0ff4b3 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -4,6 +4,7 @@ import com.couchbase.intellij.tools.Mctimings; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import utils.TemplateUtil; @@ -88,6 +89,30 @@ protected JComponent createCenterPanel() { c.gridx = 1; c.gridy = 2; + List optionalParametersList = getStrings(); + optionalParametersComboCheckBox.removeAllItems(); + optionalParametersComboCheckBox.setHint("Select some or none optional parameters"); + optionalParametersList.forEach(optionalParametersComboCheckBox::addItem); + dialogPanel.add(optionalParametersComboCheckBox, c); + + // Line 4: Output + c.gridx = 0; + c.gridy = 3; + JPanel outputLabel = TemplateUtil.getLabelWithHelp("Output:", ""); + dialogPanel.add(outputLabel, c); + + c.gridx = 0; + c.gridy = 4; + c.weightx = 1; + c.weighty = 1; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + + return dialogPanel; + } + + @NotNull + private static List getStrings() { String[] optionalParameters = { "Get", "Set", "Add", "Replace", "Delete", "Increment", "Decrement", "Quit", "Flush", "GetQ", "No-op", "Version", "GetK", "GetKQ", "Append", "Prepend", "Stat", "SetQ", "AddQ", "ReplaceQ", "DeleteQ", "IncrementQ", "DecrementQ", "QuitQ", "FlushQ", "AppendQ", "PrependQ", @@ -113,26 +138,7 @@ protected JComponent createCenterPanel() { "Isasl refresh", "Ssl certs refresh", "Get cmd timer", "Set ctrl token", "Get ctrl token", "Init complete" }; - List optionalParametersList = new ArrayList<>(Arrays.asList(optionalParameters)); - optionalParametersComboCheckBox.removeAllItems(); - optionalParametersComboCheckBox.setHint("Select some or none optional parameters"); - optionalParametersList.forEach(optionalParametersComboCheckBox::addItem); - dialogPanel.add(optionalParametersComboCheckBox, c); - - // Line 4: Output - c.gridx = 0; - c.gridy = 3; - JPanel outputLabel = TemplateUtil.getLabelWithHelp("Output:", ""); - dialogPanel.add(outputLabel, c); - - c.gridx = 0; - c.gridy = 4; - c.weightx = 1; - c.weighty = 1; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - - return dialogPanel; + return new ArrayList<>(Arrays.asList(optionalParameters)); } @Override From 37bac0645384a12669a02ce9d2b7e6d1c068aa60 Mon Sep 17 00:00:00 2001 From: teetangh Date: Mon, 18 Sep 2023 15:54:42 +0530 Subject: [PATCH 7/7] Fixed histogram panel not being reusable + minor ui changes + removed warnings --- .../couchbase/intellij/tools/Mctimings.java | 16 ++-- .../tools/dialog/MctimingsDialog.java | 73 +++++++++++-------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/Mctimings.java b/src/main/java/com/couchbase/intellij/tools/Mctimings.java index aa2d7a04..9caa0325 100644 --- a/src/main/java/com/couchbase/intellij/tools/Mctimings.java +++ b/src/main/java/com/couchbase/intellij/tools/Mctimings.java @@ -107,8 +107,10 @@ public List executeCommand() { // Add the selected optional parameters to the command if (!selectedOptionalParameters.isEmpty()) { - String parameters = String.join(" ", selectedOptionalParameters).toLowerCase(); - command.add(parameters); + for (String parameter : selectedOptionalParameters) { + String parameterLowerCase = parameter.toLowerCase(); + command.add(parameterLowerCase); + } } Log.debug("Command is" + command); @@ -162,7 +164,7 @@ public static Map>> parseHistogram(Proce public JPanel generateHistograms(Map>> histogramData) { JPanel outputPanel = new JPanel(); outputPanel.setLayout(new BoxLayout(outputPanel, BoxLayout.Y_AXIS)); - + // For each bucket in the histogram data for (Map.Entry>> bucketEntry : histogramData.entrySet()) { String bucket = bucketEntry.getKey(); @@ -210,12 +212,8 @@ protected JPanel generateBarChart(String bucket, String operation, String[] labe } JFreeChart barChart = ChartFactory.createBarChart( - "Operation Duration Histogram for " + bucket + "with operation " + operation, - "Operation Duration", - "Occurrences", - dataset, - PlotOrientation.VERTICAL, - true, true, false); + "Operation Duration Histogram for " + bucket + "with operation " + operation, "Operation Duration", + "Occurrences", dataset, PlotOrientation.VERTICAL, true, true, false); // Set dynamic range for Y-axis NumberAxis rangeAxis = (NumberAxis) barChart.getCategoryPlot().getRangeAxis(); diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java index 2f0ff4b3..916c7032 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/MctimingsDialog.java @@ -1,37 +1,54 @@ package com.couchbase.intellij.tools.dialog; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.ScrollPaneConstants; + +import com.intellij.openapi.ui.ComboBox; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import com.couchbase.intellij.database.ActiveCluster; import com.couchbase.intellij.tools.Mctimings; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ui.JBUI; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import utils.TemplateUtil; -import javax.swing.*; -import java.awt.*; -import java.util.List; -import java.util.*; +import utils.TemplateUtil; public class MctimingsDialog extends DialogWrapper { + private static final String SUMMARY_OF_ALL_OPERATIONS = "Summary of All Operations"; + private static final String HISTOGRAM = "Histogram"; + private static final String JSON = "Json"; + private static final String JSON_PRETTY_PRINTED = "Json pretty printed"; private final JComboCheckBox optionalParametersComboCheckBox = new JComboCheckBox(); private GridBagConstraints c; private JComboBox bucketComboBox; private JComboBox outputFormatComboBox; private JPanel outputPanel; private JPanel dialogPanel; - - private static final String SUMMARY_OF_ALL_OPERATIONS = "Summary of All Operations"; - private static final String HISTOGRAM = "Histogram"; - private static final String JSON = "Json"; - private static final String JSON_PRETTY_PRINTED = "Json pretty printed"; + private JBScrollPane histogramScrollPane; public MctimingsDialog() { super(true); init(); setTitle("Couchbase Mctimings Dialog"); - getWindow().setMinimumSize(new Dimension(800, 600)); + getWindow().setMinimumSize(new Dimension(600, 400)); setResizable(true); setOKButtonText("Display Timings"); } @@ -53,7 +70,7 @@ protected JComponent createCenterPanel() { c.gridx = 1; c.gridy = 0; - bucketComboBox = new JComboBox<>(); + bucketComboBox = new ComboBox<>(); Set bucketSet = ActiveCluster.getInstance().get().buckets().getAllBuckets().keySet(); String[] buckets = bucketSet.toArray(new String[0]); bucketComboBox.addItem("All buckets"); @@ -71,7 +88,7 @@ protected JComponent createCenterPanel() { c.gridx = 1; c.gridy = 1; - outputFormatComboBox = new JComboBox<>(); + outputFormatComboBox = new ComboBox<>(); outputFormatComboBox.addItem(SUMMARY_OF_ALL_OPERATIONS); outputFormatComboBox.addItem(HISTOGRAM); outputFormatComboBox.addItem(JSON); @@ -159,12 +176,11 @@ protected JComponent createSouthPanel() { @Override protected void doOKAction() { - getWindow().setMinimumSize(new Dimension(1600, 800)); - if (outputPanel != null) { - outputPanel.removeAll(); + if (outputPanel != null) dialogPanel.remove(outputPanel); - } + if (histogramScrollPane != null) + dialogPanel.remove(histogramScrollPane); String selectedBucket = (String) bucketComboBox.getSelectedItem(); String selectedOutputFormat = (String) outputFormatComboBox.getSelectedItem(); @@ -174,14 +190,11 @@ protected void doOKAction() { Mctimings mctimings = new Mctimings(selectedBucket, selectedOutputFormat, selectedOptionalParameters); outputPanel = mctimings.executeCommandAndReturnPanel(); - // Create a JScrollPane containing the output panel - JScrollPane scrollPane = new JScrollPane(outputPanel); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + histogramScrollPane = new JBScrollPane(outputPanel); + histogramScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + histogramScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - // Replace output panel with scroll pane in dialog panel - dialogPanel.remove(outputPanel); - dialogPanel.add(scrollPane, c); + dialogPanel.add(histogramScrollPane, c); } else { JTextArea outputTextArea = new JTextArea(); @@ -190,17 +203,15 @@ protected void doOKAction() { outputTextArea.setLineWrap(true); // Enable line wrapping outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries - JScrollPane scrollPane = new JScrollPane(outputTextArea); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + JBScrollPane outputTextAreaScrollPane = new JBScrollPane(outputTextArea); + outputTextAreaScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); outputPanel = new JPanel(new BorderLayout()); Mctimings mctimings = new Mctimings(selectedBucket, selectedOutputFormat, selectedOptionalParameters); String output = mctimings.executeCommandAndReturnString(); outputTextArea.setText(output); - outputPanel.add(scrollPane, BorderLayout.CENTER); - outputPanel.revalidate(); - outputPanel.repaint(); + outputPanel.add(outputTextAreaScrollPane, BorderLayout.CENTER); dialogPanel.add(outputPanel, c); }