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

zhaoqingran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new 5746cbbbd [improve] Prometheus streaming parsing supports CRLF (#3745)
5746cbbbd is described below

commit 5746cbbbd755690f9c673dae3f805829715128c0
Author: Duansg <siguod...@gmail.com>
AuthorDate: Fri Sep 5 00:52:33 2025 +0800

    [improve] Prometheus streaming parsing supports CRLF (#3745)
---
 .../collect/prometheus/parser/OnlineParser.java    |   8 +
 .../prometheus/parser/OnlineParserTest.java        | 182 +++++++++++++++++++++
 2 files changed, 190 insertions(+)

diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParser.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParser.java
index cfc87527c..60571ee78 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParser.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParser.java
@@ -185,6 +185,10 @@ public class OnlineParser {
             stringBuilder.append((char) i);
             i = getChar(inputStream);
         }
+        // Skip \r character to handle Windows line endings
+        if (i == '\r') {
+            i = getChar(inputStream);
+        }
         return new CharChecker(i);
     }
 
@@ -193,6 +197,10 @@ public class OnlineParser {
         while (i >= '0' && i <= '9') {
             i = getChar(inputStream);
         }
+        // Skip \r character to handle Windows line endings
+        if (i == '\r') {
+            i = getChar(inputStream);
+        }
         return new CharChecker(i);
     }
 
diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParserTest.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParserTest.java
index cac930206..de8775135 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParserTest.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/prometheus/parser/OnlineParserTest.java
@@ -105,4 +105,186 @@ class OnlineParserTest {
             });
         });
     }
+
+    @Test
+    void testParseMetricsWithCrLf() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\r\n"
+                + "# TYPE go_gc_duration_seconds summary\r\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0\r\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139\r\n";
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+
+        str = "# HELP go_gc_duration_seconds A summary of the pause duration 
of garbage collection cycles.\r\n"
+                + "# TYPE go_gc_duration_seconds summary\r\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0 1234567890\r\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139 1234567890\r\n";
+        inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        metricFamilyMap = OnlineParser.parseMetrics(inputStream);
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        metricFamily = metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        metricFamily1 = metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+    }
+
+    @Test
+    void testParseMetricsWithLf() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\n"
+                + "# TYPE go_gc_duration_seconds summary\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139\n";
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+
+        str = "# HELP go_gc_duration_seconds A summary of the pause duration 
of garbage collection cycles.\n"
+                + "# TYPE go_gc_duration_seconds summary\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0 1234567890\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139 1234567890\n";
+        inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        metricFamilyMap = OnlineParser.parseMetrics(inputStream);
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        metricFamily = metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        metricFamily1 = metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+    }
+
+    @Test
+    void testParseMetricsWithoutFinalNewline() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\r\n"
+                + "# TYPE go_gc_duration_seconds summary\r\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0\r\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139";
+
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+
+        str = "# HELP go_gc_duration_seconds A summary of the pause duration 
of garbage collection cycles.\n"
+                + "# TYPE go_gc_duration_seconds summary\n"
+                + "jvm_gc_pause_seconds_count{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 1.0\n"
+                + "jvm_gc_pause_seconds_sum{action=\"end of major 
GC\",cause=\"Metadata GC Threshold\",} 0.139";
+
+        inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        metricFamilyMap = OnlineParser.parseMetrics(inputStream);
+
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        metricFamily = metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        metricFamily1 = metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+    }
+
+    @Test
+    void testParseMetricsWithEmptyLabelsAndCrLf() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\r\n"
+                + "# TYPE go_gc_duration_seconds summary\r\n"
+                + "jvm_gc_pause_seconds_count 1.0\r\n"
+                + "jvm_gc_pause_seconds_sum{} 0.139";
+
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+
+    }
+
+    @Test
+    void testParseMetricsWithEmptyLabelsAndLf() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\n"
+                + "# TYPE go_gc_duration_seconds summary\n"
+                + "jvm_gc_pause_seconds_count 1.0\n"
+                + "jvm_gc_pause_seconds_sum{} 0.139";
+
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+    }
+
+    @Test
+    void testParseMetricsWithMixedLineEndings() throws Exception {
+        String str = "# HELP go_gc_duration_seconds A summary of the pause 
duration of garbage collection cycles.\r\n"
+                + "# TYPE go_gc_duration_seconds summary\n"
+                + "jvm_gc_pause_seconds_count 1.0\n"
+                + "jvm_gc_pause_seconds_sum{} 0.139\r\n";
+
+        InputStream inputStream = new 
ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
+
+        assertNotNull(metricFamilyMap);
+        assertEquals(2, metricFamilyMap.values().size());
+
+        MetricFamily metricFamily = 
metricFamilyMap.get("jvm_gc_pause_seconds_count");
+        assertEquals("jvm_gc_pause_seconds_count", metricFamily.getName());
+        assertEquals(1.0, metricFamily.getMetricList().get(0).getValue());
+
+        MetricFamily metricFamily1 = 
metricFamilyMap.get("jvm_gc_pause_seconds_sum");
+        assertEquals("jvm_gc_pause_seconds_sum", metricFamily1.getName());
+        assertEquals(0.139, metricFamily1.getMetricList().get(0).getValue());
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@hertzbeat.apache.org
For additional commands, e-mail: notifications-h...@hertzbeat.apache.org

Reply via email to