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

alexpl 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 4633ca4f2cc IGNITE-17345 Thin client: Add affinity hits/misses metric 
- Fixes #10649.
4633ca4f2cc is described below

commit 4633ca4f2cc88949579ce2de213252fa0a0f8471
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Tue Apr 18 10:01:51 2023 +0300

    IGNITE-17345 Thin client: Add affinity hits/misses metric - Fixes #10649.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 docs/_docs/monitoring-metrics/new-metrics.adoc     |   4 +
 .../common/RunningQueryInfoCheckInitiatorTest.java |   2 +-
 .../jdbc/thin/JdbcThinWalModeChangeSelfTest.java   |   2 +-
 .../apache/ignite/internal/GridKernalContext.java  |   6 +-
 .../ignite/internal/GridKernalContextImpl.java     |   8 +-
 .../commandline/meta/tasks/MetadataRemoveTask.java |   2 +-
 .../wal/reader/StandaloneGridKernalContext.java    |   2 +-
 .../processors/odbc/ClientListenerMetrics.java     |  66 ++++++-
 .../processors/odbc/ClientListenerNioListener.java |  11 +-
 .../processors/odbc/ClientListenerProcessor.java   |  14 +-
 .../platform/client/ClientRequestHandler.java      |   2 +-
 .../client/cache/ClientCacheClearKeyRequest.java   |   4 +-
 .../cache/ClientCacheContainsKeyRequest.java       |   2 +-
 .../cache/ClientCacheGetAndPutIfAbsentRequest.java |   2 +-
 .../client/cache/ClientCacheGetAndPutRequest.java  |   2 +-
 .../cache/ClientCacheGetAndRemoveRequest.java      |   2 +-
 .../cache/ClientCacheGetAndReplaceRequest.java     |   2 +-
 .../client/cache/ClientCacheGetRequest.java        |   2 +-
 .../client/cache/ClientCacheIndexQueryRequest.java |   5 +-
 .../client/cache/ClientCacheKeyRequest.java        |  38 ++++
 .../client/cache/ClientCacheKeyValueRequest.java   |   2 +-
 .../client/cache/ClientCacheLocalPeekRequest.java  |   2 +-
 .../cache/ClientCachePutIfAbsentRequest.java       |   2 +-
 .../client/cache/ClientCachePutRequest.java        |   4 +-
 .../client/cache/ClientCacheQueryRequest.java      |  57 ++++++
 .../cache/ClientCacheRemoveIfEqualsRequest.java    |   2 +-
 .../client/cache/ClientCacheRemoveKeyRequest.java  |   2 +-
 .../cache/ClientCacheReplaceIfEqualsRequest.java   |   2 +-
 .../client/cache/ClientCacheReplaceRequest.java    |   2 +-
 .../client/cache/ClientCacheScanQueryRequest.java  |   5 +-
 .../cache/ClientCacheSqlFieldsQueryRequest.java    |   2 +-
 .../client/cache/ClientCacheSqlQueryRequest.java   |   2 +-
 .../platform/client/compute/ClientComputeTask.java |   2 +-
 .../ignite/internal/sql/SqlCommandProcessor.java   |   4 +-
 .../client/VisorClientConnectionDropTask.java      |   2 +-
 .../internal/client/thin/AffinityMetricsTest.java  | 213 +++++++++++++++++++++
 .../org/apache/ignite/client/ClientTestSuite.java  |   2 +
 37 files changed, 438 insertions(+), 47 deletions(-)

diff --git a/docs/_docs/monitoring-metrics/new-metrics.adoc 
b/docs/_docs/monitoring-metrics/new-metrics.adoc
index 42aedf50a65..7eae8cd24da 100644
--- a/docs/_docs/monitoring-metrics/new-metrics.adoc
+++ b/docs/_docs/monitoring-metrics/new-metrics.adoc
@@ -315,6 +315,10 @@ Register name: `client.connector`
 |SentBytesCount|   long|   Sent bytes count.
 |SslEnabled|   boolean|   Indicates whether SSL is enabled.
 |SslHandshakeDurationHistogram|   histogram|   Histogram of SSL handshake 
