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

sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new bc1ab107c89 IGNITE-25460 Add topology metrics (#5901)
bc1ab107c89 is described below

commit bc1ab107c890b81b435f299cfd5032ec136d085d
Author: Slava Koptilin <[email protected]>
AuthorDate: Wed May 28 13:04:19 2025 +0300

    IGNITE-25460 Add topology metrics (#5901)
---
 .../ignite/internal/cli/CliIntegrationTest.java    |   4 +-
 .../partitions/reset/ItResetPartitionsTest.java    |   5 +-
 .../restart/ItRestartPartitionsTest.java           |   5 +-
 .../partitions/states/ItPartitionStatesTest.java   |   4 +-
 modules/cluster-management/build.gradle            |   1 +
 .../management/metrics/ItTopologyMetricsTest.java  |  82 ++++++++++++
 .../management/ClusterManagementGroupManager.java  |  36 +++++-
 .../metrics/ClusterTopologyMetricsSource.java      | 140 +++++++++++++++++++++
 .../metrics/LocalTopologyMetricsSource.java        | 126 +++++++++++++++++++
 .../ClusterManagementGroupManagerTest.java         |   7 +-
 .../internal/cluster/management/MockNode.java      |   4 +-
 .../rebalance/ItRebalanceDistributedTest.java      |   3 +-
 .../ItMetaStorageMultipleNodesAbstractTest.java    |   3 +-
 .../metastorage/impl/ItMetaStorageWatchTest.java   |   8 +-
 .../exporters/otlp/OtlpPushMetricExporterTest.java |   6 +-
 .../ignite/internal/metrics/StringGauge.java       |  57 +++++++++
 .../apache/ignite/internal/metrics/UuidGauge.java  |  64 ++++++++++
 .../metrics/exporters/jmx/JmxExporter.java         |  29 ++---
 .../metrics/exporters/jmx/MetricSetMbean.java      |  12 +-
 .../metrics/exporters/jmx/JmxExporterTest.java     |  26 ++--
 .../partition/replicator/fixtures/Node.java        |   8 +-
 .../rest/metrics/ItMetricControllerTest.java       |   4 +-
 ...terRecoveryControllerRestartPartitionsTest.java |   5 +-
 .../recovery/ItDisasterRecoveryControllerTest.java |  13 +-
 .../ItDistributedConfigurationPropertiesTest.java  |   8 +-
 .../ItDistributedConfigurationStorageTest.java     |   9 +-
 .../runner/app/ItIgniteNodeRestartTest.java        |   7 +-
 .../org/apache/ignite/internal/app/IgniteImpl.java |   3 +-
 .../sql/metrics/SqlClientMetricSource.java         |   2 +-
 .../exec/mapping/MappingServiceImplTest.java       |   9 +-
 .../partition/ItPartitionDestructionTest.java      |  12 +-
 .../disaster/ItDisasterRecoveryManagerTest.java    |  12 +-
 32 files changed, 623 insertions(+), 91 deletions(-)

diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
index b68c327621d..eee49f10326 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/CliIntegrationTest.java
@@ -65,7 +65,9 @@ public abstract class CliIntegrationTest extends 
ClusterPerClassIntegrationTest
             new MetricSource().name("sql.client").enabled(true),
             new MetricSource().name("sql.plan.cache").enabled(true),
             new MetricSource().name("storage.aipersist.default").enabled(true),
-            new 
MetricSource().name("storage.aipersist.default_aipersist").enabled(true)
+            new 
MetricSource().name("storage.aipersist.default_aipersist").enabled(true),
+            new MetricSource().name("topology.cluster").enabled(true),
+            new MetricSource().name("topology.local").enabled(true)
     };
 
     /** Correct ignite jdbc url. */
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/reset/ItResetPartitionsTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/reset/ItResetPartitionsTest.java
index aefc2f51a3a..6c583442be9 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/reset/ItResetPartitionsTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/reset/ItResetPartitionsTest.java
@@ -22,13 +22,12 @@ import static 
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_IDS_OPTION;
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION;
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION;
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
 import static org.apache.ignite.lang.util.IgniteNameUtils.canonicalName;
 
 import org.apache.ignite.internal.cli.CliIntegrationTest;
-import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIf;
 
 /** Base test class for Cluster Recovery reset partitions commands. */
 public abstract class ItResetPartitionsTest extends CliIntegrationTest {
@@ -81,9 +80,9 @@ public abstract class ItResetPartitionsTest extends 
CliIntegrationTest {
     }
 
     @Test
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testResetPartitionTableNotFound() {
         // This test in colocation mode is not relevant.
-        Assumptions.assumeFalse(enabledColocation());
 
         String unknownTable = "PUBLIC.unknown_table";
 
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
index fae0a50b7c8..9604724bb14 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
@@ -24,14 +24,13 @@ import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_IDS_OPTION;
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION;
 import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION;
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
 import static org.apache.ignite.lang.util.IgniteNameUtils.canonicalName;
 
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.cli.CliIntegrationTest;
-import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIf;
 
 /** Base test class for Cluster Recovery restart partitions commands. */
 public abstract class ItRestartPartitionsTest extends CliIntegrationTest {
@@ -105,9 +104,9 @@ public abstract class ItRestartPartitionsTest extends 
CliIntegrationTest {
     }
 
     @Test
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testRestartPartitionTableNotFound() {
         // This test in colocation mode is not relevant.
-        Assumptions.assumeFalse(enabledColocation());
 
         String unknownTable = "PUBLIC.unknown_table";
 
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/states/ItPartitionStatesTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/states/ItPartitionStatesTest.java
index 6edc7269729..7d59d95737d 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/states/ItPartitionStatesTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/states/ItPartitionStatesTest.java
@@ -34,9 +34,9 @@ import java.util.Set;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.cli.CliIntegrationTest;
 import org.apache.ignite.internal.util.CollectionUtils;
-import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIf;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
 
@@ -231,9 +231,9 @@ public abstract class ItPartitionStatesTest extends 
CliIntegrationTest {
 
     @ParameterizedTest
     @ValueSource(booleans = {false, true})
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void testPartitionStatesEmptyResult(boolean global) {
         // This test is not applicable for colocation enabled because empty 
zones are still have partitions.
-        Assumptions.assumeFalse(enabledColocation());
 
         execute(CLUSTER_URL_OPTION, NODE_URL,
                 RECOVERY_ZONE_NAMES_OPTION, EMPTY_ZONE,
diff --git a/modules/cluster-management/build.gradle 
b/modules/cluster-management/build.gradle
index d446c229597..bb00f86d070 100644
--- a/modules/cluster-management/build.gradle
+++ b/modules/cluster-management/build.gradle
@@ -42,6 +42,7 @@ dependencies {
     implementation project(':ignite-security')
     implementation project(':ignite-configuration-root')
     implementation project(':ignite-system-disaster-recovery-api')
+    implementation project(':ignite-metrics')
     implementation libs.jetbrains.annotations
     implementation libs.fastutil.core
     implementation libs.auto.service.annotations
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/metrics/ItTopologyMetricsTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/metrics/ItTopologyMetricsTest.java
new file mode 100644
index 00000000000..794093c2902
--- /dev/null
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/metrics/ItTopologyMetricsTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.cluster.management.metrics;
+
+import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.apache.ignite.internal.ClusterPerTestIntegrationTest;
+import org.apache.ignite.internal.app.IgniteImpl;
+import org.apache.ignite.internal.metrics.MetricManager;
+import org.apache.ignite.internal.metrics.MetricSource;
+import org.apache.ignite.internal.properties.IgniteProductVersion;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for the topology metrics.
+ */
+public class ItTopologyMetricsTest extends ClusterPerTestIntegrationTest {
+    @Override
+    protected int initialNodes() {
+        return 1;
+    }
+
+    @Test
+    public void testLocalNodeMetrics() {
+        IgniteImpl node = unwrapIgniteImpl(node(0));
+
+        LocalTopologyMetricsSource clusterTopologyMetricsSource = 
localTopologyMetricsSource(node.metricManager());
+
+        assertThat(clusterTopologyMetricsSource, is(notNullValue()));
+
+        assertThat(clusterTopologyMetricsSource.localNodeName(), 
is(node.clusterService().nodeName()));
+        assertThat(clusterTopologyMetricsSource.localNodeId(), 
is(node.clusterService().topologyService().localMember().id()));
+        assertThat(clusterTopologyMetricsSource.localNodeVersion(), 
is(IgniteProductVersion.CURRENT_VERSION.toString()));
+    }
+
+    @Test
+    public void testClusterMetrics() {
+        IgniteImpl node = unwrapIgniteImpl(node(0));
+
+        ClusterTopologyMetricsSource clusterTopologyMetricsSource = 
clusterTopologyMetricsSource(node.metricManager());
+
+        assertThat(clusterTopologyMetricsSource, is(notNullValue()));
+
+        assertThat(clusterTopologyMetricsSource.clusterName(), is("cluster"));
+        assertThat(clusterTopologyMetricsSource.totalNodes(), is(1));
+    }
+
+    private static ClusterTopologyMetricsSource 
clusterTopologyMetricsSource(MetricManager metricManager) {
+        return (ClusterTopologyMetricsSource) 
topologyMetricsSource(metricManager, ClusterTopologyMetricsSource.SOURCE_NAME);
+    }
+
+    private static LocalTopologyMetricsSource 
localTopologyMetricsSource(MetricManager metricManager) {
+        return (LocalTopologyMetricsSource) 
topologyMetricsSource(metricManager, LocalTopologyMetricsSource.SOURCE_NAME);
+    }
+
+    private static MetricSource topologyMetricsSource(MetricManager 
metricManager, String sourceName) {
+        return metricManager
+                .metricSources()
+                .stream()
+                .filter(source -> source.name().equals(sourceName))
+                .findFirst()
+                .orElseThrow();
+    }
+}
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
index c028ec2de58..4d1d263c7df 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
@@ -46,6 +46,8 @@ import 
org.apache.ignite.internal.cluster.management.LocalStateStorage.LocalStat
 import 
org.apache.ignite.internal.cluster.management.events.BeforeStartRaftGroupEventParameters;
 import 
org.apache.ignite.internal.cluster.management.events.ClusterManagerGroupEvent;
 import 
org.apache.ignite.internal.cluster.management.events.EmptyEventParameters;
+import 
org.apache.ignite.internal.cluster.management.metrics.ClusterTopologyMetricsSource;
+import 
org.apache.ignite.internal.cluster.management.metrics.LocalTopologyMetricsSource;
 import 
org.apache.ignite.internal.cluster.management.network.CmgMessageCallback;
 import org.apache.ignite.internal.cluster.management.network.CmgMessageHandler;
 import 
org.apache.ignite.internal.cluster.management.network.messages.CancelInitMessage;
@@ -78,6 +80,7 @@ import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.manager.ComponentContext;
 import org.apache.ignite.internal.manager.IgniteComponent;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.network.ClusterNodeImpl;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.NetworkMessage;
@@ -169,6 +172,12 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
 
     private final RaftGroupOptionsConfigurer raftGroupOptionsConfigurer;
 
+    private final MetricManager metricsManager;
+
+    private final ClusterTopologyMetricsSource clusterTopologyMetricsSource;
+
+    private final LocalTopologyMetricsSource localTopologyMetricsSource;
+
     /** Constructor. */
     public ClusterManagementGroupManager(
             VaultManager vault,
@@ -182,7 +191,8 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
             NodeAttributes nodeAttributes,
             FailureProcessor failureProcessor,
             ClusterIdStore clusterIdStore,
-            RaftGroupOptionsConfigurer raftGroupOptionsConfigurer
+            RaftGroupOptionsConfigurer raftGroupOptionsConfigurer,
+            MetricManager metricManager
     ) {
         this.clusterResetStorage = clusterResetStorage;
         this.clusterService = clusterService;
@@ -196,6 +206,18 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
         this.failureProcessor = failureProcessor;
         this.clusterIdStore = clusterIdStore;
         this.raftGroupOptionsConfigurer = raftGroupOptionsConfigurer;
+        this.metricsManager = metricManager;
+
+        this.clusterTopologyMetricsSource = new 
ClusterTopologyMetricsSource(logicalTopology, () -> {
+            LocalState localState = localStateStorage.getLocalState();
+
+            if (localState == null) {
+                return null;
+            }
+
+            return localState.clusterTag();
+        });
+        this.localTopologyMetricsSource = new 
LocalTopologyMetricsSource(clusterService.topologyService());
 
         scheduledExecutor = Executors.newSingleThreadScheduledExecutor(
                 NamedThreadFactory.create(clusterService.nodeName(), 
"cmg-manager", LOG)
@@ -249,7 +271,8 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
             NodeAttributes nodeAttributes,
             FailureProcessor failureProcessor,
             ClusterIdStore clusterIdStore,
-            RaftGroupOptionsConfigurer raftGroupOptionsConfigurer
+            RaftGroupOptionsConfigurer raftGroupOptionsConfigurer,
+            MetricManager metricManager
     ) {
         this(
                 vault,
@@ -263,7 +286,8 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
                 nodeAttributes,
                 failureProcessor,
                 clusterIdStore,
-                raftGroupOptionsConfigurer
+                raftGroupOptionsConfigurer,
+                metricManager
         );
     }
 
@@ -357,6 +381,12 @@ public class ClusterManagementGroupManager extends 
AbstractEventProducer<Cluster
 
     @Override
     public CompletableFuture<Void> startAsync(ComponentContext 
componentContext) {
+        metricsManager.registerSource(clusterTopologyMetricsSource);
+        metricsManager.registerSource(localTopologyMetricsSource);
+
+        metricsManager.enable(clusterTopologyMetricsSource);
+        metricsManager.enable(localTopologyMetricsSource);
+
         ResetClusterMessage resetClusterMessage = 
clusterResetStorage.readResetClusterMessage();
         if (resetClusterMessage != null) {
             return doClusterReset(resetClusterMessage);
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
new file mode 100644
index 00000000000..a9f9aa603b3
--- /dev/null
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.cluster.management.metrics;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.cluster.management.ClusterTag;
+import org.apache.ignite.internal.cluster.management.topology.LogicalTopology;
+import org.apache.ignite.internal.metrics.AbstractMetricSource;
+import org.apache.ignite.internal.metrics.IntGauge;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.StringGauge;
+import org.apache.ignite.internal.metrics.UuidGauge;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * The source of cluster topology metrics.
+ */
+public class ClusterTopologyMetricsSource extends 
AbstractMetricSource<ClusterTopologyMetricsSource.Holder> {
+    /** Source name. */
+    static final String SOURCE_NAME = "topology.cluster";
+
+    /** Logical topology. */
+    private final LogicalTopology logicalTopology;
+
+    /** Provider of the cluster's tag. */
+    private final Supplier<ClusterTag> clusterTagSupplier;
+
+    /**
+     * Creates a new instance of the topology metrics source.
+     *
+     * @param logicalTopology Logical topology.
+     * @param clusterTagSupplier Supplier of the cluster's tag.
+     */
+    public ClusterTopologyMetricsSource(LogicalTopology logicalTopology, 
Supplier<ClusterTag> clusterTagSupplier) {
+        super(SOURCE_NAME);
+
+        this.logicalTopology = logicalTopology;
+        this.clusterTagSupplier = clusterTagSupplier;
+    }
+
+    @Override
+    protected Holder createHolder() {
+        return new Holder();
+    }
+
+    /**
+     * Returns name of the cluster.
+     *
+     * @return Name of the cluster, or empty string if the holder is not 
initialized.
+     */
+    public String clusterName() {
+        Holder h = holder();
+
+        if (h == null) {
+            return "";
+        }
+
+        return h.clusterName.value();
+    }
+
+    /**
+     * Returns the unique identifier of the cluster.
+     *
+     * @return Returns the unique identifier of the cluster, or {@code null} 
if the holder is not initialized.
+     */
+    public @Nullable UUID clusterId() {
+        Holder h = holder();
+
+        if (h == null) {
+            return null;
+        }
+
+        return h.clusterId.value();
+    }
+
+    /**
+     * Returns the total number of nodes in the logical topology.
+     *
+     * @return Returns the total number of nodes in the logical topology, or 
{@code 0} if the holder is not initialized.
+     */
+    public int totalNodes() {
+        Holder h = holder();
+
+        if (h == null) {
+            return 0;
+        }
+
+        return h.clusterSize.value();
+    }
+
+    /** Holder. */
+    protected class Holder implements AbstractMetricSource.Holder<Holder> {
+        private final IntGauge clusterSize = new IntGauge(
+                "TotalNodes",
+                "Number of nodes in the logical topology",
+                () -> logicalTopology.getLogicalTopology().nodes().size());
+
+        private final UuidGauge clusterId = new UuidGauge(
+                "ClusterId",
+                "Unique identifier of the cluster",
+                () -> {
+                    ClusterTag tag = clusterTagSupplier.get();
+
+                    return tag != null ? tag.clusterId() : null;
+                });
+
+        private final StringGauge clusterName = new StringGauge(
+                "ClusterName",
+                "Unique name of the cluster",
+                () -> {
+                    ClusterTag tag = clusterTagSupplier.get();
+
+                    return tag != null ? tag.clusterName() : "";
+                });
+
+        private final List<Metric> metrics = List.of(clusterId, clusterName, 
clusterSize);
+
+        @Override
+        public Iterable<Metric> metrics() {
+            return metrics;
+        }
+    }
+}
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
new file mode 100644
index 00000000000..1ea4e66e00d
--- /dev/null
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/LocalTopologyMetricsSource.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.cluster.management.metrics;
+
+import java.util.List;
+import java.util.UUID;
+import org.apache.ignite.internal.metrics.AbstractMetricSource;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.StringGauge;
+import org.apache.ignite.internal.metrics.UuidGauge;
+import org.apache.ignite.internal.network.TopologyService;
+import org.apache.ignite.internal.properties.IgniteProductVersion;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * The source of local node metrics.
+ */
+public class LocalTopologyMetricsSource extends 
AbstractMetricSource<LocalTopologyMetricsSource.Holder> {
+    /** Source name. */
+    static final String SOURCE_NAME = "topology.local";
+
+    /** Physical topology. */
+    private final TopologyService physicalTopology;
+
+    /**
+     * Creates a new instance of the local node metrics source.
+     *
+     * @param physicalTopology Physical topology.
+     */
+    public LocalTopologyMetricsSource(TopologyService physicalTopology) {
+        super(SOURCE_NAME);
+
+        this.physicalTopology = physicalTopology;
+    }
+
+    @Override
+    protected Holder createHolder() {
+        return new Holder();
+    }
+
+    /**
+     * Returns name of the local node.
+     *
+     * @return Name of the local node, or an empty string if the holder is not 
initialized.
+     */
+    public String localNodeName() {
+        Holder h = holder();
+
+        if (h == null) {
+            return "";
+        }
+
+        return h.localNodeName.value();
+    }
+
+    /**
+     * Returns the unique identifier of the local node.
+     *
+     * @return Unique identifier of the local node, or {@code null} if the 
holder is not initialized.
+     */
+    public @Nullable UUID localNodeId() {
+        Holder h = holder();
+
+        if (h == null) {
+            return null;
+        }
+
+        return h.localNodeId.value();
+    }
+
+    /**
+     * Returns version of the local node.
+     *
+     * @return Version of the local node, or empty string if the holder is not 
initialized.
+     */
+    public String localNodeVersion() {
+        Holder h = holder();
+
+        if (h == null) {
+            return "";
+        }
+
+        return h.localNodeVersion.value();
+    }
+
+    /** Holder. */
+    protected class Holder implements AbstractMetricSource.Holder<Holder> {
+        // Local node metrics.
+        private final StringGauge localNodeVersion = new StringGauge(
+                "NodeVersion",
+                "Ignite product version",
+                IgniteProductVersion.CURRENT_VERSION::toString);
+
+        private final UuidGauge localNodeId = new UuidGauge(
+                "NodeId",
+                "Unique identifier of the local node",
+                () -> physicalTopology.localMember().id());
+
+        private final StringGauge localNodeName = new StringGauge(
+                "NodeName",
+                "Unique name of the local node",
+                () -> physicalTopology.localMember().name());
+
+        private final List<Metric> metrics = List.of(localNodeName, 
localNodeId, localNodeVersion);
+
+        @Override
+        public Iterable<Metric> metrics() {
+            return metrics;
+        }
+    }
+}
diff --git 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManagerTest.java
 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManagerTest.java
index 630bb24fff2..1dc6948e1c0 100644
--- 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManagerTest.java
+++ 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManagerTest.java
@@ -41,6 +41,7 @@ import 
org.apache.ignite.internal.disaster.system.SystemDisasterRecoveryStorage;
 import org.apache.ignite.internal.failure.FailureManager;
 import org.apache.ignite.internal.lang.NodeStoppingException;
 import org.apache.ignite.internal.manager.ComponentContext;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.NetworkMessage;
 import org.apache.ignite.internal.network.StaticNodeFinder;
@@ -81,7 +82,8 @@ class ClusterManagementGroupManagerTest extends 
BaseIgniteAbstractTest {
             @Mock LogicalTopology logicalTopology,
             @Mock NodeAttributes nodeAttributes,
             @Mock FailureManager failureManager,
-            @Mock RaftGroupService raftGroupService
+            @Mock RaftGroupService raftGroupService,
+            @Mock MetricManager metricManager
     ) throws NodeStoppingException {
         var addr = new NetworkAddress("localhost", 10_000);
 
@@ -116,7 +118,8 @@ class ClusterManagementGroupManagerTest extends 
BaseIgniteAbstractTest {
                 nodeAttributes,
                 failureManager,
                 new ClusterIdHolder(),
-                RaftGroupOptionsConfigurer.EMPTY
+                RaftGroupOptionsConfigurer.EMPTY,
+                metricManager
         );
 
         assertThat(clusterService.startAsync(componentContext), 
willCompleteSuccessfully());
diff --git 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
index bcaaa209f8d..c5f0d0919af 100644
--- 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
+++ 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
@@ -44,6 +44,7 @@ import org.apache.ignite.internal.failure.NoOpFailureManager;
 import org.apache.ignite.internal.hlc.HybridClockImpl;
 import org.apache.ignite.internal.manager.ComponentContext;
 import org.apache.ignite.internal.manager.IgniteComponent;
+import org.apache.ignite.internal.metrics.NoOpMetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.NodeFinder;
 import org.apache.ignite.internal.network.utils.ClusterServiceTestUtils;
@@ -136,7 +137,8 @@ public class MockNode {
                 new NodeAttributesCollector(nodeAttributes, 
storageProfilesConfiguration),
                 failureManager,
                 clusterIdHolder,
-                cmgRaftConfigurer
+                cmgRaftConfigurer,
+                new NoOpMetricManager()
         );
 
         components = List.of(
diff --git 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
index 16a2918e6d3..327c096ecab 100644
--- 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
+++ 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
@@ -1308,7 +1308,8 @@ public class ItRebalanceDistributedTest extends 
BaseIgniteAbstractTest {
                     new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                     failureManager,
                     clusterIdService,
-                    cmgRaftConfigurer
+                    cmgRaftConfigurer,
+                    metricManager
             );
 
             LogicalTopologyServiceImpl logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
index 0f80c040cc4..550894248e6 100644
--- 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
+++ 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesAbstractTest.java
@@ -193,7 +193,8 @@ abstract class ItMetaStorageMultipleNodesAbstractTest 
extends IgniteAbstractTest
                     new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                     failureManager,
                     new ClusterIdHolder(),
-                    cmgRaftConfigurator
+                    cmgRaftConfigurator,
+                    new NoOpMetricManager()
             );
 
             var logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
index 3566292ad7c..41d6565a454 100644
--- 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
+++ 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageWatchTest.java
@@ -78,6 +78,7 @@ import org.apache.ignite.internal.metastorage.dsl.Conditions;
 import org.apache.ignite.internal.metastorage.dsl.Operations;
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import 
org.apache.ignite.internal.metastorage.server.persistence.RocksDbKeyValueStorage;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.metrics.NoOpMetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.StaticNodeFinder;
@@ -191,6 +192,8 @@ public class ItMetaStorageWatchTest extends 
IgniteAbstractTest {
             RaftGroupOptionsConfigurer cmgRaftConfigurer =
                     
RaftGroupOptionsConfigHelper.configureProperties(cmgLogStorageFactory, 
cmgWorkDir.metaPath());
 
+            MetricManager metricManager = new NoOpMetricManager();
+
             this.cmgManager = new ClusterManagementGroupManager(
                     vaultManager,
                     new SystemDisasterRecoveryStorage(vaultManager),
@@ -202,7 +205,8 @@ public class ItMetaStorageWatchTest extends 
IgniteAbstractTest {
                     new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                     failureManager,
                     new ClusterIdHolder(),
-                    cmgRaftConfigurer
+                    cmgRaftConfigurer,
+                    metricManager
             );
 
             components.add(cmgManager);
@@ -246,7 +250,7 @@ public class ItMetaStorageWatchTest extends 
IgniteAbstractTest {
                     storage,
                     clock,
                     topologyAwareRaftGroupServiceFactory,
-                    new NoOpMetricManager(),
+                    metricManager,
                     systemConfiguration,
                     msRaftConfigurer,
                     readOperationForCompactionTracker
diff --git 
a/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java
 
b/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java
index e80c75a0bd8..4d9b1caacff 100644
--- 
a/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java
+++ 
b/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java
@@ -87,7 +87,11 @@ class OtlpPushMetricExporterTest extends 
BaseIgniteAbstractTest {
 
     private static final String SRC_NAME = "testSource";
 
-    /** Metric set with all available metric types. */
+    /**
+     * Metric set with all available metric types.
+     * Note that OTLP does not support {@link 
org.apache.ignite.internal.metrics.UuidGauge} and
+     * {@link org.apache.ignite.internal.metrics.StringGauge} types, so they 
are not included here.
+     **/
     private static final MetricSet metricSet =
             new MetricSet(
                     SRC_NAME,
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/StringGauge.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/StringGauge.java
new file mode 100644
index 00000000000..32acc1c616d
--- /dev/null
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/StringGauge.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import java.util.function.Supplier;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * UUID metric based on {@link Supplier}.
+ * Use this type of metric with caution, as it is not a scalar metric and 
might not be supported by all exporters.
+ */
+public class StringGauge extends AbstractMetric {
+    /** Value supplier. */
+    private final Supplier<String> val;
+
+    /**
+     * Creates a new instance of StringGauge.
+     *
+     * @param name Metric name.
+     * @param desc Metric Description.
+     * @param val Supplier for the metric value.
+     */
+    public StringGauge(String name, @Nullable String desc, Supplier<String> 
val) {
+        super(name, desc);
+
+        this.val = val;
+    }
+
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public String value() {
+        return val.get();
+    }
+
+    @Override
+    public @Nullable String getValueAsString() {
+        return value();
+    }
+}
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/UuidGauge.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/UuidGauge.java
new file mode 100644
index 00000000000..65edccd035c
--- /dev/null
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/UuidGauge.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.metrics;
+
+import java.util.UUID;
+import java.util.function.Supplier;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * UUID metric based on {@link Supplier}.
+ * Use this type of metric with caution, as it is not a scalar metric and 
might not be supported by all exporters.
+ */
+public class UuidGauge extends AbstractMetric {
+    /** Value supplier. */
+    private final Supplier<UUID> val;
+
+    /**
+     * Creates a new instance of UuidGauge.
+     *
+     * @param name Metric name.
+     * @param desc Metric Description.
+     * @param val Supplier for the metric value.
+     */
+    public UuidGauge(String name, @Nullable String desc, Supplier<UUID> val) {
+        super(name, desc);
+
+        this.val = val;
+    }
+
+    /**
+     * Value of the metric.
+     *
+     * @return Value of the metric.
+     */
+    public UUID value() {
+        return val.get();
+    }
+
+    @Override
+    public @Nullable String getValueAsString() {
+        UUID value = value();
+
+        if (value == null) {
+            return null;
+        }
+
+        return value().toString();
+    }
+}
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporter.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporter.java
index 646bc32b7dd..5f345c5b49f 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporter.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporter.java
@@ -43,22 +43,16 @@ import 
org.apache.ignite.internal.metrics.exporters.configuration.JmxExporterVie
  */
 @AutoService(MetricExporter.class)
 public class JmxExporter extends BasicMetricExporter<JmxExporterView> {
-    /**
-     * Exporter name. Must be the same for configuration and exporter itself.
-     */
+    /** Exporter name. Must be the same for configuration and exporter itself. 
*/
     public static final String JMX_EXPORTER_NAME = "jmx";
 
     /** Group attribute of {@link ObjectName} shared for all metric MBeans. */
     public static final String JMX_METRIC_GROUP = "metrics";
 
-    /**
-     * Logger.
-     */
+    /** Logger. */
     private final IgniteLogger log;
 
-    /**
-     * Current registered MBeans.
-     */
+    /** Current registered MBeans. */
     private final List<ObjectName> mbeans = new ArrayList<>();
 
     public JmxExporter() {
@@ -69,12 +63,13 @@ public class JmxExporter extends 
BasicMetricExporter<JmxExporterView> {
         this.log = log;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public synchronized void start(MetricProvider metricsProvider, 
JmxExporterView configuration, Supplier<UUID> clusterIdSupplier,
-            String nodeName) {
+    public synchronized void start(
+            MetricProvider metricsProvider,
+            JmxExporterView configuration,
+            Supplier<UUID> clusterIdSupplier,
+            String nodeName
+    ) {
         super.start(metricsProvider, configuration, clusterIdSupplier, 
nodeName);
 
         for (MetricSet metricSet : metricsProvider.metrics().get1().values()) {
@@ -82,9 +77,6 @@ public class JmxExporter extends 
BasicMetricExporter<JmxExporterView> {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public synchronized void stop() {
         mbeans.forEach(this::unregBean);
@@ -92,9 +84,6 @@ public class JmxExporter extends 
BasicMetricExporter<JmxExporterView> {
         mbeans.clear();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public String name() {
         return JMX_EXPORTER_NAME;
diff --git 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/MetricSetMbean.java
 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/MetricSetMbean.java
index 4433558cf24..aa91aaf6760 100644
--- 
a/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/MetricSetMbean.java
+++ 
b/modules/metrics/src/main/java/org/apache/ignite/internal/metrics/exporters/jmx/MetricSetMbean.java
@@ -36,6 +36,8 @@ import org.apache.ignite.internal.metrics.LongMetric;
 import org.apache.ignite.internal.metrics.Metric;
 import org.apache.ignite.internal.metrics.MetricManagerImpl;
 import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.StringGauge;
+import org.apache.ignite.internal.metrics.UuidGauge;
 
 /**
  * MBean implementation, which produce JMX API representation for {@link 
MetricSet}.
@@ -61,7 +63,7 @@ public class MetricSetMbean implements DynamicMBean {
      */
     @Override
     public Object getAttribute(String attribute) throws 
AttributeNotFoundException {
-        if (attribute.equals("MBeanInfo")) {
+        if ("MBeanInfo".equals(attribute)) {
             return getMBeanInfo();
         }
 
@@ -78,6 +80,10 @@ public class MetricSetMbean implements DynamicMBean {
         } else if (metric instanceof CompositeMetric) {
             String value = metric.getValueAsString();
             return value == null ? "" : value;
+        } else if (metric instanceof StringGauge) {
+            return ((StringGauge) metric).value();
+        } else if (metric instanceof UuidGauge) {
+            return ((UuidGauge) metric).value();
         }
 
         throw new AttributeNotFoundException("Unknown metric class " + 
metric.getClass());
@@ -180,6 +186,10 @@ public class MetricSetMbean implements DynamicMBean {
             return long[].class.getName();
         } else if (metric instanceof CompositeMetric) {
             return String.class.getName();
+        } else if (metric instanceof StringGauge) {
+            return String.class.getName();
+        } else if (metric instanceof UuidGauge) {
+            return UuidGauge.class.getName();
         }
 
         throw new IllegalArgumentException("Unknown metric class " + 
metric.getClass());
diff --git 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java
 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java
index a29ffb0d0ed..3c74b7496ab 100644
--- 
a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java
+++ 
b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.when;
 
 import java.lang.management.ManagementFactory;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -64,6 +63,8 @@ import org.apache.ignite.internal.metrics.LongMetric;
 import org.apache.ignite.internal.metrics.Metric;
 import org.apache.ignite.internal.metrics.MetricProvider;
 import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.StringGauge;
+import org.apache.ignite.internal.metrics.UuidGauge;
 import org.apache.ignite.internal.metrics.configuration.MetricConfiguration;
 import 
org.apache.ignite.internal.metrics.exporters.configuration.JmxExporterView;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
@@ -90,6 +91,8 @@ public class JmxExporterTest extends BaseIgniteAbstractTest {
 
     private static final String MTRC_NAME = "testMetric";
 
+    private static final UUID uuid = UUID.randomUUID();
+
     /**
      * Metric set with all available metric types.
      */
@@ -110,7 +113,9 @@ public class JmxExporterTest extends BaseIgniteAbstractTest 
{
                             new IgniteBiTuple<>("customIntMetric", new 
CustomIntMetric()),
                             new IgniteBiTuple<>("customLongMetric", new 
CustomLongMetric()),
                             new IgniteBiTuple<>("customDoubleMetric", new 
CustomDoubleMetric()),
-                            new IgniteBiTuple<>("customCompositeMetric", new 
CustomCompositeMetric())
+                            new IgniteBiTuple<>("customCompositeMetric", new 
CustomCompositeMetric()),
+                            new IgniteBiTuple<>("stringGauge", new 
StringGauge("stringGauge", "", () -> "testString")),
+                            new IgniteBiTuple<>("uuidGauge", new 
UuidGauge("uuidGauge", "", () -> uuid))
                     ).collect(toMap(IgniteBiTuple::getKey, 
IgniteBiTuple::getValue))
             );
 
@@ -141,8 +146,7 @@ public class JmxExporterTest extends BaseIgniteAbstractTest 
{
     }
 
     @Test
-    public void testStart()
-            throws ReflectionException, AttributeNotFoundException, 
MBeanException {
+    public void testStart() throws ReflectionException, 
AttributeNotFoundException, MBeanException {
         Map<String, MetricSet> metrics = Map.of(metricSet.name(), metricSet);
 
         when(metricsProvider.metrics()).thenReturn(new 
IgniteBiTuple<>(metrics, 1L));
@@ -153,8 +157,7 @@ public class JmxExporterTest extends BaseIgniteAbstractTest 
{
     }
 
     @Test
-    public void testAddMetric()
-            throws ReflectionException, AttributeNotFoundException, 
MBeanException {
+    public void testAddMetric() throws ReflectionException, 
AttributeNotFoundException, MBeanException {
         when(metricsProvider.metrics()).thenReturn(new IgniteBiTuple<>(new 
HashMap<>(), 1L));
 
         jmxExporter.start(metricsProvider, jmxExporterConf, UUID::randomUUID, 
"nodeName");
@@ -170,8 +173,7 @@ public class JmxExporterTest extends BaseIgniteAbstractTest 
{
     }
 
     @Test
-    public void testRemoveMetric()
-            throws ReflectionException, AttributeNotFoundException, 
MBeanException {
+    public void testRemoveMetric() throws ReflectionException, 
AttributeNotFoundException, MBeanException {
         Map<String, MetricSet> metrics = Map.of(metricSet.name(), metricSet);
 
         when(metricsProvider.metrics()).thenReturn(new 
IgniteBiTuple<>(metrics, 1L));
@@ -247,9 +249,7 @@ public class JmxExporterTest extends BaseIgniteAbstractTest 
{
      */
     private void assertThatMbeanAttributeAndMetricValuesAreTheSame()
             throws ReflectionException, AttributeNotFoundException, 
MBeanException {
-        for (Iterator<Metric> it = metricSet.iterator(); it.hasNext(); ) {
-            Metric metric = it.next();
-
+        for (Metric metric : metricSet) {
             Object beanAttribute = mbean().getAttribute(metric.name());
 
             String errorMsg = "Wrong MBean attribute value for the metric with 
name " + metric.name();
@@ -264,6 +264,10 @@ public class JmxExporterTest extends 
BaseIgniteAbstractTest {
                 assertArrayEquals(((DistributionMetric) metric).value(), 
(long[]) beanAttribute, errorMsg);
             } else if (metric instanceof CompositeMetric) {
                 assertEquals(metric.getValueAsString(), beanAttribute, 
errorMsg);
+            } else if (metric instanceof StringGauge) {
+                assertEquals(((StringGauge) metric).value(), beanAttribute, 
errorMsg);
+            } else if (metric instanceof UuidGauge) {
+                assertEquals(((UuidGauge) metric).value(), beanAttribute, 
errorMsg);
             }
         }
     }
diff --git 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
index 02b96e6588e..424a175485f 100644
--- 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
+++ 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/fixtures/Node.java
@@ -111,6 +111,7 @@ import 
org.apache.ignite.internal.metastorage.impl.MetaStorageRevisionListenerRe
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import 
org.apache.ignite.internal.metastorage.server.persistence.RocksDbKeyValueStorage;
 import org.apache.ignite.internal.metastorage.server.raft.MetastorageGroupId;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.metrics.NoOpMetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.NodeFinder;
@@ -383,9 +384,11 @@ public class Node {
         RaftGroupOptionsConfigurer partitionRaftConfigurer =
                 
RaftGroupOptionsConfigHelper.configureProperties(partitionsLogStorageFactory, 
partitionsWorkDir.metaPath());
 
+        MetricManager metricManager = new NoOpMetricManager();
+
         raftManager = new Loza(
                 clusterService,
-                new NoOpMetricManager(),
+                metricManager,
                 raftConfiguration,
                 hybridClock,
                 raftGroupEventsClientListener,
@@ -422,7 +425,8 @@ public class Node {
                 new NodeAttributesCollector(nodeAttributesConfiguration, 
storageConfiguration),
                 failureManager,
                 clusterIdHolder,
-                cmgRaftConfigurer
+                cmgRaftConfigurer,
+                metricManager
         );
 
         LogicalTopologyServiceImpl logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/metrics/ItMetricControllerTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/metrics/ItMetricControllerTest.java
index 334cf85106f..a1ed52b403e 100644
--- 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/metrics/ItMetricControllerTest.java
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/metrics/ItMetricControllerTest.java
@@ -56,7 +56,9 @@ class ItMetricControllerTest extends 
ClusterPerClassIntegrationTest {
             new MetricSource("sql.client", true),
             new MetricSource("sql.plan.cache", true),
             new MetricSource("storage.aipersist.default", true),
-            new MetricSource("storage.aipersist.default_aipersist", true)
+            new MetricSource("storage.aipersist.default_aipersist", true),
+            new MetricSource("topology.cluster", true),
+            new MetricSource("topology.local", true)
     };
 
     @Inject
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerRestartPartitionsTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerRestartPartitionsTest.java
index b92dd988f36..b273930fdd2 100644
--- 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerRestartPartitionsTest.java
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerRestartPartitionsTest.java
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.rest.recovery;
 import static java.util.stream.Collectors.toSet;
 import static 
org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERSIST_PROFILE_NAME;
 import static 
org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.COLOCATION_FEATURE_FLAG;
 import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
 import static org.apache.ignite.internal.rest.constants.HttpCode.BAD_REQUEST;
 import static org.apache.ignite.internal.rest.constants.HttpCode.OK;
@@ -49,7 +48,7 @@ import 
org.apache.ignite.internal.rest.api.recovery.RestartPartitionsRequest;
 import 
org.apache.ignite.internal.rest.api.recovery.RestartZonePartitionsRequest;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.condition.DisabledIf;
 
 /** Test for disaster recovery restart partitions command. */
 @MicronautTest
@@ -93,7 +92,7 @@ public class 
ItDisasterRecoveryControllerRestartPartitionsTest extends ClusterPe
 
     @Test
     // TODO: remove this test when colocation is enabled 
https://issues.apache.org/jira/browse/IGNITE-22522
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testRestartPartitionTableNotFound() {
         String tableName = "PUBLIC.unknown_table";
 
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerTest.java
index 1d3ad17d169..a7d175fcbfa 100644
--- 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerTest.java
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/recovery/ItDisasterRecoveryControllerTest.java
@@ -24,7 +24,6 @@ import static 
org.apache.ignite.internal.TestDefaultProfilesNames.DEFAULT_AIPERS
 import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
 import static 
org.apache.ignite.internal.catalog.CatalogManagerImpl.DEFAULT_ZONE_NAME;
 import static 
org.apache.ignite.internal.catalog.commands.CatalogUtils.DEFAULT_PARTITION_COUNT;
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.COLOCATION_FEATURE_FLAG;
 import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
 import static org.apache.ignite.internal.rest.constants.HttpCode.BAD_REQUEST;
 import static org.apache.ignite.internal.sql.SqlCommon.DEFAULT_SCHEMA_NAME;
@@ -70,7 +69,7 @@ import 
org.apache.ignite.internal.rest.api.recovery.ResetZonePartitionsRequest;
 import org.apache.ignite.internal.util.CollectionUtils;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.condition.DisabledIf;
 
 /**
  * Test for disaster recovery REST commands.
@@ -208,7 +207,7 @@ public class ItDisasterRecoveryControllerTest extends 
ClusterPerClassIntegration
     }
 
     @Test
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void testLocalPartitionsEmptyResult() {
         String path = localStatePath();
         HttpResponse<?> response = client.toBlocking().exchange(
@@ -221,7 +220,7 @@ public class ItDisasterRecoveryControllerTest extends 
ClusterPerClassIntegration
     }
 
     // TODO: https://issues.apache.org/jira/browse/IGNITE-25448 Does not work 
with colocation enabled.
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     @Test
     void testLocalPartitionStatesByZones() {
         String path = localStatePath();
@@ -388,7 +387,7 @@ public class ItDisasterRecoveryControllerTest extends 
ClusterPerClassIntegration
     }
 
     @Test
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void testGlobalPartitionsEmptyResult() {
         String path = globalStatePath();
 
@@ -466,7 +465,7 @@ public class ItDisasterRecoveryControllerTest extends 
ClusterPerClassIntegration
 
     @Test
     // TODO: remove this test when colocation is enabled 
https://issues.apache.org/jira/browse/IGNITE-22522
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testResetPartitionTableNotFound() {
         String tableName = "PUBLIC.unknown_table";
 
@@ -511,7 +510,7 @@ public class ItDisasterRecoveryControllerTest extends 
ClusterPerClassIntegration
     }
 
     // TODO: https://issues.apache.org/jira/browse/IGNITE-25448 Does not work 
with colocation enabled.
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     @Test
     void testLocalPartitionStatesWithUpdatedEstimatedRows() {
         insertRowToAllTables(1, 1);
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
index 0955e9c4122..4c63e8d6426 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/ItDistributedConfigurationPropertiesTest.java
@@ -64,6 +64,7 @@ import 
org.apache.ignite.internal.metastorage.MetaStorageManager;
 import org.apache.ignite.internal.metastorage.impl.MetaStorageManagerImpl;
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import 
org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStorage;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.metrics.NoOpMetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.StaticNodeFinder;
@@ -202,6 +203,8 @@ public class ItDistributedConfigurationPropertiesTest 
extends BaseIgniteAbstract
             RaftGroupOptionsConfigurer cmgRaftConfigurer =
                     
RaftGroupOptionsConfigHelper.configureProperties(cmgLogStorageFactory, 
cmgWorkDir.metaPath());
 
+            MetricManager metricManager = new NoOpMetricManager();
+
             cmgManager = new ClusterManagementGroupManager(
                     vaultManager,
                     new SystemDisasterRecoveryStorage(vaultManager),
@@ -213,7 +216,8 @@ public class ItDistributedConfigurationPropertiesTest 
extends BaseIgniteAbstract
                     new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                     failureManager,
                     new ClusterIdHolder(),
-                    cmgRaftConfigurer
+                    cmgRaftConfigurer,
+                    metricManager
             );
 
             var logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
@@ -243,7 +247,7 @@ public class ItDistributedConfigurationPropertiesTest 
extends BaseIgniteAbstract
                     new SimpleInMemoryKeyValueStorage(name(), 
readOperationForCompactionTracker),
                     clock,
                     topologyAwareRaftGroupServiceFactory,
-                    new NoOpMetricManager(),
+                    metricManager,
                     systemConfiguration,
                     msRaftConfigurer,
                     readOperationForCompactionTracker
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
index 85f1494ab7e..6b6989c4bf7 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/configuration/storage/ItDistributedConfigurationStorageTest.java
@@ -57,6 +57,7 @@ import 
org.apache.ignite.internal.metastorage.MetaStorageManager;
 import org.apache.ignite.internal.metastorage.impl.MetaStorageManagerImpl;
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import 
org.apache.ignite.internal.metastorage.server.SimpleInMemoryKeyValueStorage;
+import org.apache.ignite.internal.metrics.MetricManager;
 import org.apache.ignite.internal.metrics.NoOpMetricManager;
 import org.apache.ignite.internal.network.ClusterService;
 import org.apache.ignite.internal.network.StaticNodeFinder;
@@ -175,6 +176,9 @@ public class ItDistributedConfigurationStorageTest extends 
BaseIgniteAbstractTes
 
             RaftGroupOptionsConfigurer cmgRaftConfigurer =
                     
RaftGroupOptionsConfigHelper.configureProperties(cmgLogStorageFactory, 
cmgWorkDir.metaPath());
+
+            MetricManager metricManager = new NoOpMetricManager();
+
             cmgManager = new ClusterManagementGroupManager(
                     vaultManager,
                     new SystemDisasterRecoveryStorage(vaultManager),
@@ -186,7 +190,8 @@ public class ItDistributedConfigurationStorageTest extends 
BaseIgniteAbstractTes
                     new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                     failureManager,
                     new ClusterIdHolder(),
-                    cmgRaftConfigurer
+                    cmgRaftConfigurer,
+                    metricManager
             );
 
             var logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
@@ -216,7 +221,7 @@ public class ItDistributedConfigurationStorageTest extends 
BaseIgniteAbstractTes
                     new SimpleInMemoryKeyValueStorage(name(), 
readOperationForCompactionTracker),
                     clock,
                     topologyAwareRaftGroupServiceFactory,
-                    new NoOpMetricManager(),
+                    metricManager,
                     systemConfiguration,
                     msRaftConfigurer,
                     readOperationForCompactionTracker
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index 9cb13fe98d8..f3e236c1a7b 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -445,6 +445,8 @@ public class ItIgniteNodeRestartTest extends 
BaseIgniteRestartTest {
         StorageConfiguration storageConfiguration = 
nodeCfgMgr.configurationRegistry()
                 .getConfiguration(StorageExtensionConfiguration.KEY).storage();
 
+        var metricManager = new MetricManagerImpl();
+
         var cmgManager = new ClusterManagementGroupManager(
                 vault,
                 new SystemDisasterRecoveryStorage(vault),
@@ -456,7 +458,8 @@ public class ItIgniteNodeRestartTest extends 
BaseIgniteRestartTest {
                 new NodeAttributesCollector(nodeAttributes, 
storageConfiguration),
                 failureProcessor,
                 clusterIdService,
-                cmgRaftConfigurer
+                cmgRaftConfigurer,
+                metricManager
         );
 
         LongSupplier partitionIdleSafeTimePropagationPeriodMsSupplier
@@ -480,8 +483,6 @@ public class ItIgniteNodeRestartTest extends 
BaseIgniteRestartTest {
 
         var logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgManager);
 
-        var metricManager = new MetricManagerImpl();
-
         var topologyAwareRaftGroupServiceFactory = new 
TopologyAwareRaftGroupServiceFactory(
                 clusterSvc,
                 logicalTopologyService,
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index b82cb15bc46..ab0500e6587 100644
--- 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -725,7 +725,8 @@ public class IgniteImpl implements Ignite {
                 nodeAttributesCollector,
                 failureManager,
                 clusterIdService,
-                cmgRaftConfigurer
+                cmgRaftConfigurer,
+                metricManager
         );
 
         logicalTopologyService = new 
LogicalTopologyServiceImpl(logicalTopology, cmgMgr);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/metrics/SqlClientMetricSource.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/metrics/SqlClientMetricSource.java
index 506d048c89c..e1474dad1a7 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/metrics/SqlClientMetricSource.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/metrics/SqlClientMetricSource.java
@@ -50,7 +50,7 @@ public class SqlClientMetricSource extends 
AbstractMetricSource<SqlClientMetricS
     protected class Holder implements AbstractMetricSource.Holder<Holder> {
         private final IntGauge numberOfOpenCursors = new IntGauge(
                 METRIC_OPEN_CURSORS,
-                "Number of current open cursors",
+                "Number of currently open cursors",
                 numberOfOpenCursorsSupplier
         );
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImplTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImplTest.java
index 27ccae90edb..26d5147f579 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImplTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImplTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.sql.engine.exec.mapping;
 
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.COLOCATION_FEATURE_FLAG;
 import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willSucceedFast;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -72,8 +71,8 @@ import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.internal.util.SubscriptionUtils;
 import org.jetbrains.annotations.Nullable;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.condition.DisabledIf;
+import org.junit.jupiter.api.condition.EnabledIf;
 import org.mockito.Mockito;
 
 /**
@@ -254,7 +253,7 @@ public class MappingServiceImplTest extends 
BaseIgniteAbstractTest {
     // TODO https://issues.apache.org/jira/browse/IGNITE-22522 Remove this 
test.
     // The colocation case is covered by {@link 
#testCacheInvalidationOnPrimaryZoneExpiration()}.
     @Test
-    @DisabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = 
"true")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testCacheInvalidationOnPrimaryExpiration() {
         String localNodeName = "NODE";
         List<String> nodeNames = List.of(localNodeName, "NODE1");
@@ -304,7 +303,7 @@ public class MappingServiceImplTest extends 
BaseIgniteAbstractTest {
     }
 
     @Test
-    @EnabledIfSystemProperty(named = COLOCATION_FEATURE_FLAG, matches = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     public void testCacheInvalidationOnPrimaryZoneExpiration() {
         String localNodeName = "NODE";
         List<String> nodeNames = List.of(localNodeName, "NODE1");
diff --git 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/partition/ItPartitionDestructionTest.java
 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/partition/ItPartitionDestructionTest.java
index 4eaf5d55253..c57e66294da 100644
--- 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/partition/ItPartitionDestructionTest.java
+++ 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/partition/ItPartitionDestructionTest.java
@@ -41,7 +41,6 @@ import 
org.apache.ignite.internal.ClusterPerTestIntegrationTest;
 import org.apache.ignite.internal.TestWrappers;
 import org.apache.ignite.internal.app.IgniteImpl;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
-import org.apache.ignite.internal.lang.IgniteSystemProperties;
 import org.apache.ignite.internal.partitiondistribution.Assignment;
 import org.apache.ignite.internal.partitiondistribution.TokenizedAssignments;
 import org.apache.ignite.internal.raft.Peer;
@@ -52,12 +51,13 @@ import 
org.apache.ignite.internal.replicator.ZonePartitionId;
 import org.apache.ignite.internal.sql.engine.util.SqlTestUtils;
 import org.apache.ignite.internal.table.TableImpl;
 import org.apache.ignite.internal.testframework.SystemPropertiesExtension;
-import org.apache.ignite.internal.testframework.WithSystemProperty;
 import org.apache.ignite.raft.jraft.option.RaftOptions;
 import org.apache.ignite.raft.jraft.storage.LogStorage;
 import org.apache.ignite.table.Table;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIf;
+import org.junit.jupiter.api.condition.EnabledIf;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 @ExtendWith(SystemPropertiesExtension.class)
@@ -82,7 +82,7 @@ class ItPartitionDestructionTest extends 
ClusterPerTestIntegrationTest {
     }
 
     @Test
-    @WithSystemProperty(key = IgniteSystemProperties.COLOCATION_FEATURE_FLAG, 
value = "false")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void partitionIsDestroyedOnTableDestruction() throws Exception {
         cluster.startAndInit(1, 
ItPartitionDestructionTest::aggressiveLowWatermarkIncrease);
 
@@ -103,7 +103,7 @@ class ItPartitionDestructionTest extends 
ClusterPerTestIntegrationTest {
 
     @Test
     @Disabled("https://issues.apache.org/jira/browse/IGNITE-24345";)
-    @WithSystemProperty(key = IgniteSystemProperties.COLOCATION_FEATURE_FLAG, 
value = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void partitionIsDestroyedOnZoneDestruction() throws Exception {
         cluster.startAndInit(1, 
ItPartitionDestructionTest::aggressiveLowWatermarkIncrease);
 
@@ -209,13 +209,13 @@ class ItPartitionDestructionTest extends 
ClusterPerTestIntegrationTest {
     }
 
     @Test
-    @WithSystemProperty(key = IgniteSystemProperties.COLOCATION_FEATURE_FLAG, 
value = "false")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void tablePartitionIsDestroyedWhenItIsEvictedFromNode() throws Exception {
         testPartitionIsDestroyedWhenItIsEvictedFromNode(tableId -> new 
TablePartitionId(tableId, PARTITION_ID));
     }
 
     @Test
-    @WithSystemProperty(key = IgniteSystemProperties.COLOCATION_FEATURE_FLAG, 
value = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void zonePartitionIsDestroyedWhenItIsEvictedFromNode() throws Exception {
         testPartitionIsDestroyedWhenItIsEvictedFromNode(tableId -> new 
ZonePartitionId(zoneId(tableId), PARTITION_ID));
     }
diff --git 
a/modules/transactions/src/integrationTest/java/org/apache/ignite/internal/disaster/ItDisasterRecoveryManagerTest.java
 
b/modules/transactions/src/integrationTest/java/org/apache/ignite/internal/disaster/ItDisasterRecoveryManagerTest.java
index 109151400c8..c9ab8456d1b 100644
--- 
a/modules/transactions/src/integrationTest/java/org/apache/ignite/internal/disaster/ItDisasterRecoveryManagerTest.java
+++ 
b/modules/transactions/src/integrationTest/java/org/apache/ignite/internal/disaster/ItDisasterRecoveryManagerTest.java
@@ -21,7 +21,6 @@ import static java.util.Collections.emptySet;
 import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
 import static 
org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
-import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.COLOCATION_FEATURE_FLAG;
 import static 
org.apache.ignite.internal.lang.IgniteSystemProperties.enabledColocation;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -57,11 +56,12 @@ import 
org.apache.ignite.internal.table.distributed.disaster.LocalPartitionState
 import 
org.apache.ignite.internal.table.distributed.disaster.LocalPartitionStateByNode;
 import 
org.apache.ignite.internal.table.distributed.disaster.LocalTablePartitionState;
 import 
org.apache.ignite.internal.table.distributed.disaster.LocalTablePartitionStateByNode;
-import org.apache.ignite.internal.testframework.WithSystemProperty;
 import org.apache.ignite.internal.wrapper.Wrapper;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.condition.DisabledIf;
+import org.junit.jupiter.api.condition.EnabledIf;
 
 /** For {@link DisasterRecoveryManager} integration testing. */
 // TODO https://issues.apache.org/jira/browse/IGNITE-22332 Add test cases.
@@ -104,7 +104,7 @@ public class ItDisasterRecoveryManagerTest extends 
ClusterPerTestIntegrationTest
         ));
     }
 
-    @WithSystemProperty(key = COLOCATION_FEATURE_FLAG, value = "false")
+    
@DisabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     @Test
     void testRestartTablePartitions() {
         IgniteImpl node = unwrapIgniteImpl(cluster.aliveNode());
@@ -132,7 +132,7 @@ public class ItDisasterRecoveryManagerTest extends 
ClusterPerTestIntegrationTest
     }
 
     @Test
-    @WithSystemProperty(key = COLOCATION_FEATURE_FLAG, value = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     void testRestartZonePartitions() {
         IgniteImpl node = unwrapIgniteImpl(cluster.aliveNode());
 
@@ -193,7 +193,7 @@ public class ItDisasterRecoveryManagerTest extends 
ClusterPerTestIntegrationTest
     }
 
     @Test
-    @WithSystemProperty(key = COLOCATION_FEATURE_FLAG, value = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     @ZoneParams(nodes = 2, replicas = 2, partitions = 2)
     void testLocalPartitionStateZone() throws Exception {
         IgniteImpl node = unwrapIgniteImpl(cluster.aliveNode());
@@ -266,7 +266,7 @@ public class ItDisasterRecoveryManagerTest extends 
ClusterPerTestIntegrationTest
     }
 
     @Test
-    @WithSystemProperty(key = COLOCATION_FEATURE_FLAG, value = "true")
+    
@EnabledIf("org.apache.ignite.internal.lang.IgniteSystemProperties#enabledColocation")
     @ZoneParams(nodes = 2, replicas = 2, partitions = 2)
     void testGlobalPartitionStateZone() throws Exception {
         IgniteImpl node = unwrapIgniteImpl(cluster.aliveNode());

Reply via email to