diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/JmxClusterUtil.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/JmxClusterUtil.java index c0680708a0..c50597fd44 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/JmxClusterUtil.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/JmxClusterUtil.java @@ -1,11 +1,10 @@ package com.provectus.kafka.ui.util; import com.provectus.kafka.ui.model.Metric; -import java.io.IOException; import java.math.BigDecimal; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.List; @@ -13,16 +12,12 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceNotFoundException; import javax.management.MBeanAttributeInfo; -import javax.management.MBeanException; import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; import javax.management.ObjectName; -import javax.management.ReflectionException; import javax.management.remote.JMXConnector; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.KeyedObjectPool; import org.springframework.stereotype.Component; @@ -38,12 +33,19 @@ public class JmxClusterUtil { private static final String NAME_METRIC_FIELD = "name"; private final KeyedObjectPool pool; + @SneakyThrows public List getJmxMetrics(int jmxPort, String jmxHost) { String jmxUrl = JMX_URL + jmxHost + ":" + jmxPort + "/" + JMX_SERVICE_TYPE; - List result = new ArrayList<>(); - JMXConnector srv = null; + JMXConnector srv; try { srv = pool.borrowObject(jmxUrl); + } catch (Exception e) { + log.error("Cannot get JMX connector for the pool due to: ", e); + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + try { MBeanServerConnection msc = srv.getMBeanServerConnection(); var jmxMetrics = msc.queryNames(null, null).stream() .filter(q -> q.getCanonicalName().startsWith(KAFKA_SERVER_PARAM)) @@ -54,50 +56,28 @@ public class JmxClusterUtil { metric.setName(params.get(NAME_METRIC_FIELD)); metric.setCanonicalName(jmxMetric.getCanonicalName()); metric.setParams(params); - metric.setValue(getJmxMetric(jmxMetric.getCanonicalName(), msc, srv, jmxUrl)); + metric.setValue(getJmxMetric(jmxMetric.getCanonicalName(), msc)); result.add(metric); } pool.returnObject(jmxUrl, srv); - } catch (IOException ioe) { - log.error("Cannot get jmxMetricsNames, {}", jmxUrl, ioe); - closeConnectionExceptionally(jmxUrl, srv); } catch (Exception e) { - log.error("Cannot get JmxConnection from pool, {}", jmxUrl, e); + log.error("Cannot get jmxMetricsNames, {}", jmxUrl, e); closeConnectionExceptionally(jmxUrl, srv); } return result; } - private Map getJmxMetric(String canonicalName, MBeanServerConnection msc, - JMXConnector srv, String jmxUrl) { + @SneakyThrows + private Map getJmxMetric(String canonicalName, MBeanServerConnection msc) { Map resultAttr = new HashMap<>(); - try { - ObjectName name = new ObjectName(canonicalName); - var attrNames = msc.getMBeanInfo(name).getAttributes(); - for (MBeanAttributeInfo attrName : attrNames) { - var value = msc.getAttribute(name, attrName.getName()); - if ((value instanceof Number) - && (!(value instanceof Double) || !((Double) value).isInfinite())) { - resultAttr.put(attrName.getName(), new BigDecimal(value.toString())); - } + ObjectName name = new ObjectName(canonicalName); + var attrNames = msc.getMBeanInfo(name).getAttributes(); + for (MBeanAttributeInfo attrName : attrNames) { + var value = msc.getAttribute(name, attrName.getName()); + if (NumberUtil.isNumeric(value)) { + resultAttr.put(attrName.getName(), new BigDecimal(value.toString())); } - } catch (MalformedURLException url) { - log.error("Cannot create JmxServiceUrl from {}", jmxUrl); - closeConnectionExceptionally(jmxUrl, srv); - } catch (IOException io) { - log.error("Cannot connect to KafkaJmxServer with url {}", jmxUrl); - closeConnectionExceptionally(jmxUrl, srv); - } catch (MBeanException | AttributeNotFoundException - | InstanceNotFoundException | ReflectionException e) { - log.error("Cannot find attribute", e); - closeConnectionExceptionally(jmxUrl, srv); - } catch (MalformedObjectNameException objectNameE) { - log.error("Cannot create objectName", objectNameE); - closeConnectionExceptionally(jmxUrl, srv); - } catch (Exception e) { - log.error("Error while retrieving connection {} from pool", jmxUrl); - closeConnectionExceptionally(jmxUrl, srv); } return resultAttr; } diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/NumberUtil.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/NumberUtil.java new file mode 100644 index 0000000000..3f557f8e36 --- /dev/null +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/NumberUtil.java @@ -0,0 +1,9 @@ +package com.provectus.kafka.ui.util; + +import org.apache.commons.lang3.math.NumberUtils; + +public class NumberUtil { + public static boolean isNumeric(Object value) { + return value != null && NumberUtils.isCreatable(value.toString()); + } +} \ No newline at end of file diff --git a/kafka-ui-api/src/test/java/com/provectus/kafka/ui/util/NumberUtilTest.java b/kafka-ui-api/src/test/java/com/provectus/kafka/ui/util/NumberUtilTest.java new file mode 100644 index 0000000000..1c85d65535 --- /dev/null +++ b/kafka-ui-api/src/test/java/com/provectus/kafka/ui/util/NumberUtilTest.java @@ -0,0 +1,28 @@ +package com.provectus.kafka.ui.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class NumberUtilTest { + + @Test + void shouldReturnFalseWhenNonNumeric() { + Assertions.assertFalse(NumberUtil.isNumeric(Double.POSITIVE_INFINITY)); + Assertions.assertFalse(NumberUtil.isNumeric(Double.NEGATIVE_INFINITY)); + Assertions.assertFalse(NumberUtil.isNumeric(Double.NaN)); + Assertions.assertFalse(NumberUtil.isNumeric(null)); + Assertions.assertFalse(NumberUtil.isNumeric(" ")); + Assertions.assertFalse(NumberUtil.isNumeric(new Object())); + Assertions.assertFalse(NumberUtil.isNumeric("1231asd")); + } + + @Test + void shouldReturnTrueWhenNumeric() { + Assertions.assertTrue(NumberUtil.isNumeric("123.45")); + Assertions.assertTrue(NumberUtil.isNumeric(123.45)); + Assertions.assertTrue(NumberUtil.isNumeric(123)); + Assertions.assertTrue(NumberUtil.isNumeric(-123.45)); + Assertions.assertTrue(NumberUtil.isNumeric(-1e-10)); + Assertions.assertTrue(NumberUtil.isNumeric(1e-10)); + } +} \ No newline at end of file