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

NSAmelchev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 0f357eb7e0b IGNITE-28714 Add data center ID to client connections 
system view (#13379)
0f357eb7e0b is described below

commit 0f357eb7e0bbd5e595f49e7a7caf25094d2485c5
Author: Nikita Amelchev <[email protected]>
AuthorDate: Wed Jul 22 14:23:47 2026 +0300

    IGNITE-28714 Add data center ID to client connections system view (#13379)
---
 docs/_docs/clustering/multi-data-center.adoc       | 10 ++++--
 docs/_docs/monitoring-metrics/system-views.adoc    |  1 +
 .../ignite/jdbc/thin/JdbcThinMetadataSelfTest.java |  1 +
 .../apache/ignite/util/SystemViewCommandTest.java  |  4 ++-
 .../spi/systemview/view/ClientConnectionView.java  | 14 ++++++++
 .../internal/metric/SystemViewClientTest.java      | 41 ++++++++++++++++++++++
 .../cache/metric/SqlViewExporterSpiTest.java       | 13 +++++--
 .../client/thin/ClientChannelConfiguration.java    |  9 +++--
 .../internal/client/thin/ReliableChannelImpl.java  | 37 ++++++++++++++++---
 9 files changed, 116 insertions(+), 14 deletions(-)

diff --git a/docs/_docs/clustering/multi-data-center.adoc 
b/docs/_docs/clustering/multi-data-center.adoc
index e37dca24857..a5a37e25b1f 100644
--- a/docs/_docs/clustering/multi-data-center.adoc
+++ b/docs/_docs/clustering/multi-data-center.adoc
@@ -249,6 +249,10 @@ This behavior applies to both full and historical 
rebalance.
 
 == Monitoring
 
-The data center ID is exposed in the `NODES` system view as part of node 
information.
-For client nodes, the `io.discovery.ClientRouterNodeId` metric exposes the ID 
of the server node used as
-the discovery router.
+Use the `NODES` system view to check the data center IDs of cluster nodes, and 
the `CLIENT_CONNECTIONS` view to check
+the data center IDs of thin-client connections. This makes it easy to spot 
clients with a wrong or missing ID.
+
+For Java thin clients, the `IGNITE_DATA_CENTER_ID` system property takes 
precedence over the user attribute of the same
+name.
+
+For a client node, the `io.discovery.ClientRouterNodeId` metric identifies the 
server node used as the discovery router.
diff --git a/docs/_docs/monitoring-metrics/system-views.adoc 
b/docs/_docs/monitoring-metrics/system-views.adoc
index 9f3a4fc7424..4edf9e574da 100644
--- a/docs/_docs/monitoring-metrics/system-views.adoc
+++ b/docs/_docs/monitoring-metrics/system-views.adoc
@@ -439,6 +439,7 @@ This view exposes information about currently opened client 
connections: JDBC, O
 |TYPE | string |  Type of the connection
 |USER | string |  User name
 |VERSION | string |  Protocol version
+|DATA_CENTER_ID | string | Effective data center ID reported by the client
 |===
 
 == CLIENT_CONNECTION_ATTRIBUTES
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
index 075c75161cf..13e5438399a 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinMetadataSelfTest.java
@@ -950,6 +950,7 @@ public class JdbcThinMetadataSelfTest extends 
JdbcThinAbstractSelfTest {
                 "SYS.CLIENT_CONNECTIONS.TYPE.null",
                 "SYS.CLIENT_CONNECTIONS.USER.null",
                 "SYS.CLIENT_CONNECTIONS.VERSION.null",
+                "SYS.CLIENT_CONNECTIONS.DATA_CENTER_ID.null",
                 "SYS.CLIENT_CONNECTION_ATTRIBUTES.CONNECTION_ID.null",
                 "SYS.CLIENT_CONNECTION_ATTRIBUTES.NAME.null",
                 "SYS.CLIENT_CONNECTION_ATTRIBUTES.VALUE.null",
diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
index 42bbfa10683..2e950c2eb35 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/util/SystemViewCommandTest.java
@@ -601,7 +601,9 @@ public class SystemViewCommandTest extends 
GridCommandHandlerClusterByClassAbstr
                 InetSocketAddress.class.getName()),
             asList("TYPE", "CLIENT_CONNECTIONS", SCHEMA_SYS, "null", "true", 
"-1", "-1", String.class.getName()),
             asList("USER", "CLIENT_CONNECTIONS", SCHEMA_SYS, "null", "true", 
"-1", "-1", String.class.getName()),
-            asList("VERSION", "CLIENT_CONNECTIONS", SCHEMA_SYS, "null", 
"true", "-1", "-1", String.class.getName())
+            asList("VERSION", "CLIENT_CONNECTIONS", SCHEMA_SYS, "null", 
"true", "-1", "-1", String.class.getName()),
+            asList("DATA_CENTER_ID", "CLIENT_CONNECTIONS", SCHEMA_SYS, "null", 
"true", "-1", "-1",
+                String.class.getName())
         ));
 
         Set<List<String>> sqlViewColumnsView = systemView(ignite0, 
SQL_VIEW_COLS_VIEW).stream()
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionView.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionView.java
index 834c250b669..6ad4d299f13 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionView.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/systemview/view/ClientConnectionView.java
@@ -25,10 +25,12 @@ import 
org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext;
 import org.apache.ignite.internal.processors.odbc.odbc.OdbcConnectionContext;
 import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import org.apache.ignite.internal.processors.security.SecurityContext;
