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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 7dd24f917e1 [improvement](metrics) Unify build version metric labels 
#68655 (#68656)
7dd24f917e1 is described below

commit 7dd24f917e16c070e92f5847d27127ebeb05ede6
Author: Gavin Chou <[email protected]>
AuthorDate: Fri Oct 9 14:44:24 2026 +0800

    [improvement](metrics) Unify build version metric labels #68655 (#68656)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Related PR: #68655
    
    Problem Summary:
    
    Backport #68655 to `branch-4.1`. FE already exposes its build identity
    with `version`, `major`, `minor`, `patch`, `hotfix`, and `short_hash`
    labels. BE and Cloud expose the same numeric version value without those
    labels, even though the decimal concatenation is ambiguous for some
    versions and does not include RC or revision information.
    
    This change adds the same fixed label schema to the existing BE and
    Cloud metrics while preserving all three metric names and their numeric
    values. The version metrics still produce one series per process, so the
    fixed build labels do not introduce runtime-dependent cardinality. The
    regression case verifies that FE, BE, and Cloud expose identical build
    metadata and values.
    
    ### Release note
    
    Expose consistent build-version labels on FE, BE, and Cloud version
    metrics.
    
    ### Check List (For Author)
    
    - Test: Added regression coverage; ran `build-support/check-format.sh`,
    `git diff --check`, and a focused C++ syntax check for the labeled bvar
    construction.
    - Behavior changed: Yes. Existing BE and Cloud version metric series now
    include fixed build-version labels; metric names and numeric values are
    unchanged.
    - Does this need documentation: No.
---
 be/src/common/config.cpp                           |  4 ++
 be/src/common/config.h                             |  3 +
 be/src/service/doris_main.cpp                      |  2 +
 be/src/util/debug_util.cpp                         | 39 +++++++++++-
 be/src/util/debug_util.h                           |  4 ++
 be/test/util/debug_util_test.cpp                   | 63 +++++++++++++++++++
 cloud/src/common/CMakeLists.txt                    |  1 +
 cloud/src/common/version_metrics.cpp               | 72 ++++++++++++++++++++++
 cloud/src/common/version_metrics.h                 | 26 ++++++++
 cloud/src/main.cpp                                 | 16 +----
 cloud/test/metric_test.cpp                         | 37 +++++++++++
 .../java/org/apache/doris/metric/MetricsTest.java  | 24 ++++++++
 .../suites/metrics_p0/test_version_metrics.groovy  | 51 +++++++++------
 13 files changed, 308 insertions(+), 34 deletions(-)

diff --git a/be/src/common/config.cpp b/be/src/common/config.cpp
index 4b0ead5a7a8..0e34b88d708 100644
--- a/be/src/common/config.cpp
+++ b/be/src/common/config.cpp
@@ -109,6 +109,10 @@ DEFINE_Int32(brpc_num_threads, "256");
 // the default value is set to -1, which means never close idle connection.
 DEFINE_Int32(brpc_idle_timeout_sec, "-1");
 
+// Maximum number of multi-dimensional bvar samples exported by /brpc_metrics.
+// brpc 1.4 defaults this flag to 0, which disables all MultiDimension metrics.
+DEFINE_String(bvar_max_dump_multi_dimension_metric_num, "5000");
+
 // Declare a selection strategy for those servers have many ips.
 // Note that there should at most one ip match this list.
 // this is a list in semicolon-delimited format, in CIDR notation, e.g. 
10.10.10.0/24
diff --git a/be/src/common/config.h b/be/src/common/config.h
index 94a9fd88f86..3931b11efed 100644
--- a/be/src/common/config.h
+++ b/be/src/common/config.h
@@ -157,6 +157,9 @@ DECLARE_Int32(arrow_flight_sql_proxy_port);
 DECLARE_Int32(brpc_num_threads);
 DECLARE_Int32(brpc_idle_timeout_sec);
 
+// Maximum number of multi-dimensional bvar samples exported by /brpc_metrics.
+DECLARE_String(bvar_max_dump_multi_dimension_metric_num);
+
 // Declare a selection strategy for those servers have many ips.
 // Note that there should at most one ip match this list.
 // This is a list in semicolon-delimited format, in CIDR notation, e.g. 
