diff --git a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetcherMetricsRegistry.java b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetcherMetricsRegistry.java index f15ac062abf..301363a638b 100644 --- a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetcherMetricsRegistry.java +++ b/clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetcherMetricsRegistry.java @@ -18,6 +18,7 @@ package org.apache.kafka.clients.consumer.internals; import java.util.Arrays; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -102,7 +103,7 @@ public class FetcherMetricsRegistry { "The maximum throttle time in ms", tags); /***** Topic level *****/ - Set topicTags = new HashSet<>(tags); + Set topicTags = new LinkedHashSet<>(tags); topicTags.add("topic"); this.topicFetchSizeAvg = new MetricNameTemplate("fetch-size-avg", groupName, diff --git a/clients/src/main/java/org/apache/kafka/clients/producer/internals/SenderMetricsRegistry.java b/clients/src/main/java/org/apache/kafka/clients/producer/internals/SenderMetricsRegistry.java index 21dbca61830..b01236f6218 100644 --- a/clients/src/main/java/org/apache/kafka/clients/producer/internals/SenderMetricsRegistry.java +++ b/clients/src/main/java/org/apache/kafka/clients/producer/internals/SenderMetricsRegistry.java @@ -17,7 +17,7 @@ package org.apache.kafka.clients.producer.internals; import java.util.ArrayList; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -70,12 +70,12 @@ public class SenderMetricsRegistry { private final Metrics metrics; private final Set tags; - private final HashSet topicTags; + private final LinkedHashSet topicTags; public SenderMetricsRegistry(Metrics metrics) { this.metrics = metrics; this.tags = this.metrics.config().tags().keySet(); - this.allTemplates = new ArrayList(); + this.allTemplates = new ArrayList<>(); /***** Client level *****/ @@ -126,7 +126,7 @@ public class SenderMetricsRegistry { "The maximum time in ms a request was throttled by a broker"); /***** Topic level *****/ - this.topicTags = new HashSet(tags); + this.topicTags = new LinkedHashSet<>(tags); this.topicTags.add("topic"); // We can't create the MetricName up front for these, because we don't know the topic name yet. diff --git a/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java b/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java index e3ea9950ef1..1b1de71037d 100644 --- a/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java +++ b/clients/src/main/java/org/apache/kafka/common/MetricNameTemplate.java @@ -16,7 +16,7 @@ */ package org.apache.kafka.common; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Objects; import java.util.Set; @@ -26,27 +26,45 @@ import org.apache.kafka.common.utils.Utils; * A template for a MetricName. It contains a name, group, and description, as * well as all the tags that will be used to create the mBean name. Tag values * are omitted from the template, but are filled in at runtime with their - * specified values. + * specified values. The order of the tags is maintained, if an ordered set + * is provided, so that the mBean names can be compared and sorted lexicographically. */ public class MetricNameTemplate { private final String name; private final String group; private final String description; - private Set tags; + private LinkedHashSet tags; - public MetricNameTemplate(String name, String group, String description, Set tags) { + /** + * Create a new template. Note that the order of the tags will be preserved if the supplied + * {@code tagsNames} set has an order. + * + * @param name the name of the metric; may not be null + * @param group the name of the group; may not be null + * @param description the description of the metric; may not be null + * @param tagsNames the set of metric tag names, which can/should be a set that maintains order; may not be null + */ + public MetricNameTemplate(String name, String group, String description, Set tagsNames) { this.name = Utils.notNull(name); this.group = Utils.notNull(group); this.description = Utils.notNull(description); - this.tags = Utils.notNull(tags); + this.tags = new LinkedHashSet<>(Utils.notNull(tagsNames)); } - - public MetricNameTemplate(String name, String group, String description, String... keys) { - this(name, group, description, getTags(keys)); + + /** + * Create a new template. Note that the order of the tags will be preserved. + * + * @param name the name of the metric; may not be null + * @param group the name of the group; may not be null + * @param description the description of the metric; may not be null + * @param tagsNames the names of the metric tags in the preferred order; none of the tag names should be null + */ + public MetricNameTemplate(String name, String group, String description, String... tagsNames) { + this(name, group, description, getTags(tagsNames)); } - private static Set getTags(String... keys) { - Set tags = new HashSet(); + private static LinkedHashSet getTags(String... keys) { + LinkedHashSet tags = new LinkedHashSet<>(); for (int i = 0; i < keys.length; i++) tags.add(keys[i]); @@ -54,18 +72,38 @@ public class MetricNameTemplate { return tags; } + /** + * Get the name of the metric. + * + * @return the metric name; never null + */ public String name() { return this.name; } + /** + * Get the name of the group. + * + * @return the group name; never null + */ public String group() { return this.group; } + /** + * Get the description of the metric. + * + * @return the metric description; never null + */ public String description() { return this.description; } + /** + * Get the set of tag names for the metric. + * + * @return the ordered set of tag names; never null but possibly empty + */ public Set tags() { return tags; } diff --git a/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java b/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java index 7f9fb9dad5a..8868ee7ac48 100644 --- a/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java +++ b/clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java @@ -232,12 +232,22 @@ public class Metrics implements Closeable { return tags; } - public static String toHtmlTable(String domain, List allMetrics) { + /** + * Use the specified domain and metric name templates to generate an HTML table documenting the metrics. A separate table section + * will be generated for each of the MBeans and the associated attributes. The MBean names are lexicographically sorted to + * determine the order of these sections. This order is therefore dependent upon the order of the + * tags in each {@link MetricNameTemplate}. + * + * @param domain the domain or prefix for the JMX MBean names; may not be null + * @param allMetrics the collection of all {@link MetricNameTemplate} instances each describing one metric; may not be null + * @return the string containing the HTML table; never null + */ + public static String toHtmlTable(String domain, Iterable allMetrics) { Map> beansAndAttributes = new TreeMap>(); try (Metrics metrics = new Metrics()) { for (MetricNameTemplate template : allMetrics) { - Map tags = new TreeMap(); + Map tags = new LinkedHashMap<>(); for (String s : template.tags()) { tags.put(s, "{" + s + "}"); }