mirror of https://github.com/apache/kafka.git
KAFKA-14559: Fix JMX tool to handle the object names with wildcard and optional attributes (#13060)
Reviewers: Federico Valeri <fedevaleri@gmail.com>, Satish Duggana <satishd@apache.org>
This commit is contained in:
parent
bd65db82b4
commit
54a4067f81
|
@ -82,7 +82,7 @@ public class JmxTool {
|
||||||
List<ObjectName> queries = options.queries();
|
List<ObjectName> queries = options.queries();
|
||||||
boolean hasPatternQueries = queries.stream().filter(Objects::nonNull).anyMatch(ObjectName::isPattern);
|
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 =
|
Map<ObjectName, Integer> numExpectedAttributes =
|
||||||
findNumExpectedAttributes(conn, attributesInclude, hasPatternQueries, queries, found);
|
findNumExpectedAttributes(conn, attributesInclude, hasPatternQueries, queries, found);
|
||||||
|
|
||||||
|
@ -113,8 +113,8 @@ public class JmxTool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String mkString(Stream<Object> stream, String delimeter) {
|
private static String mkString(Stream<Object> stream, String delimiter) {
|
||||||
return stream.filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(delimeter));
|
return stream.filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(delimiter));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int sumValues(Map<ObjectName, Integer> numExpectedAttributes) {
|
private static int sumValues(Map<ObjectName, Integer> numExpectedAttributes) {
|
||||||
|
@ -162,26 +162,24 @@ public class JmxTool {
|
||||||
return serverConn;
|
return serverConn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<ObjectName> findObjectsIfNoPattern(JmxToolOptions options,
|
private static Set<ObjectName> findObjects(JmxToolOptions options,
|
||||||
MBeanServerConnection conn,
|
MBeanServerConnection conn,
|
||||||
List<ObjectName> queries,
|
List<ObjectName> queries,
|
||||||
boolean hasPatternQueries) throws Exception {
|
boolean hasPatternQueries) throws Exception {
|
||||||
long waitTimeoutMs = 10_000;
|
long waitTimeoutMs = 10_000;
|
||||||
Set<ObjectName> result = new HashSet<>();
|
Set<ObjectName> result = new HashSet<>();
|
||||||
Set<ObjectName> querySet = new HashSet<>(queries);
|
Set<ObjectName> querySet = new HashSet<>(queries);
|
||||||
BiPredicate<Set<ObjectName>, Set<ObjectName>> foundAllObjects = (s1, s2) -> s1.containsAll(s2);
|
BiPredicate<Set<ObjectName>, Set<ObjectName>> foundAllObjects = Set::containsAll;
|
||||||
if (!hasPatternQueries) {
|
long start = System.currentTimeMillis();
|
||||||
long start = System.currentTimeMillis();
|
do {
|
||||||
do {
|
if (!result.isEmpty()) {
|
||||||
if (!result.isEmpty()) {
|
System.err.println("Could not find all object names, retrying");
|
||||||
System.err.println("Could not find all object names, retrying");
|
TimeUnit.MILLISECONDS.sleep(100);
|
||||||
TimeUnit.MILLISECONDS.sleep(100);
|
}
|
||||||
}
|
result.addAll(queryObjects(conn, queries));
|
||||||
result.addAll(queryObjects(conn, queries));
|
} while (!hasPatternQueries && options.hasWait() && System.currentTimeMillis() - start < waitTimeoutMs && !foundAllObjects.test(querySet, result));
|
||||||
} while (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);
|
querySet.removeAll(result);
|
||||||
String missing = mkString(querySet.stream().map(Object::toString), ",");
|
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));
|
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 {
|
} else {
|
||||||
if (!hasPatternQueries) {
|
if (hasPatternQueries) {
|
||||||
found.forEach(objectName -> {
|
found.forEach(objectName -> {
|
||||||
try {
|
try {
|
||||||
MBeanInfo mBeanInfo = conn.getMBeanInfo(objectName);
|
MBeanInfo mBeanInfo = conn.getMBeanInfo(objectName);
|
||||||
|
@ -237,7 +235,7 @@ public class JmxTool {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
queries.forEach(objectName -> result.put(objectName, attributesInclude.get().length));
|
found.forEach(objectName -> result.put(objectName, attributesInclude.get().length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,140 @@ public class JmxToolTest {
|
||||||
assertEquals("3.0", csv.get("kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec:FiveMinuteRate"));
|
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
|
@Test
|
||||||
public void dateFormat() {
|
public void dateFormat() {
|
||||||
String dateFormat = "yyyyMMdd-hh:mm:ss";
|
String dateFormat = "yyyyMMdd-hh:mm:ss";
|
||||||
|
|
Loading…
Reference in New Issue