10.10.10.0/24
diff --git a/be/src/service/doris_main.cpp b/be/src/service/doris_main.cpp
index 2f31e3055a0..8ec1da32f08 100644
--- a/be/src/service/doris_main.cpp
+++ b/be/src/service/doris_main.cpp
@@ -413,6 +413,8 @@ int main(int argc, char** argv) {
         return -1;
     }
 
+    doris::init_be_version_metrics();
+
     // ATTN: Callers that want to override default gflags variables should do 
so before calling this method
     google::ParseCommandLineFlags(&argc, &argv, true);
     // ATTN: MUST init before LOG
diff --git a/be/src/util/debug_util.cpp b/be/src/util/debug_util.cpp
index b98dd76967b..7362788c169 100644
--- a/be/src/util/debug_util.cpp
+++ b/be/src/util/debug_util.cpp
@@ -18,16 +18,23 @@
 #include "util/debug_util.h"
 
 #include <bvar/bvar.h>
+#include <bvar/multi_dimension.h>
 #include <gen_cpp/HeartbeatService_types.h>
 #include <gen_cpp/PlanNodes_types.h>
+#include <gflags/gflags.h>
 #include <stdint.h>
 
+#include <cstdlib>
 #include <cstring>
 #include <iomanip>
+#include <list>
 #include <map>
 #include <sstream> // IWYU pragma: keep
+#include <string>
 #include <utility>
 
+#include "common/check.h"
+#include "common/config.h"
 #include "common/version_internal.h"
 #include "fmt/core.h"
 #include "util/uid_util.h"
@@ -109,7 +116,9 @@ std::string hexdump(const char* buf, int len) {
     return ss.str();
 }
 
