You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by sa...@apache.org on 2023/05/11 16:19:49 UTC

[kafka] branch trunk updated: KAFKA-14559: Fix JMX tool to handle the object names with wildcard and optional attributes (#13060)

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

satishd pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/kafka.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 54a4067f81e KAFKA-14559: Fix JMX tool to handle the object names with wildcard and optional attributes (#13060)
54a4067f81e is described below

commit 54a4067f81e1434d956ef797274f7b437fe49ea1
Author: Kamal Chandraprakash <kc...@uber.com>
AuthorDate: Thu May 11 21:49:21 2023 +0530

    KAFKA-14559: Fix JMX tool to handle the object names with wildcard and optional attributes (#13060)
    
    Reviewers: Federico Valeri <fe...@gmail.com>, Satish Duggana <sa...@apache.org>
---
 .../main/java/org/apache/kafka/tools/JmxTool.java  |  40 +++---
 .../java/org/apache/kafka/tools/JmxToolTest.java   | 134 +++++++++++++++++++++
 2 files changed, 153 insertions(+), 21 deletions(-)

diff --git a/tools/src/main/java/org/apache/kafka/tools/JmxTool.java b/tools/src/main/java/org/apache/kafka/tools/JmxTool.java
index ea75748f68c..8347bffed3a 100644
--- a/tools/src/main/java/org/apache/kafka/tools/JmxTool.java
+++ b/tools/src/main/java/org/apache/kafka/tools/JmxTool.java
@@ -82,7 +82,7 @@ public class JmxTool {
             List<ObjectName> queries = options.queries();
             boolean hasPatternQueries = queries.stream().filter(Objects::nonNull).anyMatch(ObjectName::isPattern);
 
-            Set<ObjectName> found = findObjectsIfNoPattern(options, conn, queries, hasPatternQueries);
+            Set<ObjectName> found = findObjects(options, conn, queries, hasPatternQueries);
             Map<ObjectName, Integer> numExpectedAttributes =
                     findNumExpectedAttributes(conn, attributesInclude, hasPatternQueries, queries, found);
 
@@ -113,8 +113,8 @@ public class JmxTool {
         }
     }
 
-    private static String mkString(Stream<Object> stream, String delimeter) {
-        return stream.filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(delimeter));
+    private static String mkString(Stream<Object> stream, String delimiter) {
+        return stream.filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(delimiter));
     }
 
     private static int sumValues(Map<ObjectName, Integer> numExpectedAttributes) {
@@ -162,26 +162,24 @@ public class JmxTool {
         return serverConn;
     }
 
-    private static Set<ObjectName> findObjectsIfNoPattern(JmxToolOptions options,
-                                                          MBeanServerConnection conn,
-                                                          List<ObjectName> queries,
-                                                          boolean hasPatternQueries) throws Exception {
+    private static Set<ObjectName> findObjects(JmxToolOptions options,
+                                               MBeanServerConnection conn,
+                                               List<ObjectName> queries,
+                                               boolean hasPatternQueries) throws Exception {
         long waitTimeoutMs = 10_000;
         Set<ObjectName> result = new HashSet<>();
         Set<ObjectName> querySet = new HashSet<>(queries);
-        BiPredicate<Set<ObjectName>, Set<ObjectName>> foundAllObjects = (s1, s2) -> s1.containsAll(s2);
-        if (!hasPatternQueries) {
-            long start = System.currentTimeMillis();
-            do {
-                if (!result.isEmpty()) {
-                    System.err.println("Could not find all object names, retrying");
-                    TimeUnit.MILLISECONDS.sleep(100);
-                }
-                result.addAll(queryObjects(conn, queries));
-            } while (options.hasWait() && System.currentTimeMillis() - start < waitTimeoutMs && !foundAllObjects.test(querySet, result));
-        }
+        BiPredicate<Set<ObjectName>, Set<ObjectName>> foundAllObjects = Set::containsAll;
+        long start = System.currentTimeMillis();
+        do {
+            if (!result.isEmpty()) {
+                System.err.println("Could not find all object names, retrying");
+                TimeUnit.MILLISECONDS.sleep(100);
+            }
+            result.addAll(queryObjects(conn, queries));
+        } while (!hasPatternQueries && options.hasWait() && System.currentTimeMillis() - start < waitTimeoutMs && !foundAllObjects.test(querySet, result));
 
-        if (options.hasWait() && !foundAllObjects.test(querySet, result)) {
+        if (!hasPatternQueries && options.hasWait() && !foundAllObjects.test(querySet, result)) {
             querySet.removeAll(result);
             String missing = mkString(querySet.stream().map(Object::toString), ",");
             throw new TerseException(String.format("Could not find all requested object names after %d ms. Missing %s", waitTimeoutMs, missing));
@@ -218,7 +216,7 @@ public class JmxTool {
                 }
             });
         } else {
-            if (!hasPatternQueries) {
+            if (hasPatternQueries) {
                 found.forEach(objectName -> {
                     try {
                         MBeanInfo mBeanInfo = conn.getMBeanInfo(objectName);
@@ -237,7 +235,7 @@ public class JmxTool {
                     }
                 });
             } else {
-                queries.forEach(objectName -> result.put(objectName, attributesInclude.get().length));
+                found.forEach(objectName -> result.put(objectName, attributesInclude.get().length));
             }
         }
 
diff --git a/tools/src/test/java/org/apache/kafka/tools/JmxToolTest.java b/tools/src/test/java/org/apache/kafka/tools/JmxToolTest.java
index 8314d164058..674599edccb 100644
--- a/tools/src/test/java/org/apache/kafka/tools/JmxToolTest.java
+++ b/tools/src/test/java/org/apache/kafka/tools/JmxToolTest.java
@@ -174,6 +174,140 @@ public class JmxToolTest {
         assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
     }
 
+    @Test
+    public void testDomainNamePattern() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.serve?:*",
+            "--attributes", "FifteenMinuteRate,FiveMinuteRate",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    public void testDomainNamePatternWithNoAttributes() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.serve?:*",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    public void testPropertyListPattern() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=BrokerTopicMetrics,*",
+            "--attributes", "FifteenMinuteRate,FiveMinuteRate",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    public void testPropertyListPatternWithNoAttributes() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=BrokerTopicMetrics,*",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    public void testPropertyValuePattern() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=BrokerTopicMetrics,name=*InPerSec",
+            "--attributes", "FifteenMinuteRate,FiveMinuteRate",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    public void testPropertyValuePatternWithNoAttributes() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=BrokerTopicMetrics,name=*InPerSec",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    // Combination of property-list and property-value patterns
+    public void testPropertyPattern() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=*,*",
+            "--attributes", "FifteenMinuteRate,FiveMinuteRate",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
+    @Test
+    // Combination of property-list and property-value patterns
+    public void testPropertyPatternWithNoAttributes() {
+        String[] args = new String[]{
+            "--jmx-url", jmxUrl,
+            "--object-name", "kafka.server:type=*,*",
+            "--report-format", "csv",
+            "--one-time"
+        };
+        String out = executeAndGetOut(args);
+        assertNormalExit();
+
+        Map<String, String> csv = parseCsv(out);
+        assertEquals("1.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FifteenMinuteRate"));
+        assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
+    }
+
     @Test
     public void dateFormat() {
         String dateFormat = "yyyyMMdd-hh:mm:ss";