duration in milliseconds (metric is exported only if SSL is enabled).
+|AffinityKeyRequestsHits|   long|   The number of affinity-aware cache key 
requests that were sent to the primary node.
+|AffinityKeyRequestsMisses|   long|   The number of affinity-aware cache key 
requests that were sent not to the primary node.
+|AffinityQueryRequestsHits|   long|   The number of affinity-aware query 
requests that were sent to the primary node.
+|AffinityQueryRequestsMisses|   long|   The number of affinity-aware query 
requests that were sent not to the primary node.
 |===
 
 
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/common/RunningQueryInfoCheckInitiatorTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/common/RunningQueryInfoCheckInitiatorTest.java
index 38776d727c9..bc721296bd5 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/common/RunningQueryInfoCheckInitiatorTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/common/RunningQueryInfoCheckInitiatorTest.java
@@ -364,7 +364,7 @@ public class RunningQueryInfoCheckInitiatorTest extends 
JdbcThinAbstractSelfTest
 
     /** */
     private static int clientPort(IgniteEx ign) {
-        return ign.context().sqlListener().port();
+        return ign.context().clientListener().port();
     }
 
     /**
diff --git 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinWalModeChangeSelfTest.java
 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinWalModeChangeSelfTest.java
index c94ead9134a..718ead55026 100644
--- 
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinWalModeChangeSelfTest.java
+++ 
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinWalModeChangeSelfTest.java
@@ -135,7 +135,7 @@ public class JdbcThinWalModeChangeSelfTest extends 
WalModeChangeAbstractSelfTest
     private static Connection connect(Ignite node) throws Exception {
         IgniteKernal node0 = (IgniteKernal)node;
 
-        int port = node0.context().sqlListener().port();
+        int port = node0.context().clientListener().port();
 
         return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:" + 
port);
     }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java 
b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index 7bf057e5fb1..544b6b5d2eb 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -341,11 +341,11 @@ public interface GridKernalContext extends 
Iterable<GridComponent> {
     public GridQueryProcessor query();
 
     /**
-     * Gets SQL listener processor.
+     * Gets client listener processor.
      *
-     * @return SQL listener processor.
+     * @return Client listener processor.
      */
-    public ClientListenerProcessor sqlListener();
+    public ClientListenerProcessor clientListener();
 
     /**
      * @return Plugin processor.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index 8f3b685dc14..18e70f0326a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -194,7 +194,7 @@ public class GridKernalContextImpl implements 
GridKernalContext, Externalizable
 
     /** */
     @GridToStringInclude
-    private ClientListenerProcessor sqlListenerProc;
+    private ClientListenerProcessor clientListenerProc;
 
     /** */
     @GridToStringInclude
@@ -558,7 +558,7 @@ public class GridKernalContextImpl implements 
GridKernalContext, Externalizable
         else if (comp instanceof GridQueryProcessor)
             qryProc = (GridQueryProcessor)comp;
         else if (comp instanceof ClientListenerProcessor)
-            sqlListenerProc = (ClientListenerProcessor)comp;
+            clientListenerProc = (ClientListenerProcessor)comp;
         else if (comp instanceof DataStructuresProcessor)
             dataStructuresProc = (DataStructuresProcessor)comp;
         else if (comp instanceof ClusterProcessor)
@@ -853,8 +853,8 @@ public class GridKernalContextImpl implements 
GridKernalContext, Externalizable
     }
 
     /** {@inheritDoc} */
