Skip to content

KAFKA-13846: Adding overloaded addMetricIfAbsent method#12121

Merged
guozhangwang merged 8 commits intoapache:trunkfrom
vamossagar12:KAFKA-13846
Jun 13, 2022
Merged

KAFKA-13846: Adding overloaded addMetricIfAbsent method#12121
guozhangwang merged 8 commits intoapache:trunkfrom
vamossagar12:KAFKA-13846

Conversation

@vamossagar12
Copy link
Contributor

More detailed description of your change,
if necessary. The PR title and PR message become
the squashed commit message, so use a separate
comment to ping reviewers.

Summary of testing strategy (including rationale)
for the feature or bug fix. Unit and/or integration
tests are expected for any behaviour change and
system tests should be considered for larger changes.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be useful to know if the metric is created vs. already existed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah currently, metricOrElseCreate hides that fact. I can add a log line here is needed. Also, I guess the addMetric method(s) already can be used to answer the created v/s already existed question.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jolshan I added a log line for the case where there's no exception to be thrown.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wonder if this change is really necessary. Is it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @vamossagar12 @jolshan @dajac , since registerMetric is a package private function I'm thinking about modifying its signature to return the already existed metric (null if it does not exist, not null means no changes to the underlying registry since there's already a metric), hence indicating if the register-metric succeeded or not. And let the caller (addMetric or metricOrElseCreate) to react accordingly: e.g. the former would still throw exception if it gets a non-null return value, while the latter just returns the metric. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guozhangwang i think yeah that could be done. I have made the changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registerMetric is also called from the Sensor class so we have to check if that works there as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were a couple of test failures because of this usage. I updated the code to throw an IllegalArgumentException for backward compatibility reasons.

@jolshan
Copy link
Member

jolshan commented May 6, 2022

I was also wondering -- is this file (clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java) considered part of the public apis?

@vamossagar12 vamossagar12 changed the title Kafka 13846: Adding overloaded metricOrElseCreate method KAFKA-13846: Adding overloaded metricOrElseCreate method May 8, 2022
@vamossagar12
Copy link
Contributor Author

I was also wondering -- is this file (clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java) considered part of the public apis?

I am not sure of that.. @guozhangwang can answer that probably..

@vamossagar12
Copy link
Contributor Author

I was also wondering -- is this file (clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java) considered part of the public apis?

I am not sure of that.. @guozhangwang can answer that probably..

@jolshan my guess is it is. But i am not 100% sure.

@vamossagar12
Copy link
Contributor Author

@guozhangwang , could you plz review this whenever you get the chance?

Copy link
Member

@dajac dajac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I left a few comments.

From a public API point of view, Metrics is in a gray area. It is not officially part of our public API however we have a few interfaces leaking it. That being said, we should be careful with the changes that we do here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we really need all these overloads. Do we have use cases for all of them? I have the impression that the last one would be sufficient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the other 2. I had added them to be at par with the addMetric method and it's overloads.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wonder if this change is really necessary. Is it?

@vamossagar12
Copy link
Contributor Author

Thanks for the PR. I left a few comments.

From a public API point of view, Metrics is in a gray area. It is not officially part of our public API however we have a few interfaces leaking it. That being said, we should be careful with the changes that we do here.

Thank you for the review. Just wanted to know if it's a public API, does it mean we need a KIP for this? And I totally agree with being careful.

Copy link
Contributor

@guozhangwang guozhangwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vamossagar12 Thanks for the PR! I left a couple comments, aiming to make the newly added function to be atomic with just a single operation on the underlying registry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @vamossagar12 @jolshan @dajac , since registerMetric is a package private function I'm thinking about modifying its signature to return the already existed metric (null if it does not exist, not null means no changes to the underlying registry since there's already a metric), hence indicating if the register-metric succeeded or not. And let the caller (addMetric or metricOrElseCreate) to react accordingly: e.g. the former would still throw exception if it gets a non-null return value, while the latter just returns the metric. WDYT?

@guozhangwang
Copy link
Contributor

From a public API point of view, Metrics is in a gray area. It is not officially part of our public API however we have a few interfaces leaking it. That being said, we should be careful with the changes that we do here.

I agree with @dajac as well, what I was thinking is that we can modify the private registerMetric, and I'm neutral about whether adding a public metricOrElseCreate should require a KIP. If people think this is necessary, we could create one.

@vamossagar12
Copy link
Contributor Author

From a public API point of view, Metrics is in a gray area. It is not officially part of our public API however we have a few interfaces leaking it. That being said, we should be careful with the changes that we do here.

I agree with @dajac as well, what I was thinking is that we can modify the private registerMetric, and I'm neutral about whether adding a public metricOrElseCreate should require a KIP. If people think this is necessary, we could create one.

Sure thing... Even I am neutral about KIP.

@dajac
Copy link
Member

dajac commented May 20, 2022

Metrics is actually published in our javadoc. This suggests that changing it would require a KIP, no?

@dajac
Copy link
Member

dajac commented May 20, 2022

Do we also have concrete examples of usages of this new API? It would be helpful to update one or two metrics which would benefits from this change. This would be a good illustration.

Copy link
Contributor

@guozhangwang guozhangwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also have concrete examples of usages of this new API? It would be helpful to update one or two metrics which would benefits from this change. This would be a good illustration.

