From 7c2f8b57f1ce5f4616f17770c042cc22741eed15 Mon Sep 17 00:00:00 2001 From: vinci <1552443053@qq.com> Date: Mon, 2 Dec 2024 01:38:20 +0800 Subject: [PATCH] add an online parser for prometheus, which replaces org.apache.hertzbeat.collector.collect.prometheus.parser.TextParser.textToMetricFamilies --- .../prometheus/parser/OnlineParser.java | 105 ++++++++++++------ 1 file changed, 69 insertions(+), 36 deletions(-) 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 10741cee53c..ccdd0e8e361 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 @@ -22,7 +22,9 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -108,6 +110,20 @@ private CharChecker maybeEol() { return this; } + private CharChecker maybeDouble() { + if ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || i == '-' || i == '+' || i == 'e' || i == '.') { + satisfied = true; + } + return this; + } + + private CharChecker maybeLong() { + if (i >= '0' && i <= '9') { + satisfied = true; + } + return this; + } + private int noElse() throws FormatException { if (!satisfied) { throw new FormatException(); @@ -118,7 +134,6 @@ private int noElse() throws FormatException { private int getInt() throws FormatException { return this.i; } - } @@ -127,19 +142,18 @@ private static CharChecker parseOneChar(InputStream inputStream) throws IOExcept return new CharChecker(i); } - private static CharChecker parseOneWord(InputStream inputStream, StringBuilder stringBuilder) throws IOException { + private static CharChecker parseOneDouble(InputStream inputStream, StringBuilder stringBuilder) throws IOException { int i = inputStream.read(); - while ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == ':') { + while ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || i == '-' || i == '+' || i == 'e' || i == '.') { stringBuilder.append((char) i); i = inputStream.read(); } return new CharChecker(i); } - private static CharChecker parseOneDouble(InputStream inputStream, StringBuilder stringBuilder) throws IOException { + private static CharChecker skipOneLong(InputStream inputStream) throws IOException { int i = inputStream.read(); - while ((i >= '0' && i <= '9') || (i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || i == '-' || i == '+' || i == 'e' || i == '.') { - stringBuilder.append((char) i); + while (i >= '0' && i <= '9') { i = inputStream.read(); } return new CharChecker(i); @@ -163,18 +177,25 @@ private static CharChecker parseLabelName(InputStream inputStream, StringBuilder return new CharChecker(i); } - private static CharChecker parseLabelValue(InputStream inputStream, StringBuilder stringBuilder) throws IOException { + private static CharChecker parseLabelValue(InputStream inputStream, StringBuilder stringBuilder) throws IOException, FormatException { int i = inputStream.read(); while (i != '"' && i != -1) { - stringBuilder.append((char) i); - i = inputStream.read(); - } - return new CharChecker(i); - } - - private static CharChecker skipOneWord(InputStream inputStream) throws IOException { - int i = inputStream.read(); - while ((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == ':') { + if (i == '\\') { + i = inputStream.read(); + switch (i) { + case 'n': + stringBuilder.append('\n'); + case '\\': + stringBuilder.append('\\'); + case '\"': + stringBuilder.append('\"'); + default: + throw new FormatException(); + } + } + else { + stringBuilder.append((char) i); + } i = inputStream.read(); } return new CharChecker(i); @@ -214,26 +235,31 @@ private static Double toDouble(String string) throws FormatException { } } - - - private static CharChecker skipCommentLine(InputStream inputStream) throws IOException, FormatException { - // skip space after '#' - int i = skipToLineEnd(inputStream).maybeEol().maybeEof().noElse(); - return new CharChecker(i); - } - private static CharChecker parseLabels(InputStream inputStream, StringBuilder stringBuilder, List labelList) throws IOException, FormatException { int i; while (true) { MetricFamily.Label label = new MetricFamily.Label(); - parseLabelName(inputStream, stringBuilder).maybeEqualsSign().noElse(); + i = skipSpaces(inputStream).getInt(); + stringBuilder.append((char) i); + i = parseLabelName(inputStream, stringBuilder).maybeSpace().maybeEqualsSign().noElse(); label.setName(stringBuilder.toString()); stringBuilder.delete(0, stringBuilder.length()); - parseOneChar(inputStream).maybeQuotationMark().noElse(); + if (i == ' ') { + skipSpaces(inputStream).maybeEqualsSign().noElse(); + } + + i = parseOneChar(inputStream).maybeSpace().maybeQuotationMark().noElse(); + if (i == ' ') { + skipSpaces(inputStream).maybeEqualsSign().noElse(); + } parseLabelValue(inputStream, stringBuilder).maybeQuotationMark().noElse(); - label.setValue(stringBuilder.toString()); + String labelValue = stringBuilder.toString(); + if (!labelValue.equals(new String(labelValue.getBytes(StandardCharsets.UTF_8)))) { + throw new FormatException(); + } + label.setValue(labelValue); stringBuilder.delete(0, stringBuilder.length()); i = parseOneChar(inputStream).maybeComma().maybeRightBracket().noElse(); @@ -252,7 +278,7 @@ private static CharChecker parseMetric(InputStream inputStream, Map()); metricFamily.setName(metricName); @@ -262,26 +288,33 @@ private static CharChecker parseMetric(InputStream inputStream, Map labelList = new ArrayList<>(); + List labelList = new LinkedList<>(); parseLabels(inputStream, stringBuilder, labelList); metric.setLabels(labelList); + i = skipSpaces(inputStream).getInt(); } stringBuilder.delete(0, stringBuilder.length()); - i = skipSpaces(inputStream).getInt(); stringBuilder.append((char) i); - i = parseOneDouble(inputStream, stringBuilder).maybeSpace().maybeEol().maybeEof().noElse(); metric.setValue(toDouble(stringBuilder.toString())); - stringBuilder.delete(0, stringBuilder.length()); - if (i == '\n') { + if (i == '\n' || i == -1) { metricFamily.getMetricList().add(metric); return new CharChecker(i); } i = skipSpaces(inputStream).getInt(); - i = skipOneWord(inputStream).maybeSpace().maybeEol().maybeEof().noElse(); + stringBuilder.delete(0, stringBuilder.length()); + stringBuilder.append((char) i); + i = skipOneLong(inputStream).maybeSpace().maybeEol().maybeEof().noElse(); + if (i == '\n' || i == -1) { + metricFamily.getMetricList().add(metric); + return new CharChecker(i); + } i = skipSpaces(inputStream).maybeEol().maybeEof().noElse(); metricFamily.getMetricList().add(metric); @@ -293,8 +326,8 @@ public static Map parseMetrics(InputStream inputStream) th int i = inputStream.read(); try { while (i != -1) { - if (i == '#') { - skipCommentLine(inputStream); + if (i == '#' || i == '\n') { + skipToLineEnd(inputStream).maybeEol().maybeEof().noElse(); } else { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append((char) i);