-    @Override public ClientListenerProcessor sqlListener() {
-        return sqlListenerProc;
+    @Override public ClientListenerProcessor clientListener() {
+        return clientListenerProc;
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/commandline/meta/tasks/MetadataRemoveTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/commandline/meta/tasks/MetadataRemoveTask.java
index 653f9bd35bd..6b6a585272d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/commandline/meta/tasks/MetadataRemoveTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/commandline/meta/tasks/MetadataRemoveTask.java
@@ -155,7 +155,7 @@ public class MetadataRemoveTask extends 
VisorMultiNodeTask<MetadataTypeArgs, Met
 
         /** {@inheritDoc} */
         @Override public void run() throws IgniteException {
-            ignite.context().sqlListener().closeAllSessions();
+            ignite.context().clientListener().closeAllSessions();
         }
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
index 890c1198c38..8c1f52a4c15 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneGridKernalContext.java
@@ -457,7 +457,7 @@ public class StandaloneGridKernalContext implements 
GridKernalContext {
     }
 
     /** {@inheritDoc} */
-    @Override public ClientListenerProcessor sqlListener() {
+    @Override public ClientListenerProcessor clientListener() {
         return null;
     }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerMetrics.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerMetrics.java
index d9c614cff58..0e6f19b5343 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerMetrics.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerMetrics.java
@@ -16,12 +16,12 @@
  */
 package org.apache.ignite.internal.processors.odbc;
 
-import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.metric.MetricRegistry;
+import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric;
 import org.apache.ignite.internal.processors.metric.impl.IntMetricImpl;
+import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
 import org.apache.ignite.internal.processors.metric.impl.MetricUtils;
 
-import static 
org.apache.ignite.internal.processors.metric.GridMetricManager.CLIENT_CONNECTOR_METRICS;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.CLI_TYPES;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.JDBC_CLIENT;
 import static 
org.apache.ignite.internal.processors.odbc.ClientListenerNioListener.ODBC_CLIENT;
@@ -43,6 +43,18 @@ public class ClientListenerMetrics {
     /** Number of successfully established sessions. */
     public static final String METRIC_ACEPTED = "AcceptedSessions";
 
+    /** */
+    public static final String AFF_KEY_HITS = "AffinityKeyRequestsHits";
+
+    /** */
+    public static final String AFF_KEY_MISSES = "AffinityKeyRequestsMisses";
+
+    /** */
+    public static final String AFF_QRY_HITS = "AffinityQueryRequestsHits";
+
+    /** */
+    public static final String AFF_QRY_MISSES = "AffinityQueryRequestsMisses";
+
     /** Rejected by timeout. */
     private final IntMetricImpl rejectedTimeout;
 
@@ -55,12 +67,22 @@ public class ClientListenerMetrics {
     /** Connections accepted. */
     private final IntMetricImpl[] accepted;
 
+    /** */
+    private final LongAdderMetric affKeyHits;
+
+    /** */
+    private final LongAdderMetric affKeyMisses;
+
+    /** */
+    private final AtomicLongMetric affQryHits;
+
+    /** */
+    private final AtomicLongMetric affQryMisses;
+
     /**
-     * @param ctx Kernal context.
+     * @param mreg Metrics registry.
      */
-    public ClientListenerMetrics(GridKernalContext ctx) {
-        MetricRegistry mreg = ctx.metric().registry(CLIENT_CONNECTOR_METRICS);
-
+    public ClientListenerMetrics(MetricRegistry mreg) {
         rejectedTimeout = mreg.intMetric(METRIC_REJECTED_TIMEOUT,
                 "TCP sessions count that were rejected due to handshake 
timeout.");
 
@@ -71,6 +93,18 @@ public class ClientListenerMetrics {
 
         accepted = new IntMetricImpl[CLI_TYPES.length];
 
+        affKeyHits = mreg.longAdderMetric(AFF_KEY_HITS,
+            "The number of affinity-aware cache key requests that were sent to 
the primary node");
+
+        affKeyMisses = mreg.longAdderMetric(AFF_KEY_MISSES,
+            "The number of affinity-aware cache key requests that were sent 
not to the primary node");
+
+        affQryHits = mreg.longMetric(AFF_QRY_HITS,
+            "The number of affinity-aware query requests that were sent to the 
primary node");
+
+        affQryMisses = mreg.longMetric(AFF_QRY_MISSES,
+            "The number of affinity-aware query requests that were sent not to 
the primary node");
+
         for (byte clientType : CLI_TYPES) {
             String clientLabel = clientTypeLabel(clientType);
 
@@ -112,6 +146,26 @@ public class ClientListenerMetrics {
         accepted[clientType].increment();
     }
 
+    /** */
+    public void onAffinityKeyHit() {
+        affKeyHits.increment();
+    }
+
+    /** */
+    public void onAffinityKeyMiss() {
+        affKeyMisses.increment();
+    }
+
+    /** */
+    public void onAffinityQryHit() {
+        affQryHits.increment();
+    }
+
+    /** */
+    public void onAffinityQryMiss() {
+        affQryMisses.increment();
+    }
+
     /**
      * Get label for a client.
      * @param clientType Client type.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
index 7ed6296dd07..eaaca392339 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
@@ -101,9 +101,14 @@ public class ClientListenerNioListener extends 
GridNioServerListenerAdapter<Clie
      * @param ctx Context.
      * @param busyLock Shutdown busy lock.
      * @param cliConnCfg Client connector configuration.
+     * @param metrics Client listener metrics.
      */
-    public ClientListenerNioListener(GridKernalContext ctx, GridSpinBusyLock 
busyLock,
-        ClientConnectorConfiguration cliConnCfg) {
+    public ClientListenerNioListener(
+        GridKernalContext ctx,
+        GridSpinBusyLock busyLock,
+        ClientConnectorConfiguration cliConnCfg,
+        ClientListenerMetrics metrics
+    ) {
         assert cliConnCfg != null;
 
         this.ctx = ctx;
@@ -116,7 +121,7 @@ public class ClientListenerNioListener extends 
GridNioServerListenerAdapter<Clie
         thinCfg = cliConnCfg.getThinClientConfiguration() == null ? new 
ThinClientConfiguration()
             : new 
ThinClientConfiguration(cliConnCfg.getThinClientConfiguration());
 
-        metrics = new ClientListenerMetrics(ctx);
+        this.metrics = metrics;
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
index 0af5da807f3..5ddcccfd04b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
@@ -96,6 +96,9 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
     /** TCP Server. */
     private GridNioServer<ClientMessage> srv;
 
+    /** Metrics. */
+    private ClientListenerMetrics metrics;
+
     /** Executor service. */
     private ExecutorService execSvc;
 
@@ -151,12 +154,14 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
 
                 MetricRegistry mreg = 
ctx.metric().registry(CLIENT_CONNECTOR_METRICS);
 
+                metrics = new ClientListenerMetrics(mreg);
+
                 for (int port = cliConnCfg.getPort(); port <= portTo && port 
<= 65535; port++) {
                     try {
                         srv = GridNioServer.<ClientMessage>builder()
                             .address(hostAddr)
                             .port(port)
-                            .listener(new ClientListenerNioListener(ctx, 
busyLock, cliConnCfg))
+                            .listener(new ClientListenerNioListener(ctx, 
busyLock, cliConnCfg, metrics))
                             .logger(log)
                             .selectorCount(selectorCnt)
                             .igniteInstanceName(ctx.igniteInstanceName())
@@ -466,6 +471,13 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
         return srv.port();
     }
 
+    /**
+     * @return Client listener metrics.
+     */
+    public ClientListenerMetrics metrics() {
+        return metrics;
+    }
+
     /**
      * Prepare connector configuration.
      *
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
index 076bbaab59c..ffbe7174795 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientRequestHandler.java
@@ -125,7 +125,7 @@ public class ClientRequestHandler implements 
ClientListenerRequestHandler {
             msg = sqlState + ": " + msg;
         }
 
-        if 
(ctx.kernalContext().sqlListener().sendServerExceptionStackTraceToClient())
+        if 
(ctx.kernalContext().clientListener().sendServerExceptionStackTraceToClient())
             msg = msg + U.nl() + X.getFullStackTrace(e);
 
         return new ClientResponse(req.requestId(), status, msg);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheClearKeyRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheClearKeyRequest.java
index 6bcbbe89b26..d0aa19e778b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheClearKeyRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheClearKeyRequest.java
@@ -36,9 +36,9 @@ public class ClientCacheClearKeyRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         cache(ctx).clear(key());
 
-        return super.process(ctx);
+        return new ClientResponse(requestId());
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheContainsKeyRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheContainsKeyRequest.java
index 8470828e424..6cea754199e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheContainsKeyRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheContainsKeyRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheContainsKeyRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean val = cache(ctx).containsKey(key());
 
         return new ClientBooleanResponse(requestId(), val);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutIfAbsentRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutIfAbsentRequest.java
index 836021313c5..7562808a02d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutIfAbsentRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutIfAbsentRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheGetAndPutIfAbsentRequest extends 
ClientCacheKeyValueRequ
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object res = cache(ctx).getAndPutIfAbsent(key(), val());
 
         return new ClientObjectResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutRequest.java
index 7a540e8473a..15794c2d389 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndPutRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheGetAndPutRequest extends 
ClientCacheKeyValueRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object res = cache(ctx).getAndPut(key(), val());
 
         return new ClientObjectResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndRemoveRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndRemoveRequest.java
index e4fd735b186..ebbe1a854b8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndRemoveRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndRemoveRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheGetAndRemoveRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object val = cache(ctx).getAndRemove(key());
 
         return new ClientObjectResponse(requestId(), val);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndReplaceRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndReplaceRequest.java
index dba8639e4c0..d3af07d19ad 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndReplaceRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetAndReplaceRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheGetAndReplaceRequest extends 
ClientCacheKeyValueRequest
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object res = cache(ctx).getAndReplace(key(), val());
 
         return new ClientObjectResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetRequest.java
index 41558c2863d..6fc525613cf 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheGetRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object val = cache(ctx).get(key());
 
         return new ClientObjectResponse(requestId(), val);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
index 69fc5973074..51d72478fbf 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
@@ -38,7 +38,7 @@ import static 
org.apache.ignite.internal.binary.GridBinaryMarshaller.ARR_LIST;
  * IndexQuery request.
  */
 @SuppressWarnings({"rawtypes", "unchecked"})
-public class ClientCacheIndexQueryRequest extends ClientCacheRequest {
+public class ClientCacheIndexQueryRequest extends ClientCacheQueryRequest {
     /** IndexQuery. */
     private final IndexQuery qry;
 
@@ -144,6 +144,9 @@ public class ClientCacheIndexQueryRequest extends 
ClientCacheRequest {
     @Override public ClientResponse process(ClientConnectionContext ctx) {
         IgniteCache cache = !isKeepBinary() ? rawCache(ctx) : cache(ctx);
 
+        if (qry.getPartition() != null)
+            updateAffinityMetrics(ctx, qry.getPartition());
+
         ctx.incrementCursors();
 
         try {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyRequest.java
index f6517393cbd..56013524b58 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyRequest.java
@@ -17,8 +17,15 @@
 
 package org.apache.ignite.internal.processors.platform.client.cache;
 
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
 import 
org.apache.ignite.internal.processors.platform.client.tx.ClientTxAwareRequest;
+import org.apache.ignite.internal.util.typedef.F;
 
 /**
  * Cache request involving key.
@@ -38,6 +45,37 @@ public abstract class ClientCacheKeyRequest extends 
ClientCacheDataRequest imple
         key = reader.readObjectDetached();
     }
 
+    /** {@inheritDoc} */
+    @Override public final ClientResponse process(ClientConnectionContext ctx) 
{
+        if (!isTransactional()) {
+            // Calculate affinity metrics.
+            DynamicCacheDescriptor desc = cacheDescriptor(ctx);
+            CacheConfiguration<?, ?> cfg = desc.cacheConfiguration();
+
+            if (cfg.getCacheMode() == CacheMode.PARTITIONED && 
cfg.isStatisticsEnabled()) {
+                String cacheName = desc.cacheName();
+
+                try {
+                    GridKernalContext kctx = ctx.kernalContext();
+
+                    if 
(F.first(kctx.affinity().mapKeyToPrimaryAndBackups(cacheName, key, 
null)).isLocal())
+                        kctx.clientListener().metrics().onAffinityKeyHit();
+                    else
+                        kctx.clientListener().metrics().onAffinityKeyMiss();
+                }
+                catch (Exception ignored) {
+                    // No-op.
+                }
+            }
+        }
+
+        // Process request in overriden method.
+        return process0(ctx);
+    }
+
+    /** */
+    protected abstract ClientResponse process0(ClientConnectionContext ctx);
+
     /**
      * Gets the key.
      *
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyValueRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyValueRequest.java
index 03b85d6e87f..060d3d891f7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyValueRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheKeyValueRequest.java
@@ -22,7 +22,7 @@ import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 /**
  * Cache request involving key and value.
  */
-public class ClientCacheKeyValueRequest extends ClientCacheKeyRequest {
+public abstract class ClientCacheKeyValueRequest extends ClientCacheKeyRequest 
{
     /** Value. */
     private final Object val;
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheLocalPeekRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheLocalPeekRequest.java
index 2002664d007..40e01085710 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheLocalPeekRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheLocalPeekRequest.java
@@ -39,7 +39,7 @@ public class ClientCacheLocalPeekRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         Object val = cache(ctx).localPeek(key(), CachePeekMode.ALL);
 
         return new ClientObjectResponse(requestId(), val);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutIfAbsentRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutIfAbsentRequest.java
index 4dd2cde58ce..b0bd0e6317f 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutIfAbsentRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutIfAbsentRequest.java
@@ -37,7 +37,7 @@ public class ClientCachePutIfAbsentRequest extends 
ClientCacheKeyValueRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean res = cache(ctx).putIfAbsent(key(), val());
 
         return new ClientBooleanResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutRequest.java
index 2c396b7ede8..bc249fc07f3 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCachePutRequest.java
@@ -36,10 +36,10 @@ public class ClientCachePutRequest extends 
ClientCacheKeyValueRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         cache(ctx).put(key(), val());
 
-        return super.process(ctx);
+        return new ClientResponse(requestId());
     }
 }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryRequest.java
new file mode 100644
index 00000000000..ff2337cec43
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryRequest.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.processors.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import 
org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+
+/**
+ * Abstract query request.
+ */
+public abstract class ClientCacheQueryRequest extends ClientCacheDataRequest {
+    /** */
+    ClientCacheQueryRequest(BinaryRawReader reader) {
+        super(reader);
+    }
+
+    /** */
+    protected void updateAffinityMetrics(ClientConnectionContext ctx, int 
part) {
+        DynamicCacheDescriptor desc = cacheDescriptor(ctx);
+        CacheConfiguration<?, ?> cfg = desc.cacheConfiguration();
+
+        if (cfg.getCacheMode() == CacheMode.PARTITIONED && 
cfg.isStatisticsEnabled()) {
+            String cacheName = desc.cacheName();
+
+            try {
+                GridKernalContext kctx = ctx.kernalContext();
+
+                if (kctx.affinity().mapPartitionToNode(cacheName, part, 
null).isLocal())
+                    kctx.clientListener().metrics().onAffinityQryHit();
+                else
+                    kctx.clientListener().metrics().onAffinityQryMiss();
+            }
+            catch (Exception ignored) {
+                // No-op.
+            }
+        }
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveIfEqualsRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveIfEqualsRequest.java
index b86f2f8895d..14948f0e591 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveIfEqualsRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveIfEqualsRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheRemoveIfEqualsRequest extends 
ClientCacheKeyValueRequest
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean res = cache(ctx).remove(key(), val());
 
         return new ClientBooleanResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveKeyRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveKeyRequest.java
index a68c32730f4..f1c50451188 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveKeyRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRemoveKeyRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheRemoveKeyRequest extends 
ClientCacheKeyRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean val = cache(ctx).remove(key());
 
         return new ClientBooleanResponse(requestId(), val);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceIfEqualsRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceIfEqualsRequest.java
index 8645fbb8173..83d40b66e57 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceIfEqualsRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceIfEqualsRequest.java
@@ -42,7 +42,7 @@ public class ClientCacheReplaceIfEqualsRequest extends 
ClientCacheKeyValueReques
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean res = cache(ctx).replace(key(), val(), newVal);
 
         return new ClientBooleanResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceRequest.java
index bd7a642bb39..cbfa0fcc219 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheReplaceRequest.java
@@ -37,7 +37,7 @@ public class ClientCacheReplaceRequest extends 
ClientCacheKeyValueRequest {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
+    @Override public ClientResponse process0(ClientConnectionContext ctx) {
         boolean res = cache(ctx).replace(key(), val());
 
         return new ClientBooleanResponse(requestId(), res);
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
index 1bdc4f14b49..9321db3c3ad 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
@@ -36,7 +36,7 @@ import org.apache.ignite.lang.IgniteBiPredicate;
  * Scan query request.
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
-public class ClientCacheScanQueryRequest extends ClientCacheDataRequest 
implements ClientTxAwareRequest {
+public class ClientCacheScanQueryRequest extends ClientCacheQueryRequest 
implements ClientTxAwareRequest {
     /** Local flag. */
     private final boolean loc;
 
@@ -82,6 +82,9 @@ public class ClientCacheScanQueryRequest extends 
ClientCacheDataRequest implemen
             .setPartition(part)
             .setFilter(createFilter(ctx.kernalContext(), filterObj, 
filterPlatform));
 
+        if (part != null)
+            updateAffinityMetrics(ctx, part);
+
         ctx.incrementCursors();
 
         try {
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
index 43a6b460989..a1e5376d82e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
@@ -41,7 +41,7 @@ import org.apache.ignite.plugin.security.SecurityException;
  * Sql query request.
  */
 @SuppressWarnings("unchecked")
-public class ClientCacheSqlFieldsQueryRequest extends ClientCacheDataRequest 
implements ClientTxAwareRequest {
+public class ClientCacheSqlFieldsQueryRequest extends ClientCacheQueryRequest 
implements ClientTxAwareRequest {
     /** Query. */
     private final SqlFieldsQuery qry;
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
index 29b0de8d1e1..00c75c217d8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
@@ -31,7 +31,7 @@ import 
org.apache.ignite.internal.processors.platform.client.tx.ClientTxAwareReq
  * Sql query request.
  */
 @SuppressWarnings("unchecked")
-public class ClientCacheSqlQueryRequest extends ClientCacheDataRequest 
implements ClientTxAwareRequest {
+public class ClientCacheSqlQueryRequest extends ClientCacheQueryRequest 
implements ClientTxAwareRequest {
     /** Query. */
     private final SqlQuery qry;
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/compute/ClientComputeTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/compute/ClientComputeTask.java
index ed84382ec7c..f1525fa3f4a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/compute/ClientComputeTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/compute/ClientComputeTask.java
@@ -128,7 +128,7 @@ class ClientComputeTask implements ClientCloseableResource {
                 ClientNotification notification;
 
                 if (f.error() != null) {
-                    String msg = 
ctx.kernalContext().sqlListener().sendServerExceptionStackTraceToClient()
+                    String msg = 
ctx.kernalContext().clientListener().sendServerExceptionStackTraceToClient()
                             ? f.error().getMessage() + U.nl() + 
X.getFullStackTrace(f.error())
                             : f.error().getMessage();
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlCommandProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlCommandProcessor.java
index 3a1ff15b40a..698d2a62613 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlCommandProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlCommandProcessor.java
@@ -189,9 +189,9 @@ public class SqlCommandProcessor {
      */
     private void processKillClientCommand(SqlKillClientCommand cmd) {
         if (cmd.connectionId() == null)
-            ctx.sqlListener().mxBean().dropAllConnections();
+            ctx.clientListener().mxBean().dropAllConnections();
         else
-            ctx.sqlListener().mxBean().dropConnection(cmd.connectionId());
+            ctx.clientListener().mxBean().dropConnection(cmd.connectionId());
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/visor/client/VisorClientConnectionDropTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/visor/client/VisorClientConnectionDropTask.java
index b5a0d949e4e..123325d7637 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/visor/client/VisorClientConnectionDropTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/visor/client/VisorClientConnectionDropTask.java
@@ -77,7 +77,7 @@ public class VisorClientConnectionDropTask extends 
VisorMultiNodeTask<Long, Void
 
         /** {@inheritDoc} */
         @Override protected Boolean run(@Nullable Long arg) throws 
IgniteException {
-            ClientProcessorMXBean bean = 
ignite.context().sqlListener().mxBean();
+            ClientProcessorMXBean bean = 
ignite.context().clientListener().mxBean();
 
             if (arg != null)
                 return bean.dropConnection(arg);
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/AffinityMetricsTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/AffinityMetricsTest.java
new file mode 100644
index 00000000000..5877a211075
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/AffinityMetricsTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.client.thin;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.client.ClientCache;
+import org.apache.ignite.client.ClientTransaction;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.metric.MetricRegistry;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.spi.metric.LongMetric;
+import org.junit.Test;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static 
org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.AFF_KEY_HITS;
+import static 
org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.AFF_KEY_MISSES;
+import static 
org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.AFF_QRY_HITS;
+import static 
org.apache.ignite.internal.processors.odbc.ClientListenerMetrics.AFF_QRY_MISSES;
+
+/**
+ * Test thin client affinity hits/misses metrics.
+ */
+public class AffinityMetricsTest extends 
ThinClientAbstractPartitionAwarenessTest {
+    /** Grids count. */
+    private static final int GRIDS_CNT = 3;
+
+    /** */
+    private static final String PART_CACHE = "partCache";
+
+    /** */
+    private static final String REPL_CACHE = "replCache";
+
+    /** */
+    private static final String[] ALL_AFF_METRICS =
+        new String[] {AFF_KEY_HITS, AFF_KEY_MISSES, AFF_QRY_HITS, 
AFF_QRY_MISSES};
+
+    /** */
+    private final Map<String, Long> lastMetricValues = new HashMap<>();
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(GRIDS_CNT);
+
+        awaitPartitionMapExchange();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        initClient(getClientConfiguration(0, 
1).setClusterDiscoveryEnabled(false), 0, 1);
+
+        super.beforeTest();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        return 
super.getConfiguration(igniteInstanceName).setCacheConfiguration(
+            new 
CacheConfiguration<>(PART_CACHE).setCacheMode(PARTITIONED).setAtomicityMode(TRANSACTIONAL)
+                .setStatisticsEnabled(true),
+            new 
CacheConfiguration<>(REPL_CACHE).setCacheMode(REPLICATED).setAtomicityMode(TRANSACTIONAL)
+                .setStatisticsEnabled(true)
+        );
+    }
+
+    /** */
+    @Test
+    public void testCacheKeyAffinityMetricsPartitioned() {
+        resetMetricValues();
+
+        Integer affKey0 = primaryKey(ignite(0).cache(PART_CACHE));
+        Integer affKey1 = primaryKey(ignite(1).cache(PART_CACHE));
+        Integer affKey2 = primaryKey(ignite(2).cache(PART_CACHE));
+        ClientCache<Integer, Integer> cache = client.cache(PART_CACHE);
+
+        cache.put(affKey0, affKey0);
+
+        assertEquals(1, calcMetricIncrement(ignite(0), AFF_KEY_HITS));
+
+        cache.put(affKey1, affKey1);
+
+        assertEquals(1, calcMetricIncrement(ignite(1), AFF_KEY_HITS));
+
+        cache.put(affKey2, affKey2);
+
+        assertEquals(1, calcMetricIncrement(ignite(0), AFF_KEY_MISSES) +
+            calcMetricIncrement(ignite(1), AFF_KEY_MISSES));
+    }
+
+    /** */
+    @Test
+    public void testCacheKeyAffinityMetricsReplicated() {
+        resetMetricValues();
+
+        ClientCache<Integer, Integer> cache = client.cache(REPL_CACHE);
+
+        for (int i = 0; i < 100; i++)
+            cache.put(i, i);
+
+        for (Ignite ignite : G.allGrids()) {
+            for (String metricName : ALL_AFF_METRICS)
+                assertEquals(0, calcMetricIncrement(ignite, metricName));
+        }
+    }
+
+    /** */
+    @Test
+    public void testCacheKeyAffinityMetricsTx() {
+        resetMetricValues();
+
+        for (int i = 0; i < 100; i++) {
+            try (ClientTransaction tx = client.transactions().txStart()) {
+                client.cache(PART_CACHE).put(i, i);
+                tx.commit();
+            }
+        }
+
+        for (Ignite ignite : G.allGrids()) {
+            for (String metricName : ALL_AFF_METRICS)
+                assertEquals(0, calcMetricIncrement(ignite, metricName));
+        }
+    }
+
+    /** */
+    @Test
+    public void testQueryAffinityMetricsPartitioned() {
+        resetMetricValues();
+
+        Integer affKey0 = primaryKey(ignite(0).cache(PART_CACHE));
+        Integer affKey1 = primaryKey(ignite(1).cache(PART_CACHE));
+        Integer affKey2 = primaryKey(ignite(2).cache(PART_CACHE));
+
+        Affinity<Integer> aff = affinity(ignite(0).cache(PART_CACHE));
+        int part0 = aff.partition(affKey0);
+        int part1 = aff.partition(affKey1);
+        int part2 = aff.partition(affKey2);
+
+        ClientCache<Integer, Integer> cache = client.cache(PART_CACHE);
+
+        cache.query(new ScanQuery<>().setPartition(part0)).getAll();
+
+        assertEquals(1, calcMetricIncrement(ignite(0), AFF_QRY_HITS));
+
+        cache.query(new ScanQuery<>().setPartition(part1)).getAll();
+
+        assertEquals(1, calcMetricIncrement(ignite(1), AFF_QRY_HITS));
+
+        cache.query(new ScanQuery<>().setPartition(part2)).getAll();
+
+        assertEquals(1, calcMetricIncrement(ignite(0), AFF_QRY_MISSES) +
+            calcMetricIncrement(ignite(1), AFF_QRY_MISSES));
+    }
+
+    /** */
+    @Test
+    public void testQueryAffinityMetricsReplicated() {
+        resetMetricValues();
+
+        ClientCache<Integer, Integer> cache = client.cache(REPL_CACHE);
+
+        for (int i = 0; i < 10; i++)
+            cache.query(new ScanQuery<>().setPartition(i)).getAll();
+
+        for (Ignite ignite : G.allGrids()) {
+            for (String metricName : ALL_AFF_METRICS)
+                assertEquals(0, calcMetricIncrement(ignite, metricName));
+        }
+    }
+
+    /** */
+    private void resetMetricValues() {
+        lastMetricValues.clear();
+
+        for (Ignite ignite : G.allGrids()) {
+            for (String metricName : ALL_AFF_METRICS)
+                calcMetricIncrement(ignite, metricName);
+        }
+    }
+
+    /** */
+    private long calcMetricIncrement(Ignite ignite, String metricName) {
+        MetricRegistry mreg = 
((IgniteEx)ignite).context().metric().registry(GridMetricManager.CLIENT_CONNECTOR_METRICS);
+        LongMetric metric = mreg.findMetric(metricName);
+        long newVal = metric.value();
+        Long oldVal = lastMetricValues.put(ignite.name() + '.' + metricName, 
newVal);
+
+        return newVal - (oldVal == null ? 0 : oldVal);
+    }
+}
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java 
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
index cbb128e44a7..04d9e2b76d1 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/client/ClientTestSuite.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.client;
 
+import org.apache.ignite.internal.client.thin.AffinityMetricsTest;
 import org.apache.ignite.internal.client.thin.AtomicLongTest;
 import org.apache.ignite.internal.client.thin.CacheAsyncTest;
 import org.apache.ignite.internal.client.thin.CacheEntryListenersTest;
@@ -86,6 +87,7 @@ import org.junit.runners.Suite;
     IgniteClientRequestEventListenerTest.class,
     ThinClientEnpointsDiscoveryTest.class,
     InactiveClusterCacheRequestTest.class,
+    AffinityMetricsTest.class,
 })
 public class ClientTestSuite {
     // No-op.

Reply via email to