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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]