-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-9960: implement KIP-606 to add metadata context to MetricsReporter #8691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
5232433
82c0a0d
5d388cf
92d6389
e893850
2b36bc6
24bc78e
65195e1
9511de8
4964aef
8fd4ef5
69e4b7c
0e1a5b6
386a5da
6005c9a
d78a1e0
2484d71
85f7421
3e7cc54
f30c8f0
bd58373
26a2a76
a409085
d8c5d2a
1a1cf89
15bdb8d
7f5c69a
5598fa1
98371e4
1c42644
6f93472
071872f
7bcd057
319f5c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.kafka.common.metrics; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * A implementation of MetricsContext, it encapsulates required metrics context properties for Kafka services and clients | ||
| */ | ||
| public class KafkaMetricsContext implements MetricsContext { | ||
| /** | ||
| * Client or Service's contextLabels map. | ||
| */ | ||
| private final Map<String, String> contextLabels = new HashMap<>(); | ||
|
|
||
| /** | ||
| * Create a MetricsContext with namespace, no service or client properties | ||
| * @param namespace value for _namespace key | ||
| */ | ||
| public KafkaMetricsContext(String namespace) { | ||
| this(namespace, new HashMap<>()); | ||
| } | ||
|
|
||
| /** | ||
| * Create a MetricsContext with namespace, service or client properties | ||
| * @param namespace value for _namespace key | ||
| * @param contextLabels contextLabels additional entries to add to the context. | ||
| * values will be converted to string using Object.toString() | ||
| */ | ||
| public KafkaMetricsContext(String namespace, Map<String, ?> contextLabels) { | ||
| this.contextLabels.put(MetricsContext.NAMESPACE, namespace); | ||
| contextLabels.forEach((key, value) -> this.contextLabels.put(key, value.toString())); | ||
| } | ||
|
|
||
| public Map<String, String> contextLabels() { | ||
|
rhauch marked this conversation as resolved.
|
||
| return Collections.unmodifiableMap(contextLabels); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package org.apache.kafka.common.metrics; | ||
|
|
||
| import org.apache.kafka.common.annotation.InterfaceStability; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * MetricsContext encapsulates additional contextLabels about metrics exposed via a | ||
| * {@link org.apache.kafka.common.metrics.MetricsReporter} | ||
| * | ||
| * The contextLabels map provides following information: | ||
| * - a <code>_namespace</node> field indicating the component exposing metrics | ||
| * e.g. kafka.server, kafka.consumer | ||
| * {@link JmxReporter} uses this as prefix for mbean names | ||
| * | ||
| * - for clients and streams libraries: any freeform fields passed in via | ||
| * client properties in the form of `metrics.context.<key>=<value> | ||
| * | ||
| * - for kafka brokers: kafka.broker.id, kafka.cluster.id | ||
| * - for connect workers: connect.kafka.cluster.id, connect.group.id | ||
| */ | ||
| @InterfaceStability.Evolving | ||
| public interface MetricsContext { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking through the PR, it seems that MetricsContext is a short lived object used to pass values to the MetricReporters as they are constructed. Since the usage appears to be write-once, it might be better to expose a subset of Map rather than the full thing. E.g., If we think this might evolve into a mutable long-lived object, then a Map is probably better. Just a thought.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think having an interface gives us more flexibility to evolve the API, without breaking backwards compatibility.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't suggesting that we eliminate the interface, I definitely think having one is a good choice (for the reasons you mentioned). What I meant was in this interface, we expose a Map as the collection of metrics tags/labels. But since it appears that the usage is intended to be read-only, maybe a Map isn't the best choice. Here's what I was thinking: interface MetricsContext {
String namespace();
String get(String field);
Collection<String> fields();
}(included the namespace suggestion from my other comment as well).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think keeping a Map interface makes it more convenient to work with. It gives you all the helper methods and streaming interfaces rather than having to hand-roll those things for someone consuming the api. |
||
| /* predefined fields */ | ||
| String NAMESPACE = "_namespace"; // metrics namespace, formerly jmx prefix | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we define this as a field on the interface?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the interface is a natural way to expose predefined constants an API might need. I don't see a need to have a separate class for this yet.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I shouldn't have said "field" since that implies a concrete class. See above comment above for an example of what I meant.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced we should give namespace a special status over other fields, it just happens to be the only one we currently define by default for backwards compatibility reasons. If we find ourselves adding more of those, I agreee it would be worth revisiting how we expose pre-defined fields. |
||
|
|
||
| /** | ||
| * Returns contextLabels fields | ||
| */ | ||
| Map<String, String> contextLabels(); | ||
|
rhauch marked this conversation as resolved.
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| import java.util.Set; | ||
|
|
||
| import org.apache.kafka.common.Reconfigurable; | ||
| import org.apache.kafka.common.annotation.InterfaceStability; | ||
| import org.apache.kafka.common.config.ConfigException; | ||
|
|
||
| /** | ||
|
|
@@ -65,4 +66,12 @@ default void validateReconfiguration(Map<String, ?> configs) throws ConfigExcept | |
| default void reconfigure(Map<String, ?> configs) { | ||
| } | ||
|
|
||
| /** | ||
| * Provides context labels for the service or library exposing metrics | ||
| * | ||
| * @param metricsContext the metric context | ||
| */ | ||
| @InterfaceStability.Evolving | ||
| default void contextChange(MetricsContext metricsContext) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't have a strong preference. Past tense is a little odd, but I think
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would also be good to identify when this is called relative to other methods. For example, it is always called before
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. due to the way jmxreporter is initialized in Kafka today, it already gets called both before and after
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be called multiple times. Not sure if we should mention that in Javadoc, other methods in this class we are not mention if it can be called multiple times even though they can be called multiple times.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there is no clear call pattern, then it's fine to not say anything. However, If that call pattern is true, then I think we should document it. If it's also true it can be called later, then mention this as well. For example, the JavaDoc text on
WDYT?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. Updated javadoc. |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xvrl can we remove the explicit construction of JmxReporter and rely on the plugin loading mechanism after we remove this non-zero-arg constructor? Maybe something for 3.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I agree. We'll have to decide whether to make the config include this reporter by default or so something else. There are some backwards compatibility implications, but probably better to have a separate discussion for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thanks 👍