This is an automated email from the ASF dual-hosted git repository.

clebertsuconic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new c3d0658  ARTEMIS-3671 fix readability of queue stat output
c3d0658 is described below

commit c3d0658466d59d3e1f55355090895d735c349d00
Author: Justin Bertram <[email protected]>
AuthorDate: Sun Dec 12 22:53:31 2021 -0600

    ARTEMIS-3671 fix readability of queue stat output
---
 .../artemis/cli/commands/queue/StatQueue.java      | 95 +++++++++++++++++-----
 .../org/apache/activemq/cli/test/ArtemisTest.java  | 74 +++++++++++++++++
 2 files changed, 149 insertions(+), 20 deletions(-)

diff --git 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
index 5791d0a..634da39 100644
--- 
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
+++ 
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
@@ -16,6 +16,11 @@
  */
 package org.apache.activemq.artemis.cli.commands.queue;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
 import io.airlift.airline.Command;
 import io.airlift.airline.Option;
 import org.apache.activemq.artemis.api.core.JsonUtil;
@@ -23,17 +28,10 @@ import 
org.apache.activemq.artemis.api.core.client.ClientMessage;
 import org.apache.activemq.artemis.api.core.management.ManagementHelper;
 import org.apache.activemq.artemis.cli.commands.AbstractAction;
 import org.apache.activemq.artemis.cli.commands.ActionContext;
