From db98930f451c4db03d8bb28d2cfc8c01d461a0d8 Mon Sep 17 00:00:00 2001 From: teetangh Date: Wed, 13 Sep 2023 10:36:09 +0530 Subject: [PATCH 01/11] Added initial files for the dialog box --- .../tools/dialog/CbstatsCollectionDialog.java | 174 ++++++++++++++++++ .../intellij/tree/TreeRightClickListener.java | 12 +- 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java new file mode 100644 index 00000000..06d711bf --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -0,0 +1,174 @@ +package com.couchbase.intellij.tools.dialog; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.Optional; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.jetbrains.annotations.Nullable; + +import com.couchbase.client.java.manager.collection.CollectionSpec; +import com.couchbase.client.java.manager.collection.ScopeSpec; +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.workbench.Log; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.util.ui.JBUI; + +import utils.TemplateUtil; + +public class CbstatsCollectionDialog extends DialogWrapper { + + private static final String NETWORK_CONNECTIVITY_ERROR_MESSAGE = "Could not connect to the cluster. Please check your network connectivity, if the cluster is active or if the credentials are still valid."; + private static final String COUCHBASE_PLUGIN_ERROR_MESSAGE = "Couchbase Plugin Error"; + private static final String DEFAULT_TAG = "_default"; + private JPanel dialogPanel; + private GridBagConstraints c; + private JComboBox bucketComboBox; + private JComboBox scopeComboBox; + private JComboBox collectionComboBox; + + public CbstatsCollectionDialog() { + super(true); + init(); + setTitle("Custom Dialog"); + getWindow().setMinimumSize(new Dimension(800, 600)); + setResizable(true); + + + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + + dialogPanel = new JPanel(new GridBagLayout()); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.NORTH; + + bucketComboBox = new JComboBox<>(); + scopeComboBox = new JComboBox<>(); + collectionComboBox = new JComboBox<>(); + + bucketComboBox.addActionListener(e -> handleBucketComboBoxChange()); + scopeComboBox.addActionListener(e -> handleScopeComboBoxChange()); + + // Line 1: Bucket + addLabelAndComponent("Bucket:", "Select the bucket", 0, bucketComboBox); + + // Line 2: Scope + addLabelAndComponent("Scope:", "Select the scope", 1, scopeComboBox); + + // Line 3: Collection + addLabelAndComponent("Collection:", "Select the collection", 2, collectionComboBox); + + // Line 4: Collection Statistics + c.gridx = 0; + c.gridy = 3; + JPanel statsLabel = TemplateUtil.getLabelWithHelp("Collection Statistics:", "Collection statistics will be displayed here"); + dialogPanel.add(statsLabel, c); + + // Line 5: Output Text Preview Area + c.gridx = 0; + c.gridy = 4; + c.weightx = 1; + c.weighty = 1; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + + 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); + + dialogPanel.add(scrollPane, c); + + return dialogPanel; + } + + private void addLabelAndComponent(String labelText, String hint, int gridy, JComponent component) { + c.gridx = 0; + c.gridy = gridy; + c.insets = JBUI.insets(5); + + JPanel label = TemplateUtil.getLabelWithHelp(labelText, hint); + + dialogPanel.add(label, c); + + c.gridx = 1; + + dialogPanel.add(component, c); + } + + private void handleBucketComboBoxChange() { + try { + String selectedBucket = Optional.ofNullable(bucketComboBox.getSelectedItem()).map(Object::toString).orElse(null); + + Set scopeNamesSet = ActiveCluster.getInstance().get().bucket(selectedBucket).collections().getAllScopes().stream().map(ScopeSpec::name).collect(Collectors.toSet()); + scopeComboBox.removeAllItems(); + for (String s : scopeNamesSet) { + scopeComboBox.addItem(s); + } + + if (scopeComboBox.getItemCount() > 0) { + scopeComboBox.setSelectedIndex(0); + } else { + Messages.showErrorDialog("The selectd bucket is empty. Selecting default scope and collection", "Empty Bucket"); + scopeComboBox.setSelectedItem(DEFAULT_TAG); + collectionComboBox.setSelectedItem(DEFAULT_TAG); + + } + handleScopeComboBoxChange(); + } catch (Exception e) { + Messages.showErrorDialog(NETWORK_CONNECTIVITY_ERROR_MESSAGE, COUCHBASE_PLUGIN_ERROR_MESSAGE); + Log.error(e); + } + } + + private void handleScopeComboBoxChange() { + try { + String selectedBucket = Optional.ofNullable(bucketComboBox.getSelectedItem()).map(Object::toString).orElse(null); + String selectedScope = Optional.ofNullable(scopeComboBox.getSelectedItem()).map(Object::toString).orElse(null); + + if (selectedScope == null || selectedScope.isEmpty()) { + scopeComboBox.setSelectedItem(DEFAULT_TAG); + collectionComboBox.setSelectedItem(DEFAULT_TAG); + return; + } + + Consumer refreshCollectionCombo = scope -> { + String[] collectionNamesArray = ActiveCluster.getInstance().get().bucket(selectedBucket).collections().getAllScopes().stream().filter(s -> s.name().equals(scope)).flatMap(s -> s.collections().stream()).map(CollectionSpec::name).distinct().toArray(String[]::new); + collectionComboBox.removeAllItems(); + for (String s : collectionNamesArray) { + collectionComboBox.addItem(s); + } + }; + + refreshCollectionCombo.accept(selectedScope); + + if (collectionComboBox.getItemCount() > 0) { + collectionComboBox.setSelectedIndex(0); + } else { + Messages.showErrorDialog("The selectd scope is empty. Selecting default scope and collection", "Empty Bucket"); + scopeComboBox.setSelectedItem(DEFAULT_TAG); + collectionComboBox.setSelectedItem(DEFAULT_TAG); + } + } catch (Exception e) { + Messages.showErrorDialog(NETWORK_CONNECTIVITY_ERROR_MESSAGE, COUCHBASE_PLUGIN_ERROR_MESSAGE); + Log.error(e); + } + } +} diff --git a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java index 6dfb780f..a8257246 100644 --- a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java +++ b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java @@ -10,9 +10,9 @@ import com.couchbase.intellij.tools.CBImport; import com.couchbase.intellij.tools.CBTools; import com.couchbase.intellij.tools.PillowFightDialog; +import com.couchbase.intellij.tools.dialog.CbstatsCollectionDialog; 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.tree.docfilter.DocumentFilterDialog; import com.couchbase.intellij.tree.node.*; import com.couchbase.intellij.tree.overview.IndexOverviewDialog; @@ -596,6 +596,16 @@ public void actionPerformed(@NotNull AnActionEvent e) { actionGroup.add(simpleExport); } + actionGroup.addSeparator(); + AnAction viewStats = new AnAction("View Collection Statistics") { + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + CbstatsCollectionDialog cbstatsCollectionDialog = new CbstatsCollectionDialog(); + cbstatsCollectionDialog.show(); + } + }; + actionGroup.add(viewStats); + showPopup(e, tree, actionGroup); } } From e6779730c3c2078f700248708000e5104776ba75 Mon Sep 17 00:00:00 2001 From: teetangh Date: Wed, 13 Sep 2023 15:52:03 +0530 Subject: [PATCH 02/11] updated title --- .../intellij/tools/dialog/CbstatsCollectionDialog.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java index 06d711bf..41a20652 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -40,8 +40,8 @@ public class CbstatsCollectionDialog extends DialogWrapper { public CbstatsCollectionDialog() { super(true); init(); - setTitle("Custom Dialog"); - getWindow().setMinimumSize(new Dimension(800, 600)); + setTitle("Collection Statistics"); + getWindow().setMinimumSize(new Dimension(600, 400)); setResizable(true); @@ -72,6 +72,8 @@ protected JComponent createCenterPanel() { // Line 3: Collection addLabelAndComponent("Collection:", "Select the collection", 2, collectionComboBox); + handleBucketComboBoxChange(); + // Line 4: Collection Statistics c.gridx = 0; c.gridy = 3; From 04260783921b40927f5484fe93971652ecb9558e Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 14 Sep 2023 16:07:30 +0530 Subject: [PATCH 03/11] Simplified the collections statistics dialog box --- .../com/couchbase/intellij/tools/CBStats.java | 59 +++++++ .../tools/dialog/CbstatsCollectionDialog.java | 161 +++--------------- .../intellij/tree/TreeRightClickListener.java | 6 +- src/main/java/utils/ProcessUtils.java | 22 +++ 4 files changed, 112 insertions(+), 136 deletions(-) create mode 100644 src/main/java/com/couchbase/intellij/tools/CBStats.java diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java new file mode 100644 index 00000000..0e1057fb --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -0,0 +1,59 @@ +package com.couchbase.intellij.tools; + +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.workbench.Log; +import utils.ProcessUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +public class CBStats { + private String bucketName; + private String scopeName; + private String collectionName; + + public CBStats(String bucketName, String scopeName, String collectionName) { + this.bucketName = bucketName; + this.scopeName = scopeName; + this.collectionName = collectionName; + } + + public String executeCommand() throws IOException, InterruptedException { + StringBuilder output; + + // Your command + List command = new ArrayList<>(); + command.add(CBTools.getTool(CBTools.Type.CBSTATS).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()); + + command.add("-b"); + command.add(bucketName); + + command.add("collections"); + command.add(scopeName + "." + collectionName); + + // Run your command + ProcessBuilder processBuilder = new ProcessBuilder(command); + Process process = processBuilder.start(); + + output = new StringBuilder(ProcessUtils.returnOutput(process)); + + if (process.waitFor() == 0) { + Log.info("Command executed successfully"); + } else { + Log.error("Command execution failed"); + } + + return output.toString(); + } +} diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java index 41a20652..778307eb 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -1,88 +1,42 @@ package com.couchbase.intellij.tools.dialog; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.util.Optional; -import java.util.Set; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -import org.jetbrains.annotations.Nullable; - -import com.couchbase.client.java.manager.collection.CollectionSpec; -import com.couchbase.client.java.manager.collection.ScopeSpec; -import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.tools.CBStats; import com.couchbase.intellij.workbench.Log; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.Messages; -import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.Nullable; -import utils.TemplateUtil; +import javax.swing.*; +import java.awt.*; public class CbstatsCollectionDialog extends DialogWrapper { - private static final String NETWORK_CONNECTIVITY_ERROR_MESSAGE = "Could not connect to the cluster. Please check your network connectivity, if the cluster is active or if the credentials are still valid."; - private static final String COUCHBASE_PLUGIN_ERROR_MESSAGE = "Couchbase Plugin Error"; - private static final String DEFAULT_TAG = "_default"; - private JPanel dialogPanel; - private GridBagConstraints c; - private JComboBox bucketComboBox; - private JComboBox scopeComboBox; - private JComboBox collectionComboBox; - public CbstatsCollectionDialog() { + private final String bucketName; + private String scopeName; + private String collectionName; + + public CbstatsCollectionDialog(String bucket, String scope, String collection) { super(true); + this.bucketName = bucket; + this.scopeName = scope; + this.collectionName = collection; init(); - setTitle("Collection Statistics"); + setTitle("Cbstats Collection Dialog"); getWindow().setMinimumSize(new Dimension(600, 400)); setResizable(true); - - } @Nullable @Override protected JComponent createCenterPanel() { - dialogPanel = new JPanel(new GridBagLayout()); - c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; + JPanel dialogPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.NORTH; - bucketComboBox = new JComboBox<>(); - scopeComboBox = new JComboBox<>(); - collectionComboBox = new JComboBox<>(); - - bucketComboBox.addActionListener(e -> handleBucketComboBoxChange()); - scopeComboBox.addActionListener(e -> handleScopeComboBoxChange()); - - // Line 1: Bucket - addLabelAndComponent("Bucket:", "Select the bucket", 0, bucketComboBox); - - // Line 2: Scope - addLabelAndComponent("Scope:", "Select the scope", 1, scopeComboBox); - - // Line 3: Collection - addLabelAndComponent("Collection:", "Select the collection", 2, collectionComboBox); - - handleBucketComboBoxChange(); - - // Line 4: Collection Statistics - c.gridx = 0; - c.gridy = 3; - JPanel statsLabel = TemplateUtil.getLabelWithHelp("Collection Statistics:", "Collection statistics will be displayed here"); - dialogPanel.add(statsLabel, c); - - // Line 5: Output Text Preview Area + // Output Text Preview Area c.gridx = 0; - c.gridy = 4; + c.gridy = 0; c.weightx = 1; c.weighty = 1; c.gridwidth = 2; @@ -94,6 +48,15 @@ protected JComponent createCenterPanel() { outputTextArea.setLineWrap(true); // Enable line wrapping outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries + CBStats cbStats = new CBStats(bucketName,scopeName,collectionName); + String output = ""; + try { + output = cbStats.executeCommand(); + } catch (Exception e) { + Log.error(e); + } + outputTextArea.setText(output); + JScrollPane scrollPane = new JScrollPane(outputTextArea); dialogPanel.add(scrollPane, c); @@ -101,76 +64,4 @@ protected JComponent createCenterPanel() { return dialogPanel; } - private void addLabelAndComponent(String labelText, String hint, int gridy, JComponent component) { - c.gridx = 0; - c.gridy = gridy; - c.insets = JBUI.insets(5); - - JPanel label = TemplateUtil.getLabelWithHelp(labelText, hint); - - dialogPanel.add(label, c); - - c.gridx = 1; - - dialogPanel.add(component, c); - } - - private void handleBucketComboBoxChange() { - try { - String selectedBucket = Optional.ofNullable(bucketComboBox.getSelectedItem()).map(Object::toString).orElse(null); - - Set scopeNamesSet = ActiveCluster.getInstance().get().bucket(selectedBucket).collections().getAllScopes().stream().map(ScopeSpec::name).collect(Collectors.toSet()); - scopeComboBox.removeAllItems(); - for (String s : scopeNamesSet) { - scopeComboBox.addItem(s); - } - - if (scopeComboBox.getItemCount() > 0) { - scopeComboBox.setSelectedIndex(0); - } else { - Messages.showErrorDialog("The selectd bucket is empty. Selecting default scope and collection", "Empty Bucket"); - scopeComboBox.setSelectedItem(DEFAULT_TAG); - collectionComboBox.setSelectedItem(DEFAULT_TAG); - - } - handleScopeComboBoxChange(); - } catch (Exception e) { - Messages.showErrorDialog(NETWORK_CONNECTIVITY_ERROR_MESSAGE, COUCHBASE_PLUGIN_ERROR_MESSAGE); - Log.error(e); - } - } - - private void handleScopeComboBoxChange() { - try { - String selectedBucket = Optional.ofNullable(bucketComboBox.getSelectedItem()).map(Object::toString).orElse(null); - String selectedScope = Optional.ofNullable(scopeComboBox.getSelectedItem()).map(Object::toString).orElse(null); - - if (selectedScope == null || selectedScope.isEmpty()) { - scopeComboBox.setSelectedItem(DEFAULT_TAG); - collectionComboBox.setSelectedItem(DEFAULT_TAG); - return; - } - - Consumer refreshCollectionCombo = scope -> { - String[] collectionNamesArray = ActiveCluster.getInstance().get().bucket(selectedBucket).collections().getAllScopes().stream().filter(s -> s.name().equals(scope)).flatMap(s -> s.collections().stream()).map(CollectionSpec::name).distinct().toArray(String[]::new); - collectionComboBox.removeAllItems(); - for (String s : collectionNamesArray) { - collectionComboBox.addItem(s); - } - }; - - refreshCollectionCombo.accept(selectedScope); - - if (collectionComboBox.getItemCount() > 0) { - collectionComboBox.setSelectedIndex(0); - } else { - Messages.showErrorDialog("The selectd scope is empty. Selecting default scope and collection", "Empty Bucket"); - scopeComboBox.setSelectedItem(DEFAULT_TAG); - collectionComboBox.setSelectedItem(DEFAULT_TAG); - } - } catch (Exception e) { - Messages.showErrorDialog(NETWORK_CONNECTIVITY_ERROR_MESSAGE, COUCHBASE_PLUGIN_ERROR_MESSAGE); - Log.error(e); - } - } } diff --git a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java index a8257246..deb7631d 100644 --- a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java +++ b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java @@ -600,7 +600,11 @@ public void actionPerformed(@NotNull AnActionEvent e) { AnAction viewStats = new AnAction("View Collection Statistics") { @Override public void actionPerformed(@NotNull AnActionEvent e) { - CbstatsCollectionDialog cbstatsCollectionDialog = new CbstatsCollectionDialog(); + CbstatsCollectionDialog cbstatsCollectionDialog = new CbstatsCollectionDialog( + col.getBucket(), + col.getScope(), + col.getText() + ); cbstatsCollectionDialog.show(); } }; diff --git a/src/main/java/utils/ProcessUtils.java b/src/main/java/utils/ProcessUtils.java index a1e81ea5..45df901d 100644 --- a/src/main/java/utils/ProcessUtils.java +++ b/src/main/java/utils/ProcessUtils.java @@ -24,4 +24,26 @@ public static void printOutput(Process process, String message) throws IOExcepti } } } + + 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) { + output.append(line).append("\n"); + } + } + + // Process standard error + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + } + + return output.toString(); + } } From 36b52e2e22dab024abb525c3dd20bcd10e9fb190 Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 14 Sep 2023 16:42:14 +0530 Subject: [PATCH 04/11] updated cbtools dependencies downloader --- .../listener/DependenciesDownloader.java | 23 +++++++++++-------- .../com/couchbase/intellij/tools/CBStats.java | 7 ++---- .../com/couchbase/intellij/tools/CBTools.java | 3 ++- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java b/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java index d821397a..e472653b 100644 --- a/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java +++ b/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java @@ -67,6 +67,7 @@ private Map getToolsMap(String toolKey, String os) { } else if (ALL_TOOLS.equals(toolKey)) { map.put(CBTools.Type.CBC_PILLOW_FIGHT, path + "cbc-pillowfight" + suffix); map.put(CBTools.Type.MCTIMINGS, path + "mctimings" + suffix); + map.put(CBTools.Type.CBSTATS, path + "cbstats" + suffix); } else { throw new IllegalStateException("Not implemented yet"); @@ -155,16 +156,20 @@ public void downloadDependencies() throws Exception { ToolSpec cbTools = downloads.get(ALL_TOOLS); String toolsDir = toolsPath + File.separator + cbTools.getInstallationPath(); - if (CBTools.getTool(CBTools.Type.CBC_PILLOW_FIGHT).getStatus() == ToolStatus.NOT_AVAILABLE - && !isInstalled(toolsPath, downloads.get(ALL_TOOLS), CBTools.Type.CBC_PILLOW_FIGHT)) { - Log.info("Downloading CB tools. The feature will be automatically enabled when the download is complete."); - CBTools.getTool(CBTools.Type.CBC_PILLOW_FIGHT).setStatus(ToolStatus.DOWNLOADING); - CBTools.getTool(CBTools.Type.MCTIMINGS).setStatus(ToolStatus.DOWNLOADING); - downloadAndUnzip(toolsDir, cbTools); - } else { - Log.debug("CB Tools are already installed"); - setToolActive(ToolStatus.AVAILABLE, toolsDir, cbTools); + CBTools.Type[] toolTypes = {CBTools.Type.CBC_PILLOW_FIGHT, CBTools.Type.MCTIMINGS, CBTools.Type.CBSTATS}; + + for (CBTools.Type toolType : toolTypes) { + if (CBTools.getTool(toolType).getStatus() == ToolStatus.NOT_AVAILABLE + && !isInstalled(toolsPath, downloads.get(ALL_TOOLS), toolType)) { + + Log.info("Downloading " + toolType + " tool. The feature will be automatically enabled when the download is complete."); + CBTools.getTool(toolType).setStatus(ToolStatus.DOWNLOADING); + downloadAndUnzip(toolsDir, cbTools); + } else { + Log.debug(toolType + " tool is already installed"); + setToolActive(ToolStatus.AVAILABLE, toolsDir, cbTools); + } } } diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index 0e1057fb..1f4596ac 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -27,13 +27,10 @@ public String executeCommand() throws IOException, InterruptedException { // Your command List command = new ArrayList<>(); command.add(CBTools.getTool(CBTools.Type.CBSTATS).getPath()); - command.add("-h"); - command.add(ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")); - command.add("-p"); - command.add(ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210"); + command.add((ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")) + ":" + (ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210")); command.add("-u"); command.add(ActiveCluster.getInstance().getUsername()); - command.add("-P"); + command.add("-p"); command.add(ActiveCluster.getInstance().getPassword()); command.add("-b"); diff --git a/src/main/java/com/couchbase/intellij/tools/CBTools.java b/src/main/java/com/couchbase/intellij/tools/CBTools.java index bd77b523..399e47f2 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBTools.java +++ b/src/main/java/com/couchbase/intellij/tools/CBTools.java @@ -20,6 +20,7 @@ public enum Type { CB_IMPORT, CB_EXPORT, CBC_PILLOW_FIGHT, - MCTIMINGS + CBSTATS, + MCTIMINGS, } } From face15760fbb56762f3db3dc25a7b2a6c62ce2fa Mon Sep 17 00:00:00 2001 From: teetangh Date: Fri, 15 Sep 2023 13:12:52 +0530 Subject: [PATCH 05/11] updated dependencies downloader with more efficient downloading --- .../intellij/listener/DependenciesDownloader.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java b/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java index e472653b..05026147 100644 --- a/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java +++ b/src/main/java/com/couchbase/intellij/listener/DependenciesDownloader.java @@ -159,19 +159,23 @@ public void downloadDependencies() throws Exception { CBTools.Type[] toolTypes = {CBTools.Type.CBC_PILLOW_FIGHT, CBTools.Type.MCTIMINGS, CBTools.Type.CBSTATS}; + boolean shouldDownload = false; for (CBTools.Type toolType : toolTypes) { if (CBTools.getTool(toolType).getStatus() == ToolStatus.NOT_AVAILABLE && !isInstalled(toolsPath, downloads.get(ALL_TOOLS), toolType)) { - - Log.info("Downloading " + toolType + " tool. The feature will be automatically enabled when the download is complete."); + shouldDownload = true; CBTools.getTool(toolType).setStatus(ToolStatus.DOWNLOADING); - downloadAndUnzip(toolsDir, cbTools); } else { Log.debug(toolType + " tool is already installed"); setToolActive(ToolStatus.AVAILABLE, toolsDir, cbTools); } } + if (shouldDownload) { + Log.info("Downloading tools. The features will be automatically enabled when the download is complete."); + downloadAndUnzip(toolsDir, cbTools); + } + } From f4bcb99585793c1ef20c2a79181f643078119379 Mon Sep 17 00:00:00 2001 From: teetangh Date: Mon, 18 Sep 2023 16:57:41 +0530 Subject: [PATCH 06/11] resolved the cbstats path for now --- .../com/couchbase/intellij/tools/CBStats.java | 14 +++++++------- .../tools/dialog/CbstatsCollectionDialog.java | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index 1f4596ac..c9b09ac3 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -1,15 +1,14 @@ package com.couchbase.intellij.tools; -import com.couchbase.intellij.database.ActiveCluster; -import com.couchbase.intellij.workbench.Log; -import utils.ProcessUtils; - -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; +import com.couchbase.intellij.database.ActiveCluster; +import com.couchbase.intellij.workbench.Log; + +import utils.ProcessUtils; + public class CBStats { private String bucketName; private String scopeName; @@ -26,7 +25,8 @@ public String executeCommand() throws IOException, InterruptedException { // Your command List command = new ArrayList<>(); - command.add(CBTools.getTool(CBTools.Type.CBSTATS).getPath()); + // command.add(CBTools.getTool(CBTools.Type.CBSTATS).getPath()); + command.add("/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/bin/cbstats"); command.add((ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")) + ":" + (ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210")); command.add("-u"); command.add(ActiveCluster.getInstance().getUsername()); diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java index 778307eb..19b685a6 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -1,19 +1,26 @@ package com.couchbase.intellij.tools.dialog; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.jetbrains.annotations.Nullable; + import com.couchbase.intellij.tools.CBStats; import com.couchbase.intellij.workbench.Log; import com.intellij.openapi.ui.DialogWrapper; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.*; public class CbstatsCollectionDialog extends DialogWrapper { private final String bucketName; - private String scopeName; - private String collectionName; + private final String scopeName; + private final String collectionName; public CbstatsCollectionDialog(String bucket, String scope, String collection) { super(true); From 4e0d7a9e2e7fe12f95eeca95460bcbed0c339cd0 Mon Sep 17 00:00:00 2001 From: teetangh Date: Mon, 18 Sep 2023 17:35:22 +0530 Subject: [PATCH 07/11] renamed the dialog --- .../intellij/tools/dialog/CbstatsCollectionDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java index 19b685a6..61f28923 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -28,7 +28,7 @@ public CbstatsCollectionDialog(String bucket, String scope, String collection) { this.scopeName = scope; this.collectionName = collection; init(); - setTitle("Cbstats Collection Dialog"); + setTitle("Stats for collection"); getWindow().setMinimumSize(new Dimension(600, 400)); setResizable(true); } From 32a362fac35fa01f9bc714536844cff813dad8e3 Mon Sep 17 00:00:00 2001 From: teetangh Date: Wed, 20 Sep 2023 05:19:46 +0530 Subject: [PATCH 08/11] updated the ui and api for the cbstats dialog --- .../com/couchbase/intellij/tools/CBStats.java | 29 ++++-- .../tools/dialog/CbstatsCollectionDialog.java | 93 ++++++++++++------- 2 files changed, 85 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index c9b09ac3..0598ab79 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -7,12 +7,13 @@ import com.couchbase.intellij.database.ActiveCluster; import com.couchbase.intellij.workbench.Log; +import utils.OSUtil; import utils.ProcessUtils; public class CBStats { - private String bucketName; - private String scopeName; - private String collectionName; + private final String bucketName; + private final String scopeName; + private final String collectionName; public CBStats(String bucketName, String scopeName, String collectionName) { this.bucketName = bucketName; @@ -23,10 +24,27 @@ public CBStats(String bucketName, String scopeName, String collectionName) { public String executeCommand() throws IOException, InterruptedException { StringBuilder output; - // Your command List command = new ArrayList<>(); // command.add(CBTools.getTool(CBTools.Type.CBSTATS).getPath()); - command.add("/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/bin/cbstats"); + String osArch = OSUtil.getOSArch(); + + // Determine the command path based on the operating system and architecture + switch (osArch) { + case OSUtil.MACOS_ARM: + case OSUtil.MACOS_64: + command.add("/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/bin/cbstats"); + break; + case OSUtil.WINDOWS_ARM: + case OSUtil.WINDOWS_64: + command.add("C:\\Program Files\\Couchbase\\Server\\bin\\cbstats"); + break; + case OSUtil.LINUX_ARM: + case OSUtil.LINUX_64: + command.add("/opt/couchbase/bin/cbstats"); + break; + default: + throw new UnsupportedOperationException("Unsupported operating system: " + osArch); + } command.add((ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")) + ":" + (ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210")); command.add("-u"); command.add(ActiveCluster.getInstance().getUsername()); @@ -39,7 +57,6 @@ public String executeCommand() throws IOException, InterruptedException { command.add("collections"); command.add(scopeName + "." + collectionName); - // Run your command ProcessBuilder processBuilder = new ProcessBuilder(command); Process process = processBuilder.start(); diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java index 61f28923..db12ffbd 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java @@ -1,13 +1,10 @@ package com.couchbase.intellij.tools.dialog; +import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; import org.jetbrains.annotations.Nullable; @@ -15,60 +12,94 @@ import com.couchbase.intellij.workbench.Log; import com.intellij.openapi.ui.DialogWrapper; -public class CbstatsCollectionDialog extends DialogWrapper { +import utils.TemplateUtil; +public class CbstatsCollectionDialog extends DialogWrapper { private final String bucketName; private final String scopeName; private final String collectionName; + public CbstatsCollectionDialog(String bucket, String scope, String collection) { super(true); this.bucketName = bucket; this.scopeName = scope; this.collectionName = collection; init(); - setTitle("Stats for collection"); - getWindow().setMinimumSize(new Dimension(600, 400)); + setTitle("Stats for Collection"); + getWindow().setMinimumSize(new Dimension(350, 400)); setResizable(true); } @Nullable @Override protected JComponent createCenterPanel() { + JPanel dialogPanel = new JPanel(new BorderLayout()); - JPanel dialogPanel = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.NORTH; - - // Output Text Preview Area - c.gridx = 0; - c.gridy = 0; - c.weightx = 1; - c.weighty = 1; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - - JTextArea outputTextArea = new JTextArea(); - - outputTextArea.setEditable(false); - outputTextArea.setLineWrap(true); // Enable line wrapping - outputTextArea.setWrapStyleWord(true); // Wrap lines at word boundaries - - CBStats cbStats = new CBStats(bucketName,scopeName,collectionName); + CBStats cbStats = new CBStats(bucketName, scopeName, collectionName); String output = ""; try { output = cbStats.executeCommand(); - } catch (Exception e) { - Log.error(e); + } catch (Exception ex) { + Log.error(ex); } - outputTextArea.setText(output); - JScrollPane scrollPane = new JScrollPane(outputTextArea); + String[] lines = output.split("\n"); + String[] keys = new String[lines.length]; + String[] values = new String[lines.length]; - dialogPanel.add(scrollPane, c); + for (int i = 0; i < lines.length; i++) { + int keyStartIndex = lines[i].indexOf(':', lines[i].indexOf(':') + 1) + 1; + int valueStartIndex = lines[i].lastIndexOf(':') + 1; + keys[i] = getFriendlyKeyName(lines[i].substring(keyStartIndex, valueStartIndex - 1).trim()); + values[i] = getFriendlyValue(lines[i].substring(valueStartIndex).trim(), keys[i]); + } + + JPanel keyValuePanel = TemplateUtil.createKeyValuePanel(keys, values, 1); + + dialogPanel.add(keyValuePanel, BorderLayout.CENTER); return dialogPanel; } + private String getFriendlyKeyName(String key) { + switch (key) { + case "collections_mem_used": + return "Memory Used By Collection"; + case "data_size": + return "Collection Data Size"; + case "items": + return "Number Of Items"; + case "name": + return "Collection Name"; + case "ops_delete": + return "Number Of Delete Operations"; + case "ops_get": + return "Number Of Get Operations"; + case "ops_store": + return "Number Of Store Operations"; + case "scope_name": + return "Scope Name"; + default: + return key; + } + } + + private String getFriendlyValue(String value, String key) { + switch (key) { + case "Memory Used By Collection": + case "Collection Data Size": + long bytes = Long.parseLong(value); + double sizeInMB = bytes / (1024.0 * 1024.0); + if (sizeInMB >= 1024) { + double sizeInGB = sizeInMB / 1024.0; + return String.format("%.2f GB", sizeInGB); + } else { + return String.format("%.2f MB", sizeInMB); + } + default: + return value; + } + } } From c8822d515d10fd0375666907f3443aac49696aa9 Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 21 Sep 2023 16:26:45 +0530 Subject: [PATCH 09/11] refactored bunch of code + added help icon --- .../com/couchbase/intellij/tools/CBStats.java | 7 +- .../tools/dialog/CbstatsCollectionDialog.java | 105 ------------- .../intellij/tools/dialog/CbstatsDialog.java | 140 ++++++++++++++++++ .../intellij/tree/TreeRightClickListener.java | 9 +- src/main/java/utils/TemplateUtil.java | 62 +++++++- 5 files changed, 211 insertions(+), 112 deletions(-) delete mode 100644 src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java create mode 100644 src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index 0598ab79..2cc81bfd 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -15,13 +15,16 @@ public class CBStats { private final String scopeName; private final String collectionName; - public CBStats(String bucketName, String scopeName, String collectionName) { + private final String type; + + public CBStats(String bucketName, String scopeName, String collectionName, String type) { this.bucketName = bucketName; this.scopeName = scopeName; this.collectionName = collectionName; + this.type = type; } - public String executeCommand() throws IOException, InterruptedException { + public String getCollectionStatistics() throws IOException, InterruptedException { StringBuilder output; List command = new ArrayList<>(); diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java deleted file mode 100644 index db12ffbd..00000000 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsCollectionDialog.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.couchbase.intellij.tools.dialog; - -import java.awt.BorderLayout; -import java.awt.Dimension; - -import javax.swing.JComponent; -import javax.swing.JPanel; - -import org.jetbrains.annotations.Nullable; - -import com.couchbase.intellij.tools.CBStats; -import com.couchbase.intellij.workbench.Log; -import com.intellij.openapi.ui.DialogWrapper; - -import utils.TemplateUtil; - -public class CbstatsCollectionDialog extends DialogWrapper { - - private final String bucketName; - private final String scopeName; - private final String collectionName; - - - public CbstatsCollectionDialog(String bucket, String scope, String collection) { - super(true); - this.bucketName = bucket; - this.scopeName = scope; - this.collectionName = collection; - init(); - setTitle("Stats for Collection"); - getWindow().setMinimumSize(new Dimension(350, 400)); - setResizable(true); - } - - @Nullable - @Override - protected JComponent createCenterPanel() { - JPanel dialogPanel = new JPanel(new BorderLayout()); - - CBStats cbStats = new CBStats(bucketName, scopeName, collectionName); - String output = ""; - try { - output = cbStats.executeCommand(); - } catch (Exception ex) { - Log.error(ex); - } - - String[] lines = output.split("\n"); - String[] keys = new String[lines.length]; - String[] values = new String[lines.length]; - - for (int i = 0; i < lines.length; i++) { - int keyStartIndex = lines[i].indexOf(':', lines[i].indexOf(':') + 1) + 1; - int valueStartIndex = lines[i].lastIndexOf(':') + 1; - keys[i] = getFriendlyKeyName(lines[i].substring(keyStartIndex, valueStartIndex - 1).trim()); - values[i] = getFriendlyValue(lines[i].substring(valueStartIndex).trim(), keys[i]); - } - - JPanel keyValuePanel = TemplateUtil.createKeyValuePanel(keys, values, 1); - - dialogPanel.add(keyValuePanel, BorderLayout.CENTER); - - return dialogPanel; - } - - private String getFriendlyKeyName(String key) { - switch (key) { - case "collections_mem_used": - return "Memory Used By Collection"; - case "data_size": - return "Collection Data Size"; - case "items": - return "Number Of Items"; - case "name": - return "Collection Name"; - case "ops_delete": - return "Number Of Delete Operations"; - case "ops_get": - return "Number Of Get Operations"; - case "ops_store": - return "Number Of Store Operations"; - case "scope_name": - return "Scope Name"; - default: - return key; - } - } - - private String getFriendlyValue(String value, String key) { - switch (key) { - case "Memory Used By Collection": - case "Collection Data Size": - long bytes = Long.parseLong(value); - double sizeInMB = bytes / (1024.0 * 1024.0); - if (sizeInMB >= 1024) { - double sizeInGB = sizeInMB / 1024.0; - return String.format("%.2f GB", sizeInGB); - } else { - return String.format("%.2f MB", sizeInMB); - } - default: - return value; - } - } -} diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java new file mode 100644 index 00000000..6c273dea --- /dev/null +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java @@ -0,0 +1,140 @@ +package com.couchbase.intellij.tools.dialog; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.JComponent; +import javax.swing.JPanel; + +import org.jetbrains.annotations.Nullable; + +import com.couchbase.intellij.tools.CBStats; +import com.couchbase.intellij.workbench.Log; +import com.intellij.openapi.ui.DialogWrapper; + +import utils.TemplateUtil; + +public class CbstatsDialog extends DialogWrapper { + + private final String bucketName; + private final String scopeName; + private final String collectionName; + private final String type; + + private static final String MEMORY_USED_BY_COLLECTION = "Memory Used By Collection"; + private static final String COLLECTION_DATA_SIZE = "Collection Data Size"; + private static final String NUMBER_OF_ITEMS = "Number Of Items"; + private static final String COLLECTION_NAME = "Collection Name"; + private static final String NUMBER_OF_DELETE_OPERATIONS = "Number Of Delete Operations"; + private static final String NUMBER_OF_GET_OPERATIONS = "Number Of Get Operations"; + private static final String NUMBER_OF_STORE_OPERATIONS = "Number Of Store Operations"; + private static final String SCOPE_NAME = "Scope Name"; + + public CbstatsDialog(String bucket, String scope, String collection,String type) { + super(true); + this.bucketName = bucket; + this.scopeName = scope; + this.collectionName = collection; + this.type = type; + init(); + setTitle("Stats for " + type); + getWindow().setMinimumSize(new Dimension(350, 350)); + setResizable(true); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + JPanel dialogPanel = new JPanel(new BorderLayout()); + + CBStats cbStats = new CBStats(bucketName, scopeName, collectionName,type); + String output = ""; + try { + output = cbStats.getCollectionStatistics(); + } catch (Exception ex) { + Log.error(ex); + } + + String[] lines = output.split("\n"); + String[] keys = new String[lines.length]; + String[] values = new String[lines.length]; + String[] helpTexts = new String[lines.length]; // array for help texts + + for (int i = 0; i < lines.length; i++) { + int keyStartIndex = lines[i].indexOf(':', lines[i].indexOf(':') + 1) + 1; + int valueStartIndex = lines[i].lastIndexOf(':') + 1; + keys[i] = getCollectionFriendlyKeyName(lines[i].substring(keyStartIndex, valueStartIndex - 1).trim()); + values[i] = getCollectionFriendlyValue(lines[i].substring(valueStartIndex).trim(), keys[i]); + helpTexts[i] = getHelpText(keys[i]); // get help text for each key + } + + JPanel keyValuePanel = TemplateUtil.createKeyValuePanelWithHelp(keys, values, helpTexts, 1); + + dialogPanel.add(keyValuePanel, BorderLayout.CENTER); + + return dialogPanel; + } + + private String getHelpText(String key) { + switch (key) { + case MEMORY_USED_BY_COLLECTION: + return "This is the memory used by the collection. It is measured in bytes."; + case COLLECTION_DATA_SIZE: + return "This is the size of the data in the collection. It is also measured in bytes."; + case NUMBER_OF_ITEMS: + return "This represents the number of items in the collection. It doesn't have a unit as it's a count."; + case COLLECTION_NAME: + return "This is the name of the collection. It's a string and doesn't have a unit."; + case NUMBER_OF_DELETE_OPERATIONS: + return "This is the number of delete operations that have been performed on the collection. It doesn't have a unit as it's a count."; + case NUMBER_OF_GET_OPERATIONS: + return "This is the number of get operations that have been performed on the collection. It doesn't have a unit as it's a count."; + case NUMBER_OF_STORE_OPERATIONS: + return "This is the number of store operations that have been performed on the collection. It doesn't have a unit as it's a count."; + case SCOPE_NAME: + return "This is the name of the scope that contains the collection. It's a string and doesn't have a unit."; + default: + return ""; + } + } + + private String getCollectionFriendlyKeyName(String key) { + switch (key) { + case "collections_mem_used": + return MEMORY_USED_BY_COLLECTION; + case "data_size": + return COLLECTION_DATA_SIZE; + case "items": + return NUMBER_OF_ITEMS; + case "name": + return COLLECTION_NAME; + case "ops_delete": + return NUMBER_OF_DELETE_OPERATIONS; + case "ops_get": + return NUMBER_OF_GET_OPERATIONS; + case "ops_store": + return NUMBER_OF_STORE_OPERATIONS; + case "scope_name": + return SCOPE_NAME; + default: + return key; + } + } + + private String getCollectionFriendlyValue(String value, String key) { + switch (key) { + case MEMORY_USED_BY_COLLECTION: + case COLLECTION_DATA_SIZE: + long bytes = Long.parseLong(value); + double sizeInMB = bytes / (1024.0 * 1024.0); + if (sizeInMB >= 1024) { + double sizeInGB = sizeInMB / 1024.0; + return String.format("%.2f GB", sizeInGB); + } else { + return String.format("%.2f MB", sizeInMB); + } + default: + return value; + } + } +} diff --git a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java index deb7631d..b408a3bb 100644 --- a/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java +++ b/src/main/java/com/couchbase/intellij/tree/TreeRightClickListener.java @@ -10,7 +10,7 @@ import com.couchbase.intellij.tools.CBImport; import com.couchbase.intellij.tools.CBTools; import com.couchbase.intellij.tools.PillowFightDialog; -import com.couchbase.intellij.tools.dialog.CbstatsCollectionDialog; +import com.couchbase.intellij.tools.dialog.CbstatsDialog; import com.couchbase.intellij.tools.dialog.DDLExportDialog; import com.couchbase.intellij.tools.dialog.ExportDialog; import com.couchbase.intellij.tree.docfilter.DocumentFilterDialog; @@ -600,12 +600,13 @@ public void actionPerformed(@NotNull AnActionEvent e) { AnAction viewStats = new AnAction("View Collection Statistics") { @Override public void actionPerformed(@NotNull AnActionEvent e) { - CbstatsCollectionDialog cbstatsCollectionDialog = new CbstatsCollectionDialog( + CbstatsDialog cbstatsDialog = new CbstatsDialog( col.getBucket(), col.getScope(), - col.getText() + col.getText(), + "collection" ); - cbstatsCollectionDialog.show(); + cbstatsDialog.show(); } }; actionGroup.add(viewStats); diff --git a/src/main/java/utils/TemplateUtil.java b/src/main/java/utils/TemplateUtil.java index 7c154408..e8fe464e 100644 --- a/src/main/java/utils/TemplateUtil.java +++ b/src/main/java/utils/TemplateUtil.java @@ -80,6 +80,67 @@ public static JPanel createKeyValuePanel(String[] keys, String[] values, int col return finalPanel; } + public static JPanel createKeyValuePanelWithHelp(String[] keys, String[] values, String[] helpTexts, int cols) { + JPanel finalPanel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.BOTH; + gbc.gridy = 0; + + int firstColumnRows = (int) Math.ceil((double) keys.length / cols); + int remainingColumnRows = keys.length % cols == 0 ? keys.length / cols : (keys.length / cols) + 1; + + boolean isFirstColumnOdd = firstColumnRows % 2 != 0; + + for (int i = 0; i < cols; i++) { + JPanel columnPanel = new JPanel(new GridBagLayout()); + GridBagConstraints columnGbc = new GridBagConstraints(); + columnGbc.fill = GridBagConstraints.HORIZONTAL; + columnGbc.gridy = GridBagConstraints.RELATIVE; + columnGbc.anchor = GridBagConstraints.NORTHWEST; + columnGbc.insets = JBUI.insets(5, 5, 5, 15); + columnGbc.weightx = 0; + + int columnRows = (i == 0 && cols % 2 != 0) ? firstColumnRows : remainingColumnRows; + + for (int j = 0; j < columnRows; j++) { + int index = i * firstColumnRows + j - (i > 0 ? firstColumnRows - remainingColumnRows : 0); + + if (index < keys.length) { + JPanel keyPanelWithHelpIcon = getLabelWithHelp(keys[index], helpTexts[index]); + columnPanel.add(keyPanelWithHelpIcon, columnGbc); + + columnGbc.gridx = 1; + columnGbc.weightx = 1; + columnGbc.fill = GridBagConstraints.HORIZONTAL; + + columnPanel.add(new JLabel(values[index]), columnGbc); + + columnGbc.gridx = 0; + columnGbc.weightx = 0; + columnGbc.fill = GridBagConstraints.HORIZONTAL; + } else if (isFirstColumnOdd && i > 0) { + columnPanel.add(new JLabel(" "), columnGbc); + + columnGbc.gridx = 1; + columnGbc.weightx = 1; + columnGbc.fill = GridBagConstraints.HORIZONTAL; + + columnPanel.add(new JLabel(""), columnGbc); + + columnGbc.gridx = 0; + columnGbc.weightx = 0; + columnGbc.fill = GridBagConstraints.HORIZONTAL; + } + } + + gbc.weightx = 1.0 / cols; + finalPanel.add(columnPanel, gbc); + } + + finalPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, finalPanel.getPreferredSize().height)); + return finalPanel; + } + public static TitledSeparator getSeparator(String title) { TitledSeparator titledSeparator = new TitledSeparator(); titledSeparator.setText(title); @@ -146,7 +207,6 @@ public static String fmtByte(long bytes) { } } - public static String fmtDouble(Double value) { if (value == null) { From 8ca21a2d73599f16897c03e4ed4e6e6b29ae6fd0 Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 21 Sep 2023 16:46:26 +0530 Subject: [PATCH 10/11] minor edits in name --- .../java/com/couchbase/intellij/tools/CBStats.java | 14 ++++++++++---- .../intellij/tools/dialog/CbstatsDialog.java | 11 +++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index 2cc81bfd..513e5186 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -24,7 +24,7 @@ public CBStats(String bucketName, String scopeName, String collectionName, Strin this.type = type; } - public String getCollectionStatistics() throws IOException, InterruptedException { + public String executeCommand() throws IOException, InterruptedException { StringBuilder output; List command = new ArrayList<>(); @@ -48,7 +48,8 @@ public String getCollectionStatistics() throws IOException, InterruptedException default: throw new UnsupportedOperationException("Unsupported operating system: " + osArch); } - command.add((ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")) + ":" + (ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210")); + command.add((ActiveCluster.getInstance().getClusterURL().replaceFirst("^couchbase://", "")) + ":" + + (ActiveCluster.getInstance().isSSLEnabled() ? "11207" : "11210")); command.add("-u"); command.add(ActiveCluster.getInstance().getUsername()); command.add("-p"); @@ -57,8 +58,13 @@ public String getCollectionStatistics() throws IOException, InterruptedException command.add("-b"); command.add(bucketName); - command.add("collections"); - command.add(scopeName + "." + collectionName); + if (type.equalsIgnoreCase("collection")) { + command.add("collections"); + command.add(scopeName + "." + collectionName); + } else if (type.equalsIgnoreCase("scope")) { + command.add("collections"); + command.add(scopeName); + } ProcessBuilder processBuilder = new ProcessBuilder(command); Process process = processBuilder.start(); diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java index 6c273dea..c3d0857b 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java @@ -38,7 +38,6 @@ public CbstatsDialog(String bucket, String scope, String collection,String type) this.type = type; init(); setTitle("Stats for " + type); - getWindow().setMinimumSize(new Dimension(350, 350)); setResizable(true); } @@ -50,7 +49,7 @@ protected JComponent createCenterPanel() { CBStats cbStats = new CBStats(bucketName, scopeName, collectionName,type); String output = ""; try { - output = cbStats.getCollectionStatistics(); + output = cbStats.executeCommand(); } catch (Exception ex) { Log.error(ex); } @@ -63,8 +62,8 @@ protected JComponent createCenterPanel() { for (int i = 0; i < lines.length; i++) { int keyStartIndex = lines[i].indexOf(':', lines[i].indexOf(':') + 1) + 1; int valueStartIndex = lines[i].lastIndexOf(':') + 1; - keys[i] = getCollectionFriendlyKeyName(lines[i].substring(keyStartIndex, valueStartIndex - 1).trim()); - values[i] = getCollectionFriendlyValue(lines[i].substring(valueStartIndex).trim(), keys[i]); + keys[i] = getFriendlyKeyName(lines[i].substring(keyStartIndex, valueStartIndex - 1).trim()); + values[i] = getFriendlyValue(lines[i].substring(valueStartIndex).trim(), keys[i]); helpTexts[i] = getHelpText(keys[i]); // get help text for each key } @@ -98,7 +97,7 @@ private String getHelpText(String key) { } } - private String getCollectionFriendlyKeyName(String key) { + private String getFriendlyKeyName(String key) { switch (key) { case "collections_mem_used": return MEMORY_USED_BY_COLLECTION; @@ -121,7 +120,7 @@ private String getCollectionFriendlyKeyName(String key) { } } - private String getCollectionFriendlyValue(String value, String key) { + private String getFriendlyValue(String value, String key) { switch (key) { case MEMORY_USED_BY_COLLECTION: case COLLECTION_DATA_SIZE: From 4ad7a962916306947be365d484b4af63016847f2 Mon Sep 17 00:00:00 2001 From: teetangh Date: Thu, 21 Sep 2023 16:50:33 +0530 Subject: [PATCH 11/11] updated friendly values --- .../com/couchbase/intellij/tools/CBStats.java | 2 +- .../intellij/tools/dialog/CbstatsDialog.java | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/couchbase/intellij/tools/CBStats.java b/src/main/java/com/couchbase/intellij/tools/CBStats.java index 513e5186..a8a65946 100644 --- a/src/main/java/com/couchbase/intellij/tools/CBStats.java +++ b/src/main/java/com/couchbase/intellij/tools/CBStats.java @@ -62,7 +62,7 @@ public String executeCommand() throws IOException, InterruptedException { command.add("collections"); command.add(scopeName + "." + collectionName); } else if (type.equalsIgnoreCase("scope")) { - command.add("collections"); + command.add("scopes"); command.add(scopeName); } diff --git a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java index c3d0857b..8abddb5a 100644 --- a/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java +++ b/src/main/java/com/couchbase/intellij/tools/dialog/CbstatsDialog.java @@ -1,7 +1,6 @@ package com.couchbase.intellij.tools.dialog; import java.awt.BorderLayout; -import java.awt.Dimension; import javax.swing.JComponent; import javax.swing.JPanel; @@ -30,7 +29,7 @@ public class CbstatsDialog extends DialogWrapper { private static final String NUMBER_OF_STORE_OPERATIONS = "Number Of Store Operations"; private static final String SCOPE_NAME = "Scope Name"; - public CbstatsDialog(String bucket, String scope, String collection,String type) { + public CbstatsDialog(String bucket, String scope, String collection, String type) { super(true); this.bucketName = bucket; this.scopeName = scope; @@ -46,7 +45,7 @@ public CbstatsDialog(String bucket, String scope, String collection,String type) protected JComponent createCenterPanel() { JPanel dialogPanel = new JPanel(new BorderLayout()); - CBStats cbStats = new CBStats(bucketName, scopeName, collectionName,type); + CBStats cbStats = new CBStats(bucketName, scopeName, collectionName, type); String output = ""; try { output = cbStats.executeCommand(); @@ -132,8 +131,21 @@ private String getFriendlyValue(String value, String key) { } else { return String.format("%.2f MB", sizeInMB); } + case NUMBER_OF_DELETE_OPERATIONS: + case NUMBER_OF_GET_OPERATIONS: + case NUMBER_OF_STORE_OPERATIONS: + case NUMBER_OF_ITEMS: + long count = Long.parseLong(value); + if (count >= 1_000_000) { + return String.format("%.2f M", count / 1_000_000.0); + } else if (count >= 1_000) { + return String.format("%.2f K", count / 1_000.0); + } else { + return value; + } default: return value; } } + }