From c6589956ae98e587e08d37a0afe993c736974f3d Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Wed, 28 Oct 2026 17:01:39 +0300 Subject: [PATCH 1/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../discovery/GridDiscoveryManager.java | 18 +++ .../GridDiscoveryManagerClientMetricTest.java | 139 ++++++++++++++++++ .../testsuites/IgniteKernalSelfTestSuite.java | 2 + 3 files changed, 159 insertions(+) create mode 100644 modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index d8f9a4e428f49..264b65bde5f99 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -77,6 +77,8 @@ import org.apache.ignite.internal.managers.GridManagerAdapter; import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.metric.MetricRegistryImpl; +import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric; import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor; import org.apache.ignite.internal.processors.cache.ClientCacheChangeDummyDiscoveryMessage; import org.apache.ignite.internal.processors.cache.DynamicCacheChangeBatch; @@ -214,6 +216,9 @@ public class GridDiscoveryManager extends GridManagerAdapter { /** Name of the discovery metrics registry. */ public static final String DISCO_METRICS = metricName("io", "discovery"); + /** Metric name for the count of client nodes joined to topology. */ + public static final String CLIENT_NODES_JOINED = "ClientNodesJoined"; + /** Predicate filtering client nodes. */ private static final IgnitePredicate FILTER_CLI = new P1() { @Override public boolean apply(ClusterNode n) { @@ -293,6 +298,9 @@ public class GridDiscoveryManager extends GridManagerAdapter { /** Received custom messages history. */ private final ArrayDeque rcvdCustomMsgs = new ArrayDeque<>(); + /** Counter of client nodes joined to topology. */ + private final LongAdderMetric clientNodesJoinedCtr; + /** */ private final CountDownLatch startLatch = new CountDownLatch(1); @@ -309,6 +317,11 @@ public class GridDiscoveryManager extends GridManagerAdapter { public GridDiscoveryManager(GridKernalContext ctx) { super(ctx, ctx.config().getDiscoverySpi()); + MetricRegistryImpl discoReg = ctx.metric().registry(DISCO_METRICS); + + clientNodesJoinedCtr = discoReg.longAdderMetric( + CLIENT_NODES_JOINED, "Count of client nodes joined to topology"); + if (ctx.systemView().view(NODES_SYS_VIEW) == null) { ctx.systemView().registerView( NODES_SYS_VIEW, @@ -3084,6 +3097,9 @@ private void body0() throws InterruptedException { U.warn(log, e.getMessage()); // We a have well-formed attribute warning here. } + if (node.isClient()) + clientNodesJoinedCtr.increment(); + if (log.isInfoEnabled()) log.info("Added new node to topology: " + node); @@ -3112,6 +3128,8 @@ private void body0() throws InterruptedException { } case EVT_CLIENT_NODE_RECONNECTED: { + clientNodesJoinedCtr.increment(); + if (log.isInfoEnabled()) log.info("Client node reconnected to topology: " + node); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java new file mode 100644 index 0000000000000..6561c13a0ec96 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java @@ -0,0 +1,139 @@ +/* + * 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.managers.discovery; + +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.metric.MetricRegistry; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.spi.metric.LongMetric; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +import static org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.CLIENT_NODES_JOINED; +import static org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.DISCO_METRICS; +import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; + +/** + * Tests the CLIENT_NODES_JOINED metric in the discovery metrics registry. + */ +public class GridDiscoveryManagerClientMetricTest extends GridCommonAbstractTest { + /** */ + private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + TcpDiscoverySpi spi = new TcpDiscoverySpi(); + + spi.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(spi); + + return cfg; + } + + /** + * Verifies that the CLIENT_NODES_JOINED counter increments + * when client nodes join the topology. + * + * @throws Exception If fails. + */ + @Test + public void testClientNodesJoinedMetric() throws Exception { + int srvCnt = 2; + + try { + startGrids(srvCnt); + + // Initially no clients have joined. + for (int i = 0; i < srvCnt; i++) { + IgniteEx grid = grid(i); + + MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); + + assertNotNull(discoReg); + + LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + + assertNotNull("Metric " + CLIENT_NODES_JOINED + " not found", ctr); + + assertEquals(0L, ctr.value()); + } + + // Start one client node. + startClientGrid("client-0"); + + // Both servers should see 1 client joined. + for (int i = 0; i < srvCnt; i++) { + IgniteEx grid = grid(i); + + MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); + + LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + + assertTrue(waitForCondition(() -> ctr.value() == 1L, getTestTimeout())); + } + + // Start a second client node. + startClientGrid("client-1"); + + // Both servers should now see 2 clients joined. + for (int i = 0; i < srvCnt; i++) { + IgniteEx grid = grid(i); + + MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); + + LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + + assertTrue(waitForCondition(() -> ctr.value() == 2L, getTestTimeout())); + } + } + finally { + stopAllGrids(); + } + } + + /** + * Verifies that the CLIENT_NODES_JOINED metric is accessible + * via the metric registry and exposes proper name and description. + * + * @throws Exception If fails. + */ + @Test + public void testMetricMetadata() throws Exception { + try { + IgniteEx grid = startGrid(0); + + MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); + + LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + + assertNotNull(ctr); + + assertEquals(DISCO_METRICS + "." + CLIENT_NODES_JOINED, ctr.name()); + + assertEquals("Count of client nodes joined to topology", ctr.description()); + } + finally { + stopAllGrids(); + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java index dd6dd06042cb6..ac1f57d64e42f 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java @@ -47,6 +47,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentManagerStopSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAliveCacheSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAttributesSelfTest; +import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerClientMetricTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerWalModeConsistencyTest; import org.apache.ignite.internal.managers.discovery.IgniteTopologyPrintFormatSelfTest; import org.apache.ignite.internal.managers.events.GridEventStorageManagerInternalEventsSelfTest; @@ -92,6 +93,7 @@ GridManagerStopSelfTest.class, GridDiscoveryManagerAttributesSelfTest.class, GridDiscoveryManagerAliveCacheSelfTest.class, + GridDiscoveryManagerClientMetricTest.class, GridDiscoveryManagerWalModeConsistencyTest.class, GridDiscoveryEventSelfTest.class, GridPortProcessorSelfTest.class, From c58efe790d5e8ee4ba237313783b6e4fe6febb19 Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Fri, 30 Oct 2026 13:07:41 +0300 Subject: [PATCH 2/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../_docs/monitoring-metrics/new-metrics.adoc | 1 + .../discovery/GridDiscoveryManager.java | 26 ++++++--------- .../ignite/spi/discovery/DiscoverySpi.java | 10 ++++++ .../spi/discovery/tcp/TcpDiscoverySpi.java | 5 +++ .../tcp/internal/TcpDiscoveryStatistics.java | 24 ++++++++++++++ .../GridDiscoveryManagerClientMetricTest.java | 32 ++++++++++--------- .../discovery/zk/ZookeeperDiscoverySpi.java | 5 +++ .../ZookeeperDiscoveryStatistics.java | 15 +++++++++ 8 files changed, 86 insertions(+), 32 deletions(-) diff --git a/docs/_docs/monitoring-metrics/new-metrics.adoc b/docs/_docs/monitoring-metrics/new-metrics.adoc index 7482933ed43fd..b73270aecb04c 100644 --- a/docs/_docs/monitoring-metrics/new-metrics.adoc +++ b/docs/_docs/monitoring-metrics/new-metrics.adoc @@ -515,6 +515,7 @@ Register name: `io.discovery` |CoordinatorSince | long | Coordinator since timestamp. |CurrentTopologyVersion | long | Current topology version. |FailedNodes | integer | Failed nodes count. +|JoinedClientNodes | integer | Joined client nodes count. |JoinedNodes | integer | Joined nodes count. |LeftNodes | integer | Left nodes count. |LocalPort | integer | Local TCP port the discovery SPI listens to. diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index 264b65bde5f99..31254b9087857 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -77,8 +77,6 @@ import org.apache.ignite.internal.managers.GridManagerAdapter; import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; -import org.apache.ignite.internal.processors.metric.MetricRegistryImpl; -import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric; import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor; import org.apache.ignite.internal.processors.cache.ClientCacheChangeDummyDiscoveryMessage; import org.apache.ignite.internal.processors.cache.DynamicCacheChangeBatch; @@ -216,9 +214,6 @@ public class GridDiscoveryManager extends GridManagerAdapter { /** Name of the discovery metrics registry. */ public static final String DISCO_METRICS = metricName("io", "discovery"); - /** Metric name for the count of client nodes joined to topology. */ - public static final String CLIENT_NODES_JOINED = "ClientNodesJoined"; - /** Predicate filtering client nodes. */ private static final IgnitePredicate FILTER_CLI = new P1() { @Override public boolean apply(ClusterNode n) { @@ -298,9 +293,6 @@ public class GridDiscoveryManager extends GridManagerAdapter { /** Received custom messages history. */ private final ArrayDeque rcvdCustomMsgs = new ArrayDeque<>(); - /** Counter of client nodes joined to topology. */ - private final LongAdderMetric clientNodesJoinedCtr; - /** */ private final CountDownLatch startLatch = new CountDownLatch(1); @@ -317,11 +309,6 @@ public class GridDiscoveryManager extends GridManagerAdapter { public GridDiscoveryManager(GridKernalContext ctx) { super(ctx, ctx.config().getDiscoverySpi()); - MetricRegistryImpl discoReg = ctx.metric().registry(DISCO_METRICS); - - clientNodesJoinedCtr = discoReg.longAdderMetric( - CLIENT_NODES_JOINED, "Count of client nodes joined to topology"); - if (ctx.systemView().view(NODES_SYS_VIEW) == null) { ctx.systemView().registerView( NODES_SYS_VIEW, @@ -1416,8 +1403,15 @@ public void ackTopology(long topVer, int evtType, ClusterNode evtNode) { } /** - * Logs grid size for license compliance. + * Notifies the discovery SPI that a client node has joined the topology. * + * @param spi Discovery SPI. + */ + private void onClientNodeJoined(DiscoverySpi spi) { + spi.onClientNodeJoined(); + } + + /** * @param topVer Topology version. * @param evtType Event type. * @param evtNode Event node. @@ -3098,7 +3092,7 @@ private void body0() throws InterruptedException { } if (node.isClient()) - clientNodesJoinedCtr.increment(); + onClientNodeJoined(getSpi()); if (log.isInfoEnabled()) log.info("Added new node to topology: " + node); @@ -3128,8 +3122,6 @@ private void body0() throws InterruptedException { } case EVT_CLIENT_NODE_RECONNECTED: { - clientNodesJoinedCtr.increment(); - if (log.isInfoEnabled()) log.info("Client node reconnected to topology: " + node); diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java index c9492bb0b8608..0da69bce6bf44 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java @@ -170,4 +170,14 @@ public interface DiscoverySpi extends IgniteSpi { * @throws IllegalStateException If discovery SPI has not started. */ public boolean isClientMode() throws IllegalStateException; + + /** + * Notifies the discovery SPI that a client node has joined the topology. + *

+ * Default implementation does nothing. SPI implementations that support + * client-node-joined metrics should override this method. + */ + default public void onClientNodeJoined() { + // No-op by default. + } } diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java index 19903ffb5fb17..db5cb838c4ecb 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java @@ -1360,6 +1360,11 @@ public long getNodesJoined() { return stats.joinedNodesCount(); } + /** {@inheritDoc} */ + @Override public void onClientNodeJoined() { + stats.onClientNodeJoined(); + } + /** * Gets left nodes count. * diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java index 82f30d11c6834..e3681bdee5dbd 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java @@ -46,6 +46,9 @@ public class TcpDiscoveryStatistics { /** Failed nodes count. */ private final IntMetricImpl failedNodesCnt; + /** Joined client nodes count. */ + private final IntMetricImpl joinedClientNodesCnt; + /** Left nodes count. */ private final IntMetricImpl leftNodesCnt; @@ -82,6 +85,9 @@ public TcpDiscoveryStatistics() { failedNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "FailedNodes"), "Failed nodes count"); + joinedClientNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "JoinedClientNodes"), + "Joined client nodes count."); + leftNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "LeftNodes"), "Left nodes count"); pendingMsgsRegistered = new IntMetricImpl(metricName(DISCO_METRICS, "PendingMessagesRegistered"), @@ -103,6 +109,7 @@ public void registerMetrics(MetricRegistryImpl discoReg) { discoReg.register(joinedNodesCnt); discoReg.register(failedNodesCnt); + discoReg.register(joinedClientNodesCnt); discoReg.register(leftNodesCnt); discoReg.register(pendingMsgsRegistered); discoReg.register(rejectedSslConnectionsCnt); @@ -115,6 +122,13 @@ public void onNodeJoined() { joinedNodesCnt.increment(); } + /** + * Increments joined client nodes count. + */ + public void onClientNodeJoined() { + joinedClientNodesCnt.increment(); + } + /** * Increments left nodes count. */ @@ -292,6 +306,15 @@ public int joinedNodesCount() { return joinedNodesCnt.value(); } + /** + * Gets joined client nodes count. + * + * @return Joined client nodes count. + */ + public int joinedClientNodesCount() { + return joinedClientNodesCnt.value(); + } + /** * Gets nodes left count. * @@ -327,6 +350,7 @@ public synchronized void clear() { crdSinceTs.set(0); failedNodesCnt.reset(); joinedNodesCnt.reset(); + joinedClientNodesCnt.reset(); leftNodesCnt.reset(); maxMsgProcTime = 0; pendingMsgsRegistered.reset(); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java index 6561c13a0ec96..b72313d0c165c 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java @@ -22,18 +22,20 @@ import org.apache.ignite.metric.MetricRegistry; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; -import org.apache.ignite.spi.metric.LongMetric; +import org.apache.ignite.spi.metric.IntMetric; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.junit.Test; -import static org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.CLIENT_NODES_JOINED; import static org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.DISCO_METRICS; import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; /** - * Tests the CLIENT_NODES_JOINED metric in the discovery metrics registry. + * Tests the JOINED_CLIENT_NODES metric in the discovery metrics registry. */ public class GridDiscoveryManagerClientMetricTest extends GridCommonAbstractTest { + /** */ + private static final String JOINED_CLIENT_NODES = "JoinedClientNodes"; + /** */ private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); @@ -51,7 +53,7 @@ public class GridDiscoveryManagerClientMetricTest extends GridCommonAbstractTest } /** - * Verifies that the CLIENT_NODES_JOINED counter increments + * Verifies that the JOINED_CLIENT_NODES counter increments * when client nodes join the topology. * * @throws Exception If fails. @@ -71,11 +73,11 @@ public void testClientNodesJoinedMetric() throws Exception { assertNotNull(discoReg); - LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - assertNotNull("Metric " + CLIENT_NODES_JOINED + " not found", ctr); + assertNotNull("Metric " + JOINED_CLIENT_NODES + " not found", ctr); - assertEquals(0L, ctr.value()); + assertEquals(0, ctr.value()); } // Start one client node. @@ -87,9 +89,9 @@ public void testClientNodesJoinedMetric() throws Exception { MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - assertTrue(waitForCondition(() -> ctr.value() == 1L, getTestTimeout())); + assertTrue(waitForCondition(() -> ctr.value() == 1, getTestTimeout())); } // Start a second client node. @@ -101,9 +103,9 @@ public void testClientNodesJoinedMetric() throws Exception { MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - assertTrue(waitForCondition(() -> ctr.value() == 2L, getTestTimeout())); + assertTrue(waitForCondition(() -> ctr.value() == 2, getTestTimeout())); } } finally { @@ -112,7 +114,7 @@ public void testClientNodesJoinedMetric() throws Exception { } /** - * Verifies that the CLIENT_NODES_JOINED metric is accessible + * Verifies that the JOINED_CLIENT_NODES metric is accessible * via the metric registry and exposes proper name and description. * * @throws Exception If fails. @@ -124,13 +126,13 @@ public void testMetricMetadata() throws Exception { MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - LongMetric ctr = discoReg.findMetric(CLIENT_NODES_JOINED); + IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); assertNotNull(ctr); - assertEquals(DISCO_METRICS + "." + CLIENT_NODES_JOINED, ctr.name()); + assertEquals(DISCO_METRICS + "." + JOINED_CLIENT_NODES, ctr.name()); - assertEquals("Count of client nodes joined to topology", ctr.description()); + assertEquals("Joined client nodes count.", ctr.description()); } finally { stopAllGrids(); diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java index 37b963757773f..a859c3ee20af3 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java @@ -431,6 +431,11 @@ public DiscoverySpiNodeAuthenticator getAuthenticator() { return impl.localNode().isClient(); } + /** {@inheritDoc} */ + @Override public void onClientNodeJoined() { + stats.onClientNodeJoined(); + } + /** {@inheritDoc} */ @Override public void spiStart(@Nullable String igniteInstanceName) throws IgniteSpiException { startStopwatch(); diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java index 958974d0db6f6..7ec9d3d85a74e 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java @@ -40,6 +40,10 @@ public class ZookeeperDiscoveryStatistics { private final LongAdderMetric leftNodesCnt = new LongAdderMetric(metricName(DISCO_METRICS, "LeftNodes"), "Left nodes count"); + /** */ + private final LongAdderMetric joinedClientNodesCnt = new LongAdderMetric(metricName(DISCO_METRICS, "JoinedClientNodes"), + "Joined client nodes count."); + /** Communication error count. */ private final LongAdderMetric commErrCnt = new LongAdderMetric(metricName(DISCO_METRICS, "CommunicationErrors"), "Communication errors count"); @@ -54,6 +58,7 @@ public class ZookeeperDiscoveryStatistics { public void registerMetrics(MetricRegistryImpl discoReg) { discoReg.register(joinedNodesCnt); discoReg.register(failedNodesCnt); + discoReg.register(joinedClientNodesCnt); discoReg.register(leftNodesCnt); discoReg.register(commErrCnt); discoReg.register(topVer); @@ -74,6 +79,11 @@ public long leftNodesCnt() { return leftNodesCnt.value(); } + /** */ + public long joinedClientNodesCnt() { + return joinedClientNodesCnt.value(); + } + /** */ public long commErrorCount() { return commErrCnt.value(); @@ -84,6 +94,11 @@ public void onNodeJoined() { joinedNodesCnt.increment(); } + /** */ + public void onClientNodeJoined() { + joinedClientNodesCnt.increment(); + } + /** */ public void onNodeFailed() { failedNodesCnt.increment(); From 4cc4a5c84bf67a8b01c591dff34449e15593d992 Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Fri, 30 Oct 2026 14:41:35 +0300 Subject: [PATCH 3/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../discovery/GridDiscoveryManager.java | 2 ++ .../ZookeeperDiscoveryStatistics.java | 4 +-- .../internal/ZookeeperDiscoveryMiscTest.java | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index 31254b9087857..8cc3ef65ed55f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -1412,6 +1412,8 @@ private void onClientNodeJoined(DiscoverySpi spi) { } /** + * Logs grid size for license compliance. + * * @param topVer Topology version. * @param evtType Event type. * @param evtNode Event node. diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java index 7ec9d3d85a74e..bc6ec547f637f 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java @@ -41,8 +41,8 @@ public class ZookeeperDiscoveryStatistics { "Left nodes count"); /** */ - private final LongAdderMetric joinedClientNodesCnt = new LongAdderMetric(metricName(DISCO_METRICS, "JoinedClientNodes"), - "Joined client nodes count."); + private final LongAdderMetric joinedClientNodesCnt = new LongAdderMetric( + metricName(DISCO_METRICS, "JoinedClientNodes"), "Joined client nodes count."); /** Communication error count. */ private final LongAdderMetric commErrCnt = new LongAdderMetric(metricName(DISCO_METRICS, "CommunicationErrors"), diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java index a8acf9b6faf4a..e68cdcd03a375 100644 --- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java +++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java @@ -265,6 +265,34 @@ public void testMbean() throws Exception { } } + /** + * @throws Exception if failed. + */ + @Test + public void testJoinedClientNodesMetric() throws Exception { + IgniteEx srv = startGrid(0); + + try { + MetricRegistry discoReg = srv.context().metric().registry(DISCO_METRICS); + + LongMetric ctr = discoReg.findMetric("JoinedClientNodes"); + + assertNotNull("Metric JoinedClientNodes not found", ctr); + assertEquals(0L, ctr.value()); + + startClientGrid(1); + + assertEquals(1L, ctr.value()); + + startClientGrid(2); + + assertEquals(2L, ctr.value()); + } + finally { + stopAllGrids(); + } + } + /** * @throws Exception If failed. */ From 9b4fb01832019d8d18f30acbc4c022fa0fa86080 Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Fri, 30 Oct 2026 15:25:42 +0300 Subject: [PATCH 4/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java index 0da69bce6bf44..1b185b8038224 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java @@ -177,7 +177,7 @@ public interface DiscoverySpi extends IgniteSpi { * Default implementation does nothing. SPI implementations that support * client-node-joined metrics should override this method. */ - default public void onClientNodeJoined() { + default void onClientNodeJoined() { // No-op by default. } } From 0f9cd2d572b986313ae09653119a6212b869c18c Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Mon, 2 Nov 2026 11:28:46 +0300 Subject: [PATCH 5/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../discovery/GridDiscoveryManager.java | 12 -- .../ignite/spi/discovery/DiscoverySpi.java | 10 -- .../ignite/spi/discovery/tcp/ClientImpl.java | 3 + .../ignite/spi/discovery/tcp/ServerImpl.java | 3 + .../spi/discovery/tcp/TcpDiscoverySpi.java | 5 - .../tcp/internal/TcpDiscoveryStatistics.java | 9 -- .../GridDiscoveryManagerClientMetricTest.java | 141 ------------------ .../tcp/TcpDiscoverySpiMBeanTest.java | 3 + .../testsuites/IgniteKernalSelfTestSuite.java | 2 - .../discovery/zk/ZookeeperDiscoverySpi.java | 5 - .../zk/internal/ZookeeperDiscoveryImpl.java | 3 + .../ZookeeperDiscoveryStatistics.java | 5 - .../internal/ZookeeperDiscoveryMiscTest.java | 28 ---- 13 files changed, 12 insertions(+), 217 deletions(-) delete mode 100644 modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index 8cc3ef65ed55f..d8f9a4e428f49 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -1402,15 +1402,6 @@ public void ackTopology(long topVer, int evtType, ClusterNode evtNode) { ackTopology(topVer, evtType, evtNode, false); } - /** - * Notifies the discovery SPI that a client node has joined the topology. - * - * @param spi Discovery SPI. - */ - private void onClientNodeJoined(DiscoverySpi spi) { - spi.onClientNodeJoined(); - } - /** * Logs grid size for license compliance. * @@ -3093,9 +3084,6 @@ private void body0() throws InterruptedException { U.warn(log, e.getMessage()); // We a have well-formed attribute warning here. } - if (node.isClient()) - onClientNodeJoined(getSpi()); - if (log.isInfoEnabled()) log.info("Added new node to topology: " + node); diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java index 1b185b8038224..c9492bb0b8608 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/DiscoverySpi.java @@ -170,14 +170,4 @@ public interface DiscoverySpi extends IgniteSpi { * @throws IllegalStateException If discovery SPI has not started. */ public boolean isClientMode() throws IllegalStateException; - - /** - * Notifies the discovery SPI that a client node has joined the topology. - *

- * Default implementation does nothing. SPI implementations that support - * client-node-joined metrics should override this method. - */ - default void onClientNodeJoined() { - // No-op by default. - } } diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java index ddf9a61102e6c..731a3724676b3 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ClientImpl.java @@ -2334,6 +2334,9 @@ else if (log.isDebugEnabled()) notifyDiscovery(EVT_NODE_JOINED, topVer, node, top); spi.stats.onNodeJoined(); + + if (node.isClient()) + spi.stats.onClientNodeJoined(); } } else { diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java index 9a87615ffbbe0..4c5e3c72a42ce 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java @@ -5075,6 +5075,9 @@ private void processNodeAddFinishedMessage(TcpDiscoveryNodeAddFinishedMessage ms if (msg.verified() && !locNodeId.equals(nodeId) && state != CONNECTING && fireEvt) { spi.stats.onNodeJoined(); + if (node.isClient()) + spi.stats.onClientNodeJoined(); + // Make sure that node with greater order will never get EVT_NODE_JOINED // on node with less order. assert node.internalOrder() > locNode.internalOrder() : "Invalid order [node=" + node + diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java index f1550c60dd583..1ec99c1b0382c 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java @@ -1360,11 +1360,6 @@ public long getNodesJoined() { return stats.joinedNodesCount(); } - /** {@inheritDoc} */ - @Override public void onClientNodeJoined() { - stats.onClientNodeJoined(); - } - /** * Gets left nodes count. * diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java index e1c3c6c0be931..42c4ea2e4e2c6 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java @@ -334,15 +334,6 @@ public int joinedNodesCount() { return joinedNodesCnt.value(); } - /** - * Gets joined client nodes count. - * - * @return Joined client nodes count. - */ - public int joinedClientNodesCount() { - return joinedClientNodesCnt.value(); - } - /** * Gets nodes left count. * diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java deleted file mode 100644 index b72313d0c165c..0000000000000 --- a/modules/core/src/test/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManagerClientMetricTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.managers.discovery; - -import org.apache.ignite.configuration.IgniteConfiguration; -import org.apache.ignite.internal.IgniteEx; -import org.apache.ignite.metric.MetricRegistry; -import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; -import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; -import org.apache.ignite.spi.metric.IntMetric; -import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; -import org.junit.Test; - -import static org.apache.ignite.internal.managers.discovery.GridDiscoveryManager.DISCO_METRICS; -import static org.apache.ignite.testframework.GridTestUtils.waitForCondition; - -/** - * Tests the JOINED_CLIENT_NODES metric in the discovery metrics registry. - */ -public class GridDiscoveryManagerClientMetricTest extends GridCommonAbstractTest { - /** */ - private static final String JOINED_CLIENT_NODES = "JoinedClientNodes"; - - /** */ - private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); - - /** {@inheritDoc} */ - @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { - IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); - - TcpDiscoverySpi spi = new TcpDiscoverySpi(); - - spi.setIpFinder(IP_FINDER); - - cfg.setDiscoverySpi(spi); - - return cfg; - } - - /** - * Verifies that the JOINED_CLIENT_NODES counter increments - * when client nodes join the topology. - * - * @throws Exception If fails. - */ - @Test - public void testClientNodesJoinedMetric() throws Exception { - int srvCnt = 2; - - try { - startGrids(srvCnt); - - // Initially no clients have joined. - for (int i = 0; i < srvCnt; i++) { - IgniteEx grid = grid(i); - - MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - - assertNotNull(discoReg); - - IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - - assertNotNull("Metric " + JOINED_CLIENT_NODES + " not found", ctr); - - assertEquals(0, ctr.value()); - } - - // Start one client node. - startClientGrid("client-0"); - - // Both servers should see 1 client joined. - for (int i = 0; i < srvCnt; i++) { - IgniteEx grid = grid(i); - - MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - - IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - - assertTrue(waitForCondition(() -> ctr.value() == 1, getTestTimeout())); - } - - // Start a second client node. - startClientGrid("client-1"); - - // Both servers should now see 2 clients joined. - for (int i = 0; i < srvCnt; i++) { - IgniteEx grid = grid(i); - - MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - - IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - - assertTrue(waitForCondition(() -> ctr.value() == 2, getTestTimeout())); - } - } - finally { - stopAllGrids(); - } - } - - /** - * Verifies that the JOINED_CLIENT_NODES metric is accessible - * via the metric registry and exposes proper name and description. - * - * @throws Exception If fails. - */ - @Test - public void testMetricMetadata() throws Exception { - try { - IgniteEx grid = startGrid(0); - - MetricRegistry discoReg = grid.context().metric().registry(DISCO_METRICS); - - IntMetric ctr = discoReg.findMetric(JOINED_CLIENT_NODES); - - assertNotNull(ctr); - - assertEquals(DISCO_METRICS + "." + JOINED_CLIENT_NODES, ctr.name()); - - assertEquals("Joined client nodes count.", ctr.description()); - } - finally { - stopAllGrids(); - } - } -} diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java index 097ee09b4423e..3e7ed81e36f9b 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java @@ -130,6 +130,9 @@ public void testMBean() throws Exception { assertEquals((cnt - 1) - i, bean.getNodesJoined()); assertEquals((cnt - 1) - i, discoReg.findMetric("JoinedNodes").value()); + int expectedClientJoins = (i < cliIdx) ? 1 : 0; + assertEquals(expectedClientJoins, discoReg.findMetric("JoinedClientNodes").value()); + assertEquals(0L, bean.getNodesFailed()); assertEquals(0, discoReg.findMetric("FailedNodes").value()); diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java index ac1f57d64e42f..dd6dd06042cb6 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java @@ -47,7 +47,6 @@ import org.apache.ignite.internal.managers.deployment.GridDeploymentManagerStopSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAliveCacheSelfTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerAttributesSelfTest; -import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerClientMetricTest; import org.apache.ignite.internal.managers.discovery.GridDiscoveryManagerWalModeConsistencyTest; import org.apache.ignite.internal.managers.discovery.IgniteTopologyPrintFormatSelfTest; import org.apache.ignite.internal.managers.events.GridEventStorageManagerInternalEventsSelfTest; @@ -93,7 +92,6 @@ GridManagerStopSelfTest.class, GridDiscoveryManagerAttributesSelfTest.class, GridDiscoveryManagerAliveCacheSelfTest.class, - GridDiscoveryManagerClientMetricTest.class, GridDiscoveryManagerWalModeConsistencyTest.class, GridDiscoveryEventSelfTest.class, GridPortProcessorSelfTest.class, diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java index a859c3ee20af3..37b963757773f 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpi.java @@ -431,11 +431,6 @@ public DiscoverySpiNodeAuthenticator getAuthenticator() { return impl.localNode().isClient(); } - /** {@inheritDoc} */ - @Override public void onClientNodeJoined() { - stats.onClientNodeJoined(); - } - /** {@inheritDoc} */ @Override public void spiStart(@Nullable String igniteInstanceName) throws IgniteSpiException { startStopwatch(); diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java index faadb17cdd925..9d10c615bc5c4 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java @@ -3586,6 +3586,9 @@ private void notifyNodeJoin(ZkJoinedNodeEvtData joinedEvtData, ZkJoiningNodeData ).get(); stats.onNodeJoined(); + + if (joinedNode.isClient()) + stats.onClientNodeJoined(); } /** diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java index bc6ec547f637f..1f4c3c2d5f9a1 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java @@ -79,11 +79,6 @@ public long leftNodesCnt() { return leftNodesCnt.value(); } - /** */ - public long joinedClientNodesCnt() { - return joinedClientNodesCnt.value(); - } - /** */ public long commErrorCount() { return commErrCnt.value(); diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java index e68cdcd03a375..a8acf9b6faf4a 100644 --- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java +++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java @@ -265,34 +265,6 @@ public void testMbean() throws Exception { } } - /** - * @throws Exception if failed. - */ - @Test - public void testJoinedClientNodesMetric() throws Exception { - IgniteEx srv = startGrid(0); - - try { - MetricRegistry discoReg = srv.context().metric().registry(DISCO_METRICS); - - LongMetric ctr = discoReg.findMetric("JoinedClientNodes"); - - assertNotNull("Metric JoinedClientNodes not found", ctr); - assertEquals(0L, ctr.value()); - - startClientGrid(1); - - assertEquals(1L, ctr.value()); - - startClientGrid(2); - - assertEquals(2L, ctr.value()); - } - finally { - stopAllGrids(); - } - } - /** * @throws Exception If failed. */ From bffcfe6d52d915a82e43112505d25cd0e8acc5ed Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Mon, 2 Nov 2026 12:18:23 +0300 Subject: [PATCH 6/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../discovery/zk/internal/ZookeeperDiscoveryMiscTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java index a8acf9b6faf4a..16e8d53dca097 100644 --- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java +++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java @@ -251,7 +251,7 @@ public void testMbean() throws Exception { assertEquals(cnt - i - 1, bean.getNodesJoined()); assertEquals(cnt - i - 1, discoReg.findMetric("JoinedNodes").value()); - Arrays.asList("LeftNodes", "FailedNodes", "CommunicationErrors").forEach(name -> { + Arrays.asList("LeftNodes", "FailedNodes", "CommunicationErrors", "JoinedClientNodes").forEach(name -> { assertEquals(0, discoReg.findMetric(name).value()); }); @@ -304,6 +304,9 @@ public void testClientNodesStatus() throws Exception { assertEquals(1, node.cluster().forServers().nodes().size()); } + MetricRegistry srvReg = grid(0).context().metric().registry(DISCO_METRICS); + assertEquals(1L, srvReg.findMetric("JoinedClientNodes").value()); + startGrid(2); startClientGrid(3); From aae7a8d9d3aa75c9d659781418b9e14165b052c1 Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Tue, 3 Nov 2026 00:37:37 +0300 Subject: [PATCH 7/8] IGNITE-29222 Add JoinedClientNodes monitoring metric to track client node topology join events --- .../spi/discovery/tcp/internal/TcpDiscoveryStatistics.java | 4 +--- .../ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java | 3 +-- .../spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java index 42c4ea2e4e2c6..3f62e9eddf240 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java @@ -140,9 +140,7 @@ public void onNodeJoined() { joinedNodesCnt.increment(); } - /** - * Increments joined client nodes count. - */ + /** Increments joined client nodes count. */ public void onClientNodeJoined() { joinedClientNodesCnt.increment(); } diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java index 3e7ed81e36f9b..6159dc24e698b 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpiMBeanTest.java @@ -130,8 +130,7 @@ public void testMBean() throws Exception { assertEquals((cnt - 1) - i, bean.getNodesJoined()); assertEquals((cnt - 1) - i, discoReg.findMetric("JoinedNodes").value()); - int expectedClientJoins = (i < cliIdx) ? 1 : 0; - assertEquals(expectedClientJoins, discoReg.findMetric("JoinedClientNodes").value()); + assertEquals((i < cliIdx) ? 1 : 0, discoReg.findMetric("JoinedClientNodes").value()); assertEquals(0L, bean.getNodesFailed()); assertEquals(0, discoReg.findMetric("FailedNodes").value()); diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java index 16e8d53dca097..f55b8090ad44b 100644 --- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java +++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java @@ -304,8 +304,7 @@ public void testClientNodesStatus() throws Exception { assertEquals(1, node.cluster().forServers().nodes().size()); } - MetricRegistry srvReg = grid(0).context().metric().registry(DISCO_METRICS); - assertEquals(1L, srvReg.findMetric("JoinedClientNodes").value()); + assertEquals(1L, grid(0).context().metric().registry(DISCO_METRICS).findMetric("JoinedClientNodes").value()); startGrid(2); From ccab3d343b3c351eaac85233f3f36928b175c538 Mon Sep 17 00:00:00 2001 From: "baranov.e.g" Date: Tue, 3 Nov 2026 09:06:06 +0300 Subject: [PATCH 8/8] IGNITE-29222 Add ClientNodesJoined monitoring metric to track client node topology join events --- .../spi/discovery/tcp/internal/TcpDiscoveryStatistics.java | 3 +-- .../discovery/zk/internal/ZookeeperDiscoveryStatistics.java | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java index 3f62e9eddf240..d588bf851c653 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/internal/TcpDiscoveryStatistics.java @@ -91,8 +91,7 @@ public TcpDiscoveryStatistics() { failedNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "FailedNodes"), "Failed nodes count"); - joinedClientNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "JoinedClientNodes"), - "Joined client nodes count."); + joinedClientNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "JoinedClientNodes"), "Joined client nodes count."); leftNodesCnt = new IntMetricImpl(metricName(DISCO_METRICS, "LeftNodes"), "Left nodes count"); diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java index 1f4c3c2d5f9a1..e0df3c0fa31ea 100644 --- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java +++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryStatistics.java @@ -41,8 +41,8 @@ public class ZookeeperDiscoveryStatistics { "Left nodes count"); /** */ - private final LongAdderMetric joinedClientNodesCnt = new LongAdderMetric( - metricName(DISCO_METRICS, "JoinedClientNodes"), "Joined client nodes count."); + private final LongAdderMetric joinedClientNodesCnt = new LongAdderMetric(metricName(DISCO_METRICS, "JoinedClientNodes"), + "Joined client nodes count."); /** Communication error count. */ private final LongAdderMetric commErrCnt = new LongAdderMetric(metricName(DISCO_METRICS, "CommunicationErrors"),