-bvar::Status<uint64_t> be_version_metrics("doris_be_version", [] {
+namespace {
+
+uint64_t get_be_version_metric_value() {
     std::stringstream ss;
     ss << version::doris_build_version_major() << 0 << 
version::doris_build_version_minor() << 0
        << version::doris_build_version_patch();
@@ -117,7 +126,33 @@ bvar::Status<uint64_t> 
be_version_metrics("doris_be_version", [] {
         ss << 0 << version::doris_build_version_hotfix();
     }
     return std::strtoul(ss.str().c_str(), nullptr, 10);
-}());
+}
+
+} // namespace
+
+void init_be_version_metrics() {
+    // MultiDimension metrics are omitted from /brpc_metrics while this brpc 
flag is 0.
+    DORIS_CHECK(
+            
!google::SetCommandLineOption("bvar_max_dump_multi_dimension_metric_number",
+                                          
config::bvar_max_dump_multi_dimension_metric_num.c_str())
+                     .empty());
+
+    static const bool initialized = [] {
+        static bvar::MultiDimension<bvar::Status<uint64_t>> metrics(
+                "doris_be_version", {"version", "major", "minor", "patch", 
"hotfix", "short_hash"});
+        auto* metric = metrics.get_stats(
+                std::list<std::string> {version::doris_build_version(),
+                                        
std::to_string(version::doris_build_version_major()),
+                                        
std::to_string(version::doris_build_version_minor()),
+                                        
std::to_string(version::doris_build_version_patch()),
+                                        
std::to_string(version::doris_build_version_hotfix()),
+                                        version::doris_build_short_hash()});
+        DORIS_CHECK(metric != nullptr);
+        metric->set_value(get_be_version_metric_value());
+        return true;
+    }();
+    static_cast<void>(initialized);
+}
 
 std::string PrintThriftNetworkAddress(const TNetworkAddress& add) {
     std::stringstream ss;
diff --git a/be/src/util/debug_util.h b/be/src/util/debug_util.h
index 19485ca07d2..5fad41ec637 100644
--- a/be/src/util/debug_util.h
+++ b/be/src/util/debug_util.h
@@ -50,6 +50,10 @@ std::string get_short_version();
 // Returns "<program short name> version <GetBuildVersion(compact)>"
 std::string get_version_string(bool compact);
 
+// Enables multi-dimensional bvar export and registers doris_be_version.
+// This must run before the brpc server starts.
+void init_be_version_metrics();
+
 std::string hexdump(const char* buf, int len);
 
 } // namespace doris
diff --git a/be/test/util/debug_util_test.cpp b/be/test/util/debug_util_test.cpp
new file mode 100644
index 00000000000..983268a4282
--- /dev/null
+++ b/be/test/util/debug_util_test.cpp
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "util/debug_util.h"
+
+#include <butil/iobuf.h>
+#include <butil/strings/string_piece.h>
+
+// brpc's header uses the butil types above without including their 
definitions.
+#include <brpc/builtin/prometheus_metrics_service.h>
+
+#include <cstdlib>
+#include <sstream>
+#include <string>
+
+#include "common/config.h"
+#include "common/version_internal.h"
+
+namespace doris {
+
+TEST(DebugUtilTest, BeVersionMetricIsExportedWithBuildLabels) {
+    config::bvar_max_dump_multi_dimension_metric_num = "5000";
+    init_be_version_metrics();
+
+    butil::IOBuf output;
+    ASSERT_EQ(0, brpc::DumpPrometheusMetricsToIOBuf(&output));
+    const std::string body = output.to_string();
+
+    std::stringstream value;
+    value << version::doris_build_version_major() << 0 << 
version::doris_build_version_minor() << 0
+          << version::doris_build_version_patch();
+    if (version::doris_build_version_hotfix() > 0) {
+        value << 0 << version::doris_build_version_hotfix();
+    }
+
+    std::stringstream sample;
+    sample << "doris_be_version{version=\"" << version::doris_build_version() 
<< "\",major=\""
+           << version::doris_build_version_major() << "\",minor=\""
+           << version::doris_build_version_minor() << "\",patch=\""
+           << version::doris_build_version_patch() << "\",hotfix=\""
+           << version::doris_build_version_hotfix() << "\",short_hash=\""
+           << version::doris_build_short_hash() << "\"} "
+           << std::strtoull(value.str().c_str(), nullptr, 10);
+
+    EXPECT_NE(std::string::npos, body.find("# TYPE doris_be_version gauge")) 
<< body;
+    EXPECT_NE(std::string::npos, body.find(sample.str())) << body;
+}
+
+} // namespace doris
diff --git a/cloud/src/common/CMakeLists.txt b/cloud/src/common/CMakeLists.txt
index a1b989cace1..9f29e1a183b 100644
--- a/cloud/src/common/CMakeLists.txt
+++ b/cloud/src/common/CMakeLists.txt
@@ -29,6 +29,7 @@ set(COMMON_FILES
     encryption_util.cpp
     http_helper.cpp
     metric.cpp
+    version_metrics.cpp
     kms.cpp
     network_util.cpp
     ../server/oss/cloud_server_starter_factory.cpp
diff --git a/cloud/src/common/version_metrics.cpp 
b/cloud/src/common/version_metrics.cpp
new file mode 100644
index 00000000000..e627c853d3e
--- /dev/null
+++ b/cloud/src/common/version_metrics.cpp
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "common/version_metrics.h"
+
+#include <bvar/bvar.h>
+#include <bvar/multi_dimension.h>
+#include <gen_cpp/cloud_version.h>
+#include <gflags/gflags.h>
+
+#include <cstdint>
+#include <cstdlib>
+#include <list>
+#include <sstream>
+#include <string>
+
+#include "common/config.h"
+
+namespace doris::cloud {
+namespace {
+
+uint64_t get_doris_cloud_version_metric_value() {
+    std::stringstream ss;
+    ss << DORIS_CLOUD_BUILD_VERSION_MAJOR << 0 << 
DORIS_CLOUD_BUILD_VERSION_MINOR << 0
+       << DORIS_CLOUD_BUILD_VERSION_PATCH;
+    if (DORIS_CLOUD_BUILD_VERSION_HOTFIX > 0) {
+        ss << 0 << DORIS_CLOUD_BUILD_VERSION_HOTFIX;
+    }
+    return std::strtoul(ss.str().c_str(), nullptr, 10);
+}
+
+} // namespace
+
+void init_doris_cloud_version_metrics() {
+    // MultiDimension metrics are omitted from /brpc_metrics while this brpc 
flag is 0.
+    
CHECK(!google::SetCommandLineOption("bvar_max_dump_multi_dimension_metric_number",
+                                        
config::bvar_max_dump_multi_dimension_metric_num.c_str())
+                   .empty());
+
+    static const bool initialized = [] {
+        // Keep the metric name role-neutral because one doris_cloud process 
can run meta-service,
+        // recycler, or both. Runtime roles should be represented by scrape 
target labels.
+        static bvar::MultiDimension<bvar::Status<uint64_t>> metrics(
+                "doris_cloud_version",
+                {"version", "major", "minor", "patch", "hotfix", 
"short_hash"});
+        auto* metric = metrics.get_stats(std::list<std::string> {
+                DORIS_CLOUD_BUILD_VERSION, 
std::to_string(DORIS_CLOUD_BUILD_VERSION_MAJOR),
+                std::to_string(DORIS_CLOUD_BUILD_VERSION_MINOR),
+                std::to_string(DORIS_CLOUD_BUILD_VERSION_PATCH),
+                std::to_string(DORIS_CLOUD_BUILD_VERSION_HOTFIX), 
DORIS_CLOUD_BUILD_SHORT_HASH});
+        CHECK(metric != nullptr);
+        metric->set_value(get_doris_cloud_version_metric_value());
+        return true;
+    }();
+    static_cast<void>(initialized);
+}
+
+} // namespace doris::cloud
diff --git a/cloud/src/common/version_metrics.h 
b/cloud/src/common/version_metrics.h
new file mode 100644
index 00000000000..d91b2420136
--- /dev/null
+++ b/cloud/src/common/version_metrics.h
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+namespace doris::cloud {
+
+// Enables multi-dimensional bvar export and registers doris_cloud_version.
+// This must run before the brpc server starts.
+void init_doris_cloud_version_metrics();
+
+} // namespace doris::cloud
diff --git a/cloud/src/main.cpp b/cloud/src/main.cpp
index be8b347fdc9..4e8d28dd580 100644
--- a/cloud/src/main.cpp
+++ b/cloud/src/main.cpp
@@ -30,6 +30,7 @@
 #include <memory>
 #include <mutex>
 #include <sstream>
+#include <string>
 #include <thread>
 
 #include "common/arg_parser.h"
@@ -38,6 +39,7 @@
 #include "common/encryption_util.h"
 #include "common/logging.h"
 #include "common/network_util.h"
+#include "common/version_metrics.h"
 #include "meta-service/meta_server.h"
 #include "meta-store/mem_txn_kv.h"
 #include "meta-store/txn_kv.h"
@@ -151,17 +153,6 @@ static std::string build_info() {
     return ss.str();
 }
 
-// TODO(gavin): add doris cloud role to the metrics name
-bvar::Status<uint64_t> doris_cloud_version_metrics("doris_cloud_version", [] {
-    std::stringstream ss;
-    ss << DORIS_CLOUD_BUILD_VERSION_MAJOR << 0 << 
DORIS_CLOUD_BUILD_VERSION_MINOR << 0
-       << DORIS_CLOUD_BUILD_VERSION_PATCH;
-    if (DORIS_CLOUD_BUILD_VERSION_HOTFIX > 0) {
-        ss << 0 << DORIS_CLOUD_BUILD_VERSION_HOTFIX;
-    }
-    return std::strtoul(ss.str().c_str(), nullptr, 10);
-}());
-
 namespace brpc {
 DECLARE_uint64(max_body_size);
 DECLARE_int64(socket_max_unwritten_bytes);
@@ -245,8 +236,7 @@ int main(int argc, char** argv) {
         std::cerr << "try to start meta_service, recycler" << std::endl;
     }
 
-    google::SetCommandLineOption("bvar_max_dump_multi_dimension_metric_number",
-                                 
config::bvar_max_dump_multi_dimension_metric_num.c_str());
+    init_doris_cloud_version_metrics();
 
     brpc::Server server;
     brpc::FLAGS_max_body_size = config::brpc_max_body_size;
diff --git a/cloud/test/metric_test.cpp b/cloud/test/metric_test.cpp
index e00f62d990e..5b5ecc8cd72 100644
--- a/cloud/test/metric_test.cpp
+++ b/cloud/test/metric_test.cpp
@@ -17,15 +17,24 @@
 
 #include "common/metric.h"
 
+#include <butil/iobuf.h>
+#include <butil/strings/string_piece.h>
+
+// brpc's header uses the butil types above without including their 
definitions.
+#include <brpc/builtin/prometheus_metrics_service.h>
+#include <gen_cpp/cloud_version.h>
 #include <gtest/gtest.h>
 
+#include <cstdlib>
 #include <fstream>
 #include <iostream>
+#include <sstream>
 #include <string>
 #include <thread>
 
 #include "common/bvars.h"
 #include "common/config.h"
+#include "common/version_metrics.h"
 #include "meta-store/mem_txn_kv.h"
 #include "meta-store/txn_kv.h"
 #include "meta-store/txn_kv_error.h"
@@ -35,6 +44,34 @@ int main(int argc, char** argv) {
     return RUN_ALL_TESTS();
 }
 
+TEST(MetricTest, CloudVersionMetricIsExportedWithBuildLabels) {
+    using namespace doris::cloud;
+
+    config::bvar_max_dump_multi_dimension_metric_num = "5000";
+    init_doris_cloud_version_metrics();
+
+    butil::IOBuf output;
+    ASSERT_EQ(0, brpc::DumpPrometheusMetricsToIOBuf(&output));
+    const std::string body = output.to_string();
+
+    std::stringstream value;
+    value << DORIS_CLOUD_BUILD_VERSION_MAJOR << 0 << 
DORIS_CLOUD_BUILD_VERSION_MINOR << 0
+          << DORIS_CLOUD_BUILD_VERSION_PATCH;
+    if (DORIS_CLOUD_BUILD_VERSION_HOTFIX > 0) {
+        value << 0 << DORIS_CLOUD_BUILD_VERSION_HOTFIX;
+    }
+
+    std::stringstream sample;
+    sample << "doris_cloud_version{version=\"" << DORIS_CLOUD_BUILD_VERSION << 
"\",major=\""
+           << DORIS_CLOUD_BUILD_VERSION_MAJOR << "\",minor=\"" << 
DORIS_CLOUD_BUILD_VERSION_MINOR
+           << "\",patch=\"" << DORIS_CLOUD_BUILD_VERSION_PATCH << 
"\",hotfix=\""
+           << DORIS_CLOUD_BUILD_VERSION_HOTFIX << "\",short_hash=\"" << 
DORIS_CLOUD_BUILD_SHORT_HASH
+           << "\"} " << std::strtoull(value.str().c_str(), nullptr, 10);
+
+    EXPECT_NE(std::string::npos, body.find("# TYPE doris_cloud_version 
gauge")) << body;
+    EXPECT_NE(std::string::npos, body.find(sample.str())) << body;
+}
+
 TEST(MetricTest, FdbMetricExporterTest) {
     using namespace doris::cloud;
 
diff --git a/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
index e4eb487c229..737647e1f84 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/metric/MetricsTest.java
@@ -23,6 +23,7 @@ import org.apache.doris.cloud.JobWarmUpStats;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.Pair;
+import org.apache.doris.common.Version;
 import org.apache.doris.common.jmockit.Deencapsulation;
 import org.apache.doris.common.util.JsonUtil;
 import org.apache.doris.ha.FrontendNodeType;
@@ -63,6 +64,29 @@ public class MetricsTest {
         MetricRepo.init();
     }
 
+    @Test
+    public void testVersionMetricIsExportedWithBuildLabels() {
+        StringBuilder value = new StringBuilder()
+                .append(Version.DORIS_BUILD_VERSION_MAJOR).append(0)
+                .append(Version.DORIS_BUILD_VERSION_MINOR).append(0)
+                .append(Version.DORIS_BUILD_VERSION_PATCH);
+        if (Version.DORIS_BUILD_VERSION_HOTFIX > 0) {
+            value.append(0).append(Version.DORIS_BUILD_VERSION_HOTFIX);
+        }
+
+        String expectedSample = "doris_fe_version{version=\"" + 
Version.DORIS_BUILD_VERSION
+                + "\", major=\"" + Version.DORIS_BUILD_VERSION_MAJOR
+                + "\", minor=\"" + Version.DORIS_BUILD_VERSION_MINOR
+                + "\", patch=\"" + Version.DORIS_BUILD_VERSION_PATCH
+                + "\", hotfix=\"" + Version.DORIS_BUILD_VERSION_HOTFIX
+                + "\", short_hash=\"" + Version.DORIS_BUILD_SHORT_HASH
+                + "\"} " + Long.parseLong(value.toString());
+
+        String metricResult = getPrometheusMetrics();
+        Assert.assertTrue(metricResult, metricResult.contains("# TYPE 
doris_fe_version gauge"));
+        Assert.assertTrue(metricResult, metricResult.contains(expectedSample));
+    }
+
     @Test
     public void testTcpMetrics() {
         List<Metric> metrics = MetricRepo.getMetricsByName("snmp");
diff --git a/regression-test/suites/metrics_p0/test_version_metrics.groovy 
b/regression-test/suites/metrics_p0/test_version_metrics.groovy
index e6625f698ea..39112ec6e77 100644
--- a/regression-test/suites/metrics_p0/test_version_metrics.groovy
+++ b/regression-test/suites/metrics_p0/test_version_metrics.groovy
@@ -19,6 +19,33 @@ import java.util.regex.Pattern
 // under the License.
 
 suite("test_version_metrics") {
+    def requiredVersionLabels = ["version", "major", "minor", "patch", 
"hotfix", "short_hash"] as Set
+    def parseVersionMetric = { body, metricName ->
+        def parsedMetric = null
+        Pattern pattern = Pattern.compile('^' + Pattern.quote(metricName) + 
'\\{([^}]*)}\\s+(\\d+)$')
+        for (final def line in body.readLines()) {
+            Matcher matcher = pattern.matcher(line)
+            if (!matcher.matches()) {
+                continue
+            }
+
+            def labels = [:]
+            for (String label : matcher.group(1).split(",")) {
+                String[] keyValue = label.trim().split("=", 2)
+                assertEquals(2, keyValue.length)
+                assertTrue(keyValue[1].startsWith("\"") && 
keyValue[1].endsWith("\""))
+                labels[keyValue[0]] = keyValue[1].substring(1, 
keyValue[1].length() - 1)
+            }
+            assertEquals(requiredVersionLabels, labels.keySet())
+            parsedMetric = [labels: labels, value: 
Long.parseLong(matcher.group(2))]
+            break
+        }
+        assertNotNull(parsedMetric)
+        assertTrue(parsedMetric.value >= 0)
+        return parsedMetric
+    }
+
+    def feVersionMetric = null
     httpTest {
         endpoint context.config.feHttpAddress
         uri "/metrics"
@@ -27,15 +54,7 @@ suite("test_version_metrics") {
             logger.debug("code:${code} body:${body}");
             assertEquals(200, code)
             assertTrue(body.contains("doris_fe_version"))
-            for (final def line in body.split("\n")) {
-                if (line.startsWith("doris_fe_version")) {
-                    Pattern pattern = 
Pattern.compile(/^doris_fe_version\{.*}\s+(\d+)$/)
-                    Matcher matcher = pattern.matcher(line)
-                    assertTrue(matcher.matches())
-                    assertTrue(Long.parseLong(matcher.group(1)) >= 0)
-                    break
-                }
-            }
+            feVersionMetric = parseVersionMetric(body, "doris_fe_version")
         }
     }
 
@@ -50,11 +69,8 @@ suite("test_version_metrics") {
             logger.debug("code:${code} body:${body}");
             assertEquals(200, code)
             assertTrue(body.contains("doris_be_version"))
-            for (final def line in body.split("\n")) {
-                if (line.contains("doris_be_version") && !line.contains("#")) {
-                    assertTrue(Long.parseLong(line.split(" ")[1]) >= 0)
-                }
-            }
+            def beVersionMetric = parseVersionMetric(body, "doris_be_version")
+            assertEquals(feVersionMetric, beVersionMetric)
         }
     }
 
@@ -71,11 +87,8 @@ suite("test_version_metrics") {
                 logger.debug("code:${code} body:${body}");
                 assertEquals(200, code)
                 assertTrue(body.contains("doris_cloud_version"))
-                for (final def line in body.split("\n")) {
-                    if (line.contains("doris_cloud_version") && 
!line.contains("#")) {
-                        assertTrue(Long.parseLong(line.split(" ")[1]) >= 0)
-                    }
-                }
+                def cloudVersionMetric = parseVersionMetric(body, 
"doris_cloud_version")
+                assertEquals(feVersionMetric, cloudVersionMetric)
             }
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to