This is an automated email from the ASF dual-hosted git repository.

mchades pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 1ba2633891 [#8750] Bugfix(metrics): sanitize gravitino-catalog metrics 
(#8751)
1ba2633891 is described below

commit 1ba263389168ba623d5b16b4644a176f0b55e8d3
Author: Junda Yang <[email protected]>
AuthorDate: Wed Oct 8 20:15:01 2025 -0700

    [#8750] Bugfix(metrics): sanitize gravitino-catalog metrics (#8751)
    
    ### What changes were proposed in this pull request?
    
    Santinize all gravitino-catalog metrics
    
    ### Why are the changes needed?
    
    Example gravitino-catalog metric from /prometheus/metrics endpoint:
    ```
    # TYPE gravitino-catalog_fileset-cache_loads-success summary
    
gravitino-catalog_fileset-cache_loads-success{provider="fileset",metalake="uber",catalog="ma",quantile="0.5",}
 0.015295218000000001
    ```
    which contains hyphen (-).
    
    It does not conform prometheus standard -
    
https://github.com/apache/gravitino/blob/caee8d20f5129dc22b7b3e7290091f619f590cbc/core/src/main/java/org/apache/gravitino/metrics/MetricsSystem.java#L189-L195
    
    It causes errors when we parse the metrics from the endpoint.
    
    Fix: #8750
    
    ### Does this PR introduce _any_ user-facing change?
    
    No
    
    ### How was this patch tested?
    
    Unit test added
---
 .../gravitino/metrics/GravitinoSampleBuilder.java  |   8 +-
 .../metrics/TestGravitinoSampleBuilder.java        | 115 ++++++++++++++++++++-
 2 files changed, 115 insertions(+), 8 deletions(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/metrics/GravitinoSampleBuilder.java 
b/core/src/main/java/org/apache/gravitino/metrics/GravitinoSampleBuilder.java
index 5f4b7f7982..54420913f3 100644
--- 
a/core/src/main/java/org/apache/gravitino/metrics/GravitinoSampleBuilder.java
+++ 
b/core/src/main/java/org/apache/gravitino/metrics/GravitinoSampleBuilder.java
@@ -82,10 +82,10 @@ public class GravitinoSampleBuilder extends 
CustomMappingSampleBuilder {
       String provider = matcher.group(1);
       String metalake = matcher.group(2);
       String catalog = matcher.group(3);
-      // Replace '.' with '_' in the remaining part to conform to Prometheus 
naming conventions
-      String metricNameRest = matcher.group(4).replace('.', '_');
-
-      String prometheusName = GRAVITINO_CATALOG_METRIC_PREFIX + "_" + 
metricNameRest;
+      // Use Prometheus client's sanitization to conform to naming conventions
+      String metricNameRest = Collector.sanitizeMetricName(matcher.group(4));
+      String sanitizedPrefix = 
Collector.sanitizeMetricName(GRAVITINO_CATALOG_METRIC_PREFIX);
+      String prometheusName = sanitizedPrefix + "_" + metricNameRest;
 
       List<String> labelNames = new ArrayList<>();
       labelNames.add("provider");
diff --git 
a/core/src/test/java/org/apache/gravitino/metrics/TestGravitinoSampleBuilder.java
 
b/core/src/test/java/org/apache/gravitino/metrics/TestGravitinoSampleBuilder.java
index 0adc3772d9..3a6941fe17 100644
--- 
a/core/src/test/java/org/apache/gravitino/metrics/TestGravitinoSampleBuilder.java
+++ 
b/core/src/test/java/org/apache/gravitino/metrics/TestGravitinoSampleBuilder.java
@@ -18,8 +18,6 @@
  */
 package org.apache.gravitino.metrics;
 
-import static 
org.apache.gravitino.metrics.source.MetricsSource.GRAVITINO_CATALOG_METRIC_PREFIX;
-
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import io.prometheus.client.Collector;
@@ -52,7 +50,7 @@ public class TestGravitinoSampleBuilder {
         sampleBuilder.createSample(
             dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
 
-    Assertions.assertEquals(GRAVITINO_CATALOG_METRIC_PREFIX + 
"_some_metric_count", sample.name);
+    Assertions.assertEquals("gravitino_catalog_some_metric_count", 
sample.name);
     Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
     Assertions.assertEquals(ImmutableList.of("hive", "metalake1", "catalog1"), 
sample.labelValues);
     Assertions.assertEquals(value, sample.value);
@@ -69,7 +67,7 @@ public class TestGravitinoSampleBuilder {
         sampleBuilder.createSample(
             dropwizardName, "", additionalLabelNames, additionalLabelValues, 
value);
 
-    Assertions.assertEquals(GRAVITINO_CATALOG_METRIC_PREFIX + 
"_another_metric", sample.name);
+    Assertions.assertEquals("gravitino_catalog_another_metric", sample.name);
     Assertions.assertEquals(
         ImmutableList.of("provider", "metalake", "catalog", "type"), 
sample.labelNames);
     Assertions.assertEquals(
@@ -106,4 +104,113 @@ public class TestGravitinoSampleBuilder {
     Assertions.assertTrue(sample.labelValues.isEmpty());
     Assertions.assertEquals(value, sample.value);
   }
+
+  @Test
+  public void testCreateSampleWithHyphensInMetricNameRest() {
+    String dropwizardName = 
"gravitino-catalog.fileset.metalake1.catalog1.schema-cache.hit-count";
+    double value = 50.0;
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
+
+    // Both prefix and metricNameRest should have hyphens converted to 
underscores
+    Assertions.assertEquals("gravitino_catalog_schema_cache_hit_count", 
sample.name);
+    Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
+    Assertions.assertEquals(
+        ImmutableList.of("fileset", "metalake1", "catalog1"), 
sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
+
+  @Test
+  public void testCreateSampleWithFilesetCacheMetric() {
+    String dropwizardName =
+        
"gravitino-catalog.fileset.test-metalake.test-catalog.fileset-cache.miss-count";
+    double value = 15.0;
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
+
+    // All hyphens should be converted to underscores
+    Assertions.assertEquals("gravitino_catalog_fileset_cache_miss_count", 
sample.name);
+    Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
+    Assertions.assertEquals(
+        ImmutableList.of("fileset", "test-metalake", "test-catalog"), 
sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
+
+  @Test
+  public void testCreateSampleWithMultipleHyphensAndDots() {
+    String dropwizardName =
+        
"gravitino-catalog.hive.my-metalake.my-catalog.complex-metric-name.sub-component.total";
+    double value = 100.0;
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
+
+    // All dots and hyphens in metricNameRest should be converted to 
underscores
+    Assertions.assertEquals(
+        "gravitino_catalog_complex_metric_name_sub_component_total", 
sample.name);
+    Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
+    Assertions.assertEquals(
+        ImmutableList.of("hive", "my-metalake", "my-catalog"), 
sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
+
+  @Test
+  public void testCreateSampleWithOnlyHyphensInMetricName() {
+    String dropwizardName = 
"gravitino-catalog.jdbc.metalake.catalog.http-request-duration";
+    double value = 0.5;
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
+
+    // Hyphens in metricNameRest should be converted to underscores
+    Assertions.assertEquals("gravitino_catalog_http_request_duration", 
sample.name);
+    Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
+    Assertions.assertEquals(ImmutableList.of("jdbc", "metalake", "catalog"), 
sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
+
+  @Test
+  public void testCreateSampleWithMixedSpecialCharacters() {
+    String dropwizardName = 
"gravitino-catalog.model.test.example.cache-stats.hit-ratio.avg";
+    double value = 0.85;
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", Collections.emptyList(), 
Collections.emptyList(), value);
+
+    // Both dots and hyphens should be converted to underscores
+    Assertions.assertEquals("gravitino_catalog_cache_stats_hit_ratio_avg", 
sample.name);
+    Assertions.assertEquals(ImmutableList.of("provider", "metalake", 
"catalog"), sample.labelNames);
+    Assertions.assertEquals(ImmutableList.of("model", "test", "example"), 
sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
+
+  @Test
+  public void testCreateSampleWithAdditionalLabelsAndHyphens() {
+    String dropwizardName =
+        
"gravitino-catalog.fileset.prod-metalake.main-catalog.schema-cache.eviction-count";
+    double value = 25.0;
+    List<String> additionalLabelNames = ImmutableList.of("cache-type", 
"operation-mode");
+    List<String> additionalLabelValues = ImmutableList.of("lru", "async");
+
+    Collector.MetricFamilySamples.Sample sample =
+        sampleBuilder.createSample(
+            dropwizardName, "", additionalLabelNames, additionalLabelValues, 
value);
+
+    // Metric name should have all hyphens converted to underscores
+    Assertions.assertEquals("gravitino_catalog_schema_cache_eviction_count", 
sample.name);
+    Assertions.assertEquals(
+        ImmutableList.of("provider", "metalake", "catalog", "cache-type", 
"operation-mode"),
+        sample.labelNames);
+    Assertions.assertEquals(
+        ImmutableList.of("fileset", "prod-metalake", "main-catalog", "lru", 
"async"),
+        sample.labelValues);
+    Assertions.assertEquals(value, sample.value);
+  }
 }

Reply via email to