-
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonObject;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-@Command(name = "stat", description = "prints out basic stats associated with 
queues. Output includes CONSUMER_COUNT (number of consumers), MESSAGE_COUNT 
(current message count on the queue, including scheduled, paged and in-delivery 
messages), MESSAGES_ADDED (messages added to the queue), DELIVERING_COUNT 
(messages broker is currently delivering to consumer(s)), MESSAGES_ACKED 
(messages acknowledged from the consumer(s))." + " Queues can be filtered using 
EITHER '--queueName X' where X  [...]
 
-)
+@Command(name = "stat", description = "prints out basic stats associated with 
queues. Output includes CONSUMER_COUNT (number of consumers), MESSAGE_COUNT 
(current message count on the queue, including scheduled, paged and in-delivery 
messages), MESSAGES_ADDED (messages added to the queue), DELIVERING_COUNT 
(messages broker is currently delivering to consumer(s)), MESSAGES_ACKED 
(messages acknowledged from the consumer(s))." + " Queues can be filtered using 
EITHER '--queueName X' where X  [...]
 public class StatQueue extends AbstractAction {
 
    public enum FIELD {
@@ -68,6 +66,8 @@ public class StatQueue extends AbstractAction {
 
    public static final int DEFAULT_MAX_ROWS = 50;
 
+   public static final int DEFAULT_MAX_COLUMN_SIZE = 25;
+
    @Option(name = "--queueName", description = "display queue stats for 
queue(s) with names containing this string.")
    private String queueName;
 
@@ -83,6 +83,9 @@ public class StatQueue extends AbstractAction {
    @Option(name = "--maxRows", description = "max number of queues displayed. 
Default is 50.")
    private int maxRows = DEFAULT_MAX_ROWS;
 
+   @Option(name = "--maxColumnSize", description = "max width of data column. 
Set to -1 for no limit. Default is 25.")
+   private int maxColumnSize = DEFAULT_MAX_COLUMN_SIZE;
+
    //easier for testing
    public StatQueue setQueueName(String queueName) {
       this.queueName = queueName;
@@ -109,6 +112,20 @@ public class StatQueue extends AbstractAction {
       return this;
    }
 
+   public StatQueue setMaxColumnSize(int maxColumnSize) {
+      int maxFieldSize = 0;
+      for (FIELD e : FIELD.values()) {
+         if (e.jsonId.length() > maxFieldSize) {
+            maxFieldSize = e.jsonId.length();
+         }
+      }
+      if (maxColumnSize != -1 && maxColumnSize < maxFieldSize) {
+         throw new IllegalArgumentException("maxColumnSize must be " + 
maxFieldSize + " or greater or -1 (i.e. no limit).");
+      }
+      this.maxColumnSize = maxColumnSize;
+      return this;
+   }
+
    public StatQueue setverbose(boolean verbose) {
       this.verbose = verbose;
       return this;
@@ -154,7 +171,6 @@ public class StatQueue extends AbstractAction {
    }
 
    private void printStats(String result) {
-      printHeadings();
 
       //should not happen but...
       if (result == null) {
@@ -168,8 +184,21 @@ public class StatQueue extends AbstractAction {
       int count = queuesAsJsonObject.getInt("count");
       JsonArray array = queuesAsJsonObject.getJsonArray("data");
 
+      int[] columnSizes = new int[FIELD.values().length];
+
+      FIELD[] fields = FIELD.values();
+      for (int i = 0; i < fields.length; i++) {
+         columnSizes[i] = fields[i].toString().length();
+      }
+
       for (int i = 0; i < array.size(); i++) {
-         printQueueStats(array.getJsonObject(i));
+         getColumnSizes(array.getJsonObject(i), columnSizes);
+      }
+
+      printHeadings(columnSizes);
+
+      for (int i = 0; i < array.size(); i++) {
+         printQueueStats(array.getJsonObject(i), columnSizes);
       }
 
       if (count > maxRows) {
@@ -177,14 +206,33 @@ public class StatQueue extends AbstractAction {
       }
    }
 
-   private void printHeadings() {
+   private void getColumnSizes(JsonObject jsonObject, int[] columnSizes) {
+      int i = 0;
+      for (FIELD e: FIELD.values()) {
+         if (jsonObject.getString(e.jsonId).length() > columnSizes[i]) {
+            columnSizes[i] = jsonObject.getString(e.jsonId).length();
+         }
+         // enforce max
+         if (columnSizes[i] > maxColumnSize && maxColumnSize != -1) {
+            columnSizes[i] = maxColumnSize;
+         }
+         i++;
+      }
+   }
+
+   private void printHeadings(int[] columnSizes) {
+      // add 10 for the various '|' characters
+      StringBuilder stringBuilder = new 
StringBuilder(Arrays.stream(columnSizes).sum() + FIELD.values().length + 
1).append('|');
 
-      StringBuilder stringBuilder = new 
StringBuilder(134).append('|').append(paddingString(new 
StringBuilder(FIELD.NAME.toString()), 25)).append('|').append(paddingString(new 
StringBuilder(FIELD.ADDRESS.toString()), 
25)).append('|').append(paddingString(new 
StringBuilder(FIELD.CONSUMER_COUNT.toString() + " "), 
15)).append('|').append(paddingString(new 
StringBuilder(FIELD.MESSAGE_COUNT.toString() + " "), 
14)).append('|').append(paddingString(new 
StringBuilder(FIELD.MESSAGES_ADDED.toStrin [...]
+      int i = 0;
+      for (FIELD e: FIELD.values()) {
+         stringBuilder.append(paddingString(new StringBuilder(e.toString()), 
columnSizes[i++])).append('|');
+      }
 
       context.out.println(stringBuilder);
    }
 
-   private void printQueueStats(JsonObject jsonObject) {
+   private void printQueueStats(JsonObject jsonObject, int[] columnSizes) {
 
       //should not happen but just in case..
       if (jsonObject == null) {
@@ -194,16 +242,22 @@ public class StatQueue extends AbstractAction {
          return;
       }
 
-      StringBuilder stringBuilder = new 
StringBuilder(134).append('|').append(paddingString(new 
StringBuilder(jsonObject.getString(FIELD.NAME.getJsonId())), 
25)).append('|').append(paddingString(new 
StringBuilder(jsonObject.getString(FIELD.ADDRESS.getJsonId())), 
25)).append('|').append(paddingString(new 
StringBuilder(jsonObject.getString(FIELD.CONSUMER_COUNT.getJsonId())), 
15)).append('|').append(paddingString(new 
StringBuilder(jsonObject.getString(FIELD.MESSAGE_COUNT.getJsonId())), 14)) [...]
+      // add 10 for the various '|' characters
+      StringBuilder stringBuilder = new 
StringBuilder(Arrays.stream(columnSizes).sum() + FIELD.values().length + 
1).append('|');
+
+      int i = 0;
+      for (FIELD e: FIELD.values()) {
+         stringBuilder.append(paddingString(new 
StringBuilder(jsonObject.getString(e.jsonId)), columnSizes[i++])).append('|');
+      }
 
       context.out.println(stringBuilder);
    }
 
-   private StringBuilder paddingString(StringBuilder value, int size) {
+   private StringBuilder paddingString(StringBuilder value, int maxColumnSize) 
{
 
       //should not happen but just in case ...
       if (value == null) {
-         return new StringBuilder(size);
+         return new StringBuilder(maxColumnSize);
       }
 
       //would expect to have some data
@@ -212,12 +266,13 @@ public class StatQueue extends AbstractAction {
       }
 
       int length = value.length();
-      if (length >= size) {
-         //no padding required
-         return value;
+
+      if (length > maxColumnSize && this.maxColumnSize != -1) {
+         // truncate if necessary
+         return new StringBuilder(value.substring(0, maxColumnSize - 3) + 
"...");
       }
 
-      for (int i = 1; (i + length) <= size; i++) {
+      for (int i = 1; (i + length) <= maxColumnSize; i++) {
          value.append(' ');
       }
 
diff --git 
a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java 
b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
index 6020f78..de08be6 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
@@ -1738,6 +1738,80 @@ public class ArtemisTest extends CliTestBase {
    }
 
    @Test
+   public void testQstatColumnWidth() throws Exception {
+
+      File instanceQstat = new File(temporaryFolder.getRoot(), 
"instanceQStat");
+      setupAuth(instanceQstat);
+      Run.setEmbedded(true);
+      Artemis.main("create", instanceQstat.getAbsolutePath(), "--silent", 
"--no-fsync", "--no-autotune", "--no-web", "--require-login");
+      System.setProperty("artemis.instance", instanceQstat.getAbsolutePath());
+      Artemis.internalExecute("run");
+
+      try (ActiveMQConnectionFactory cf = new 
ActiveMQConnectionFactory("tcp://localhost:61616"); Connection connection = 
cf.createConnection("admin", "admin");) {
+
+         //set up some queues with messages and consumers
+         Session session = connection.createSession(false, 
Session.AUTO_ACKNOWLEDGE);
+         connection.start();
+         final String NAME = "012345678901234567890123456789";
+         sendMessages(session, NAME, 1);
+
+         TestActionContext context = new TestActionContext();
+         StatQueue statQueue = new StatQueue();
+         statQueue.setUser("admin");
+         statQueue.setPassword("admin");
+         statQueue.setQueueName(NAME);
+         statQueue.execute(context);
+         ArrayList<String> lines = getOutputLines(context, false);
+         Assert.assertEquals("rows returned", 2, lines.size());
+         String[] split = lines.get(1).split("\\|");
+         Assert.assertEquals(StatQueue.DEFAULT_MAX_COLUMN_SIZE, 
split[1].length());
+
+         context = new TestActionContext();
+         statQueue = new StatQueue();
+         statQueue.setUser("admin");
+         statQueue.setPassword("admin");
+         statQueue.setQueueName(NAME);
+         statQueue.setMaxColumnSize(15);
+         statQueue.execute(context);
+         lines = getOutputLines(context, false);
+         Assert.assertEquals("rows returned", 2, lines.size());
+         split = lines.get(1).split("\\|");
+         Assert.assertEquals(15, split[1].length());
+
+         context = new TestActionContext();
+         statQueue = new StatQueue();
+         statQueue.setUser("admin");
+         statQueue.setPassword("admin");
+         statQueue.setQueueName(NAME);
+         statQueue.setMaxColumnSize(50);
+         statQueue.execute(context);
+         lines = getOutputLines(context, false);
+         Assert.assertEquals("rows returned", 2, lines.size());
+         split = lines.get(1).split("\\|");
+         Assert.assertEquals(NAME.length(), split[1].length());
+
+         context = new TestActionContext();
+         statQueue = new StatQueue();
+         statQueue.setUser("admin");
+         statQueue.setPassword("admin");
+         statQueue.setQueueName(NAME);
+         statQueue.setMaxColumnSize(-1);
+         statQueue.execute(context);
+         lines = getOutputLines(context, false);
+         for (String line : lines) {
+            System.out.println(line);
+         }
+         Assert.assertEquals("rows returned", 2, lines.size());
+         split = lines.get(1).split("\\|");
+         Assert.assertEquals(NAME.length(), split[1].length());
+         Assert.assertEquals("CONSUMER_COUNT".length(), split[3].length());
+      } finally {
+         stopServer();
+      }
+
+   }
+
+   @Test
    public void testQstatErrors() throws Exception {
 
       File instanceQstat = new File(temporaryFolder.getRoot(), 
"instanceQStatErrors");

Reply via email to