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