Yes, there are quite many places where multiple threads tried to create the same metric and has to follow the pattern I described in the JIRA ticket. If we just search for the usage of the metric(metricName) function, we can found a bunch of them, e.g. in Fetcher, ConnectMetrics, TaskMetricsGroup, etc.

Metrics is actually published in our javadoc. This suggests that changing it would require a KIP, no?

Sounds good. Let's create a tiny KIP to add the function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybeMetric => existingMetric?

@vamossagar12
Copy link
Contributor Author

Do we also have concrete examples of usages of this new API? It would be helpful to update one or two metrics which would benefits from this change. This would be a good illustration.

Yes, there are quite many places where multiple threads tried to create the same metric and has to follow the pattern I described in the JIRA ticket. If we just search for the usage of the metric(metricName) function, we can found a bunch of them, e.g. in Fetcher, ConnectMetrics, TaskMetricsGroup, etc.

Metrics is actually published in our javadoc. This suggests that changing it would require a KIP, no?

Sounds good. Let's create a tiny KIP to add the function.

Sure. I made following updates in ConnectMetrics:

https://github.com/apache/kafka/blob/c1467aeeed99a11bae3e69c5d7edeee5bcc3e496/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/ConnectMetrics.java#L320-L332

Note that, IlegalArguementExeception is still possible through metricName() method so I didn't remove that from the javadoc.

Also, I created a small KIP for the same: https://cwiki.apache.org/confluence/display/KAFKA/KIP-843%3A+Adding+metricOrElseCreate+method+to+Metrics

@vamossagar12
Copy link
Contributor Author

@dajac , @guozhangwang The KIP has been approved. Also, as per one of the suggestions on the KIP, metricOrElseCreate has been renamed to getMetricOrElseCreate.

@guozhangwang
Copy link
Contributor

@dajac , @guozhangwang The KIP has been approved. Also, as per one of the suggestions on the KIP, metricOrElseCreate has been renamed to getMetricOrElseCreate.

Thanks! Let's wait and see what people like as the final name of the function :)

@vamossagar12
Copy link
Contributor Author

@dajac , @guozhangwang The KIP has been approved. Also, as per one of the suggestions on the KIP, metricOrElseCreate has been renamed to getMetricOrElseCreate.

Thanks! Let's wait and see what people like as the final name of the function :)

Makes sense. :)

@vamossagar12
Copy link
Contributor Author

@guozhangwang/ @dajac I have updated the name of the function now. I sent out a note 2-3 days ago and didn't notice any resistance. Plz review

@guozhangwang
Copy link
Contributor

@vamossagar12 could you close the VOTE thread before we can review and merge?

@vamossagar12
Copy link
Contributor Author

@guozhangwang done.

Copy link
Contributor

@guozhangwang guozhangwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! @vamossagar12 could you file a follow-up PR that update the web docs on 3.3 release new API changes, as well as a couple of nit comments above?

config == null ? this.config : config,
time);
registerMetric(m);
KafkaMetric existingMetric = registerMetric(m);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we clarify in the javadoc above that if the metric already exists, an exception would be thrown?

* When a metric is newly registered, this method returns null
*
* @param metric The KafkaMetric to register
* @return KafkaMetric if the metric already exists, null otherwise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can just say "the existing metric with the same name"

@guozhangwang guozhangwang merged commit 5cab11c into apache:trunk Jun 13, 2022
@ijuma
Copy link
Member

ijuma commented Jun 14, 2022

The PR title and commit title seem wrong since the method we introduced is not metricOrElseCreate...

MetricName metricName = metric.metricName();
if (this.metrics.containsKey(metricName))
throw new IllegalArgumentException("A metric named '" + metricName + "' already exists, can't register another one.");
if (this.metrics.containsKey(metricName)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not efficient to do contains and then get. We should do the get and check if the result is null. That halves the cost of the operations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even better, call putIfAbsent, if available.

ableegoldman added a commit to confluentinc/kafka that referenced this pull request Jun 14, 2022
CONFLUENT: Sync from apache/kafka trunk to confluentinc/kafka master (13 Jun 2022)

apache/trunk: (7 commits)
KAFKA-13891: reset generation when syncgroup failed with REBALANCE_IN…(apache#12140)
KAFKA-10000: Exactly-once source tasks (apache#11780)
KAFKA-13436: Omitted BrokerTopicMetrics metrics in the documentation (apache#11473)
MINOR: Use Exit.addShutdownHook instead of directly adding hooks to R…(apache#12283)
KAFKA-13846: Adding overloaded metricOrElseCreate method (apache#12121)
KAFKA-13935 Fix static usages of IBP in KRaft mode (apache#12250)
HOTFIX: null check keys of ProducerRecord when computing sizeInBytes (apache#12288)


Conflicts:
None
@vamossagar12 vamossagar12 changed the title KAFKA-13846: Adding overloaded metricOrElseCreate method KAFKA-13846: Adding overloaded addMetricIfAbsent method Jun 15, 2022
@vamossagar12
Copy link
Contributor Author

@ijuma ., i updated the PR name. Also, created a follow up PR to address some of the comments: #12297
@guozhangwang , which file does this correspond to? that update the web docs on 3.3 release new API changes

@guozhangwang
Copy link
Contributor

@guozhangwang , which file does this correspond to? that update the web docs on 3.3 release new API changes

Here: https://github.com/apache/kafka/blob/trunk/docs/upgrade.html. You can find earlier PRs how they update the upgrade guide / API changes in upcoming releases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants