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

Add warning log when duplicate leables are created or detected #29

Merged
merged 6 commits into from
Jul 16, 2024

Conversation

OwenCorrigan76
Copy link
Contributor

The logic that handles non-numeric metrics is in the DataPointSnapshotBuilder class. Here is where a new label with a metric value is created.
Currently we unconditionally add our new label without checking if a label with the same name exists already.
This PR logs a warning if duplicate labes are detected rather than throwing an IllegalArgumentException

@OwenCorrigan76 OwenCorrigan76 added this to the 0.1.0 milestone Jul 8, 2024
@OwenCorrigan76
Copy link
Contributor Author

@mimaison I've refactored the infoDataPoint to use the contains method. This takes care of the newly created labels right?
Is it in gaugeDataPoint that I should handle already existing lables?

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 PR. I left a few suggestions. This also does not currently address the first issue identified in #22 (comment)

@@ -12,20 +12,30 @@
import io.prometheus.metrics.model.snapshots.Quantiles;
import io.prometheus.metrics.model.snapshots.SummarySnapshot;

import java.util.logging.Logger;
Copy link
Contributor

Choose a reason for hiding this comment

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

We should use org.slf4j.Logger instead of java.util.logging.Logger

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's why I couldn't use interpolation with {}. I was using the java.util logger. Changed to sl4j

public static InfoSnapshot.InfoDataPointSnapshot infoDataPoint(Labels labels, Object value, String metricName) {
Labels newLabels = labels.add(PrometheusNaming.sanitizeLabelName(metricName), String.valueOf(value));
String sanitizedMetricName = PrometheusNaming.sanitizeLabelName(metricName);
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 naming this newLabelName would better describe its use.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to 'newLabelName`

String sanitizedMetricName = PrometheusNaming.sanitizeLabelName(metricName);
Labels newLabels = labels;
if (labels.contains(sanitizedMetricName)) {
LOG.warning("Ignoring metric value duplicate key: " + sanitizedMetricName);
Copy link
Contributor

Choose a reason for hiding this comment

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

It's probably worth print a bit more information such as the metric name so operators can identify the culprit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also we should not use concatenation in log lines but instead use interpolation with the {} syntax which is possible with the slf4j Logger

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 appended from metric; metricName. Is that sufficient.
{} interpolation now used

@@ -108,6 +109,19 @@ public void testCollectNonNumericMetric() {
assertEquals(expectedLabels, snapshot.getDataPoints().get(0).getLabels());
}

@Test
public void testLabelNameSanitizing() {
Copy link
Contributor

Choose a reason for hiding this comment

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

We want to avoid tests that only exercise code from dependencies. This test only validates PrometheusNaming.sanitizeLabelName() and it does not check anything from our metric reporter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

@Test
public void testLabelDuplicateWarning() {
Labels labels = Labels.builder().label("k1", "v1").build();
InfoSnapshot.InfoDataPointSnapshot snapshot = DataPointSnapshotBuilder.infoDataPoint(labels, "v1", "k1");
Copy link
Contributor

Choose a reason for hiding this comment

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

We should use a different value than v1 here. Otherwise this does not assert we did not replace the value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I missed that. Changed to just value.

}

@Test
public void testLabelDuplicateWarning() {
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 we should put this test in a new class DataPointSnapshotBuilderTest

Copy link
Contributor Author

Choose a reason for hiding this comment

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

New DataPointSnapshotBuilderTest class created and this test is moved to there

@mimaison
Copy link
Contributor

mimaison commented Jul 8, 2024

@mimaison I've refactored the infoDataPoint to use the contains method. This takes care of the newly created labels right? Is it in gaugeDataPoint that I should handle already existing lables?

No, it's in the 2 places where we create Labels objects:

@OwenCorrigan76 OwenCorrigan76 requested a review from mimaison July 10, 2024 10:22
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! It looks good overall. I left a few minor suggestions.

String newLabelName = PrometheusNaming.sanitizeLabelName(metricName);
Labels newLabels = labels;
if (labels.contains(newLabelName)) {
LOG.warn("Ignoring metric value duplicate key: {} from metric: {}", newLabelName, metricName);
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it would be worth checking the value of the existing label and only print the warning if the value is different from value. WDYT?

Can we also improve the message? We're not ignoring the metric value, we're unable to add a new label.

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. Is the new message ok?

@@ -122,10 +124,16 @@ private String metricName(MetricName metricName) {
.toLowerCase(Locale.ROOT);
}

private static Labels labelsFromTags(Map<String, String> tags) {
protected static Labels labelsFromTags(Map<String, String> tags) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need protected, we don't expect subclasses

Copy link
Contributor Author

@OwenCorrigan76 OwenCorrigan76 Jul 11, 2024

Choose a reason for hiding this comment

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

@mimaison I'm calling labelsFromTags in the test:

@Test
   public void testLabelsFromTags() {
       Map<String, String> tags = new LinkedHashMap<>();
       tags.put("k-1", "v1");
       tags.put("k_1", "v2");

       Labels labels = KafkaMetricsCollector.labelsFromTags(tags);
       assertEquals("k_1", PrometheusNaming.sanitizeLabelName("k-1"));
       assertEquals("v1", labels.get("k_1"));
       assertEquals(1, labels.size());
   }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there another way around this? Thanks

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm calling labelsFromTags in the test
How is this an issue?

Have you tried removing protected and see what happens?
You may want to review https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

Copy link
Contributor Author

@OwenCorrigan76 OwenCorrigan76 Jul 11, 2024

Choose a reason for hiding this comment

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

Yes it goes to package-private. I misunderstood your comment. I thought you wanted to keep it as private and maybe had forgotten I was calling it from the test. My bad!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed protected

if (labelNames.add(newLabelName)) {
builder.label(newLabelName, label.getValue());
} else {
LOG.warn("Ignoring duplicate label key: {} with value: {}", newLabelName, label.getValue());
Copy link
Contributor

Choose a reason for hiding this comment

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

If wonder if it's worth passing the metric name so the message helps identify the impacted metric.

Same in YammerMetricsCollector.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Metric name passed and added to the LOG

@Test
public void testNewLabelDuplicateWarning() {
Labels labels = Labels.builder().label("k1", "v1").label("k2", "v2").build();
InfoSnapshot.InfoDataPointSnapshot snapshot = DataPointSnapshotBuilder.infoDataPoint(labels, "value", "k1");
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 interesting to also test with labels that are not equal but collide when turned into Prometheus labels, for example k-1 and k_1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just like in the other tests?
assertEquals("k_1", PrometheusNaming.sanitizeLabelName("k-1"));

Copy link
Contributor

Choose a reason for hiding this comment

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

No, I mean using label names in Labels.builder().label() and DataPointSnapshotBuilder.infoDataPoint() that are not equal but collide. Currently we use k1 in both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to also test with labels that are not equal but collide when turned into Prometheus labels

public class DataPointSnapshotBuilderTest {

@Test
public void testNewLabelDuplicateWarning() {
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 a better name would be something like testCollidingNewLabelIsIgnored

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to testCollidingNewLabelIsIgnored

@mimaison
Copy link
Contributor

@OwenCorrigan76
Copy link
Contributor Author

Sorry, didn't do a mvn compile .Fixing now.

Signed-off-by: Owen <[email protected]>
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 PR! LGTM

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.

One nit. LGTM otherwise.

@mimaison mimaison merged commit 210e4d0 into strimzi:main Jul 16, 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.

3 participants