Skip to content
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

Handle non-numeric metric values #21

Merged
merged 9 commits into from
Jun 21, 2024

Conversation

OwenCorrigan76
Copy link
Contributor

@OwenCorrigan76 OwenCorrigan76 commented Jun 10, 2024

Prometheus only supports numeric values for metrics. A few metrics emitted by Kafka brokers and clients have non-numeric values. This PR will move the non-numeric value to a label and then and set its value to 1.0, to satisfy Prometheus only supporting numeric values.

Reported in the following issue:
#8

@OwenCorrigan76 OwenCorrigan76 added this to the 0.1.0 milestone Jun 10, 2024
@mimaison
Copy link
Contributor

Thanks for the PR.
I seems to only handle non-numeric metrics in KafkaMetricsCollector. You also need to do it in YammerMetricsCollector.convert()

Copy link
Contributor

@mimaison mimaison 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 updates. I made another pass and left a few more comments.

labels = new HashMap<>();
labels.put("key", "value");
}
private final Map<String, String> labels = Map.of("key", "value");
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you're making this change here, do you want to do the same in YammerMetricsCollectorTest? as it has the exact same code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We decided to keep as is because the ordering is clear

Copy link

Choose a reason for hiding this comment

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

the reply doesn't really make sense, but I'm not too worried either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, wrong place for my last comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd still prefer to use the same logic in both KafkaMetricsCollectorTest and YammerMetricsCollectorTest. So either we revert this, or we do the same in YammerMetricsCollectorTest.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I missed this comment somehow. To keep uniformity, I will revert KafkaMetricsReporter to the former logic.
In trying to implement private final LinkedHashMap<String, String> tags = new LinkedHashMap<>(Map.of("key", "value", "key2", "value2")); , while the LinkedHashMap provided ordering guarantee, I think the Map.of method creates an immutable map, and using it directly to initialize a mutable LinkedHashMap might cause issues in some cases, causing the test to fail sometimes.

Copy link

@k-wall k-wall left a comment

Choose a reason for hiding this comment

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

couple of nits, but I think this is looking close now.

Copy link
Contributor

@mimaison mimaison 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 updates. I made a another pass and left a few comments.

labels = new HashMap<>();
labels.put("key", "value");
}
private final Map<String, String> labels = Map.of("key", "value");
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd still prefer to use the same logic in both KafkaMetricsCollectorTest and YammerMetricsCollectorTest. So either we revert this, or we do the same in YammerMetricsCollectorTest.

Comment on lines 92 to 93
assertEquals("kafka_server_group_name", metricFamilySamples.name);
assertEquals(1, metricFamilySamples.samples.size());
Copy link
Contributor

Choose a reason for hiding this comment

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

These 2 assertions are checked again in assertMetricFamilySample(). Why are we checking them twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Duplicates removed

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be more idiomatic to either check the size in assertMetricFamilySample(), or pass the unique sample (metricFamilySamples.samples.get(0)) to assertMetricFamilySample().

It's weird to check the sample size is one and still pass the list of samples to assertMetricFamilySample().

Same in YammerMetricsCollectorTest.

Copy link

@k-wall k-wall left a comment

Choose a reason for hiding this comment

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

lgtm, thank you @OwenCorrigan76

Copy link
Member

@scholzj scholzj left a comment

Choose a reason for hiding this comment

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

It would be great if you could provide a bit more details in the Pr description about what and how it does.

LOG.info("Kafka metric {} is allowed", name);
LOG.info("labels " + metricName.tags());
MetricFamilySamples sample = convert(name, metricName.description(), kafkaMetric, metricName.tags());
LOG.info("Kafka metric {} is allowed", prometheusMetricName);
Copy link
Member

Choose a reason for hiding this comment

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

I know this was already here. But do we really need this on INFO level? Maybe DEBUG would be enough?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes we plan to address this in #6

Copy link
Contributor

@mimaison mimaison 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 updates, I think we're almost there. I left a few small suggestions.


/**
* Helper class to convert Kafka metrics into the Prometheus format.
*/
public class MetricFamilySamplesBuilder {

private static final Logger LOG = LoggerFactory.getLogger(KafkaMetricsCollector.class.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

KafkaMetricsCollector -> MetricFamilySamplesBuilder

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Silly mistake. Fixed

labels = new HashMap<>();
labels.put("key", "value");
}
private final Map<String, String> labels = Map.of("key", "value");
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment on lines 92 to 93
assertEquals("kafka_server_group_name", metricFamilySamples.name);
assertEquals(1, metricFamilySamples.samples.size());
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be more idiomatic to either check the size in assertMetricFamilySample(), or pass the unique sample (metricFamilySamples.samples.get(0)) to assertMetricFamilySample().

It's weird to check the sample size is one and still pass the list of samples to assertMetricFamilySample().

Same in YammerMetricsCollectorTest.

@@ -90,8 +113,8 @@ private KafkaMetric buildMetric(String name, String group, double value) {
time);
}

private KafkaMetric buildNonNumericMetric(String name, String group) {
Gauge<String> measurable = (config, now) -> "hello";
private KafkaMetric buildNonNumericMetric(String name, String group, String nonNumericValue) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: this can be just value. It's type String, so we know it's not numeric.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored

@OwenCorrigan76
Copy link
Contributor Author

@scholzj Is the PR description better? Thanks

Copy link
Contributor

@mimaison mimaison 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 implementing this feature and addressing all the comments!

There are still a couple of things not quite right in the tests (for example we access the first item before checking the collection size is 1 in assertMetricFamilySample()) but we can address them in follow up PRs.

LGTM

@mimaison mimaison merged commit 2e542e9 into strimzi:main Jun 21, 2024
7 checks passed
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.

4 participants