+import org.apache.ignite.internal.systemview.Order;
 import org.apache.ignite.internal.systemview.SystemViewDescriptor;
 import org.apache.ignite.internal.util.nio.GridNioSession;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_CENTER_ID;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.CONN_CTX_META_KEY;
 
 /**
@@ -49,6 +51,7 @@ public class ClientConnectionView {
     }
 
     /** @return Connection id. */
+    @Order(0)
     public long connectionId() {
         if (ctx == null)
             return -1;
@@ -57,6 +60,7 @@ public class ClientConnectionView {
     }
 
     /** @return Connection type. */
+    @Order(3)
     public String type() {
         if (ctx == null)
             return null;
@@ -72,16 +76,19 @@ public class ClientConnectionView {
     }
 
     /** @return Connection local address. */
+    @Order(1)
     public InetSocketAddress localAddress() {
         return ses.localAddress();
     }
 
     /** @return Connection remote address. */
+    @Order(2)
     public InetSocketAddress remoteAddress() {
         return ses.remoteAddress();
     }
 
     /** @return User name. */
+    @Order(4)
     public String user() {
         SecurityContext secCtx = ctx == null ? null : ctx.securityContext();
 
@@ -92,6 +99,7 @@ public class ClientConnectionView {
     }
 
     /** @return Protocol version. */
+    @Order(5)
     public String version() {
         if (ctx == null)
             return null;
@@ -105,4 +113,10 @@ public class ClientConnectionView {
 
         return ver == null ? null : ver.asString();
     }
+
+    /** @return Client data center ID. */
+    @Order(6)
+    @Nullable public String dataCenterId() {
+        return ctx == null ? null : 
ctx.attributes().get(IGNITE_DATA_CENTER_ID);
+    }
 }
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewClientTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewClientTest.java
index f1448d74f77..db940f0050e 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewClientTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/metric/SystemViewClientTest.java
@@ -18,7 +18,9 @@
 package org.apache.ignite.internal.metric;
 
 import java.sql.Connection;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Properties;
 import org.apache.ignite.IgniteJdbcThinDriver;
 import org.apache.ignite.Ignition;
@@ -35,8 +37,10 @@ import 
org.apache.ignite.spi.systemview.view.ClientConnectionView;
 import org.apache.ignite.spi.systemview.view.FiltrableSystemView;
 import org.apache.ignite.spi.systemview.view.SystemView;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
 import org.junit.Test;
 
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_CENTER_ID;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerProcessor.CLI_CONN_ATTR_VIEW;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerProcessor.CLI_CONN_VIEW;
 import static org.apache.ignite.internal.util.lang.GridFunc.identity;
@@ -88,6 +92,43 @@ public class SystemViewClientTest extends 
SystemViewAbstractTest {
         }
     }
 
+    /** */
+    @Test
+    @WithSystemProperty(key = IGNITE_DATA_CENTER_ID, value = "server-dc")
+    public void testClientConnectionDataCenterId() throws Exception {
+        try (IgniteEx g0 = startGrid(0)) {
+            assertEquals("server-dc", g0.localNode().dataCenterId());
+
+            System.clearProperty(IGNITE_DATA_CENTER_ID);
+
+            SystemView<ClientConnectionView> conns = 
g0.context().systemView().view(CLI_CONN_VIEW);
+
+            Map<String, String> userAttrs = 
Collections.singletonMap(IGNITE_DATA_CENTER_ID, "user-dc");
+
+            try (IgniteClient ignored = Ignition.startClient(
+                new ClientConfiguration()
+                    .setAddresses(Config.SERVER)
+                    .setUserAttributes(userAttrs))
+            ) {
+                assertEquals("user-dc", 
conns.iterator().next().dataCenterId());
+            }
+
+            assertTrue(GridTestUtils.waitForCondition(() -> conns.size() == 0, 
5_000));
+
+            System.setProperty(IGNITE_DATA_CENTER_ID, "property-dc");
+
+            try (
+                IgniteClient ignored = Ignition.startClient(new 
ClientConfiguration()
+                    .setAddresses(Config.SERVER)
+                    .setUserAttributes(userAttrs))
+            ) {
+
+                assertEquals("property-dc", 
conns.iterator().next().dataCenterId());
+                assertEquals("user-dc", userAttrs.get(IGNITE_DATA_CENTER_ID));
+            }
+        }
+    }
+
     /** */
     @Test
     public void testClientConnectionAttributes() throws Exception {
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
index e98770d4a5b..848e733d18f 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/metric/SqlViewExporterSpiTest.java
@@ -86,6 +86,7 @@ import org.apache.ignite.transactions.Transaction;
 import org.junit.Test;
 
 import static java.util.Arrays.asList;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_DATA_CENTER_ID;
 import static 
org.apache.ignite.internal.metric.SystemViewQueriesTest.TEST_PREDICATE;
 import static 
org.apache.ignite.internal.metric.SystemViewQueriesTest.TEST_TRANSFORMER;
 import static 
org.apache.ignite.internal.processors.cache.GridCacheUtils.cacheGroupId;
@@ -323,11 +324,16 @@ public class SqlViewExporterSpiTest extends 
AbstractExporterSpiTest {
 
         int port = 
ignite0.configuration().getClientConnectorConfiguration().getPort();
 
-        try (IgniteClient client = Ignition.startClient(new 
ClientConfiguration().setAddresses(host + ":" + port))) {
+        String dcId = "dc0";
+
+        try (IgniteClient client = Ignition.startClient(new 
ClientConfiguration().setAddresses(host + ":" + port)
+            .setUserAttributes(F.asMap(IGNITE_DATA_CENTER_ID, dcId)))) {
             try (Connection conn = new 
IgniteJdbcThinDriver().connect("jdbc:ignite:thin://" + host, new Properties())) 
{
-                List<List<?>> conns = execute(ignite0, "SELECT * FROM 
SYS.CLIENT_CONNECTIONS");
+                List<List<?>> conns = execute(ignite0, "SELECT TYPE, 
DATA_CENTER_ID FROM SYS.CLIENT_CONNECTIONS");
 
                 assertEquals(2, conns.size());
+                assertTrue(conns.stream().anyMatch(row -> 
"THIN".equals(row.get(0)) && dcId.equals(row.get(1))));
+                assertTrue(conns.stream().anyMatch(row -> 
"JDBC".equals(row.get(0)) && row.get(1) == null));
             }
         }
     }
@@ -569,7 +575,8 @@ public class SqlViewExporterSpiTest extends 
AbstractExporterSpiTest {
             asList("REMOTE_ADDRESS", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, 
true, -1, -1, InetSocketAddress.class.getName()),
             asList("TYPE", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, true, -1, 
-1, String.class.getName()),
             asList("USER", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, true, -1, 
-1, String.class.getName()),
-            asList("VERSION", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, true, 
-1, -1, String.class.getName())
+            asList("VERSION", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, true, 
-1, -1, String.class.getName()),
+            asList("DATA_CENTER_ID", "CLIENT_CONNECTIONS", SCHEMA_SYS, null, 
true, -1, -1, String.class.getName())
         );
 
         List<List<?>> res = execute(ignite0, "SELECT * FROM SYS.VIEW_COLUMNS 
WHERE VIEW_NAME = 'CLIENT_CONNECTIONS'");
diff --git 
a/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ClientChannelConfiguration.java
 
b/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ClientChannelConfiguration.java
index b0e9910178e..2e3caddc643 100644
--- 
a/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ClientChannelConfiguration.java
+++ 
b/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ClientChannelConfiguration.java
@@ -24,7 +24,6 @@ import java.util.Map;
 import java.util.concurrent.Executor;
 import javax.cache.configuration.Factory;
 import javax.net.ssl.SSLContext;
-
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.client.SslMode;
 import org.apache.ignite.client.SslProtocol;
@@ -123,7 +122,11 @@ final class ClientChannelConfiguration {
      * Constructor.
      */
     @SuppressWarnings("UnnecessaryThis")
-    ClientChannelConfiguration(ClientConfiguration cfg, 
List<InetSocketAddress> addrs) {
+    ClientChannelConfiguration(
+        ClientConfiguration cfg,
+        List<InetSocketAddress> addrs,
+        Map<String, String> userAttrs
+    ) {
         this.sslMode = cfg.getSslMode();
         this.tcpNoDelay = cfg.isTcpNoDelay();
         this.handshakeTimeout = cfg.getHandshakeTimeout();
@@ -145,7 +148,7 @@ final class ClientChannelConfiguration {
         this.reconnectThrottlingPeriod = cfg.getReconnectThrottlingPeriod();
         this.reconnectThrottlingRetries = cfg.getReconnectThrottlingRetries();
         this.addrs = Collections.unmodifiableList(addrs);
-        this.userAttrs = cfg.getUserAttributes();
+        this.userAttrs = userAttrs;
         this.asyncContinuationExecutor = cfg.getAsyncContinuationExecutor();
         this.heartbeatEnabled = cfg.isHeartbeatEnabled();
         this.heartbeatInterval = cfg.getHeartbeatInterval();
diff --git 
a/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannelImpl.java
 
b/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannelImpl.java
index b29bb69629f..95ef4ee4a65 100644
--- 
a/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannelImpl.java
+++ 
b/modules/thin-client/impl/src/main/java/org/apache/ignite/internal/client/thin/ReliableChannelImpl.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.client.thin;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
@@ -88,6 +89,9 @@ final class ReliableChannelImpl implements ReliableChannelEx {
     /** Client configuration. */
     private final ClientConfiguration clientCfg;
 
+    /** Effective user attributes. */
+    private final Map<String, String> effectiveUserAttrs;
+
     /** Logger. */
     private final IgniteLogger log;
 
@@ -141,10 +145,14 @@ final class ReliableChannelImpl implements 
ReliableChannelEx {
 
         partitionAwarenessEnabled = clientCfg.isPartitionAwarenessEnabled();
 
+        Map<String, String> cfgUserAttrs = clientCfg.getUserAttributes();
+
         String dcId = 
IgniteCommonsSystemProperties.getString(IgniteCommonsSystemProperties.IGNITE_DATA_CENTER_ID);
 
-        if (dcId == null && !F.isEmpty(clientCfg.getUserAttributes()))
-            dcId = 
clientCfg.getUserAttributes().get(IgniteCommonsSystemProperties.IGNITE_DATA_CENTER_ID);
+        if (dcId == null && !F.isEmpty(cfgUserAttrs))
+            dcId = 
cfgUserAttrs.get(IgniteCommonsSystemProperties.IGNITE_DATA_CENTER_ID);
+
+        effectiveUserAttrs = effectiveUserAttributes(cfgUserAttrs, dcId);
 
         affinityCtx = new ClientCacheAffinityContext(
             binary,
@@ -701,14 +709,14 @@ final class ReliableChannelImpl implements 
ReliableChannelEx {
 
                 if (hld != null) {
                     if (!hld.getAddresses().equals(addrs)) // Enrich holder 
addresses.
-                        hld.setConfiguration(new 
ClientChannelConfiguration(clientCfg, addrs));
+                        hld.setConfiguration(new 
ClientChannelConfiguration(clientCfg, addrs, effectiveUserAttrs));
 
                     break;
                 }
             }
 
             if (hld == null) { // If not found, create the new one.
-                hld = new ClientChannelHolder(new 
ClientChannelConfiguration(clientCfg, addrs));
+                hld = new ClientChannelHolder(new 
ClientChannelConfiguration(clientCfg, addrs, effectiveUserAttrs));
 
                 reinitHolders.add(hld);
 
@@ -749,6 +757,27 @@ final class ReliableChannelImpl implements 
ReliableChannelEx {
         finishChannelsReInit = System.currentTimeMillis();
     }
 
+    /**
+     * Adds the effective data center ID to user attributes.
+     *
+     * @param cfgUserAttrs Configured user attributes.
+     * @param dcId Effective data center ID.
+     * @return Effective user attributes.
+     */
+    private static Map<String, String> effectiveUserAttributes(
+        @Nullable Map<String, String> cfgUserAttrs,
+        @Nullable String dcId
+    ) {
+        if (dcId == null)
+            return cfgUserAttrs;
+
+        Map<String, String> attrs = cfgUserAttrs == null ? new HashMap<>() : 
new HashMap<>(cfgUserAttrs);
+
+        attrs.put(IgniteCommonsSystemProperties.IGNITE_DATA_CENTER_ID, dcId);
+
+        return Collections.unmodifiableMap(attrs);
+    }
+
     /**
      * Establishing connections to servers. If partition awareness feature is 
enabled connections are created
      * for every configured server. Otherwise only default channel is 
connected.

Reply via email to