You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2018/04/18 14:16:28 UTC

ignite git commit: IGNITE-6681 .NET: QueryMetrics

Repository: ignite
Updated Branches:
  refs/heads/master 9d184c9c0 -> ea8bfac60


IGNITE-6681 .NET: QueryMetrics

This closes #3839


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ea8bfac6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ea8bfac6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ea8bfac6

Branch: refs/heads/master
Commit: ea8bfac60c0e6f4e4b456f7ea9b3ab5af97a3c7e
Parents: 9d184c9
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Apr 18 17:16:17 2018 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Apr 18 17:16:17 2018 +0300

----------------------------------------------------------------------
 .../platform/cache/PlatformCache.java           |  37 ++++
 .../ExpiryCacheHolderTest.cs                    |  10 +
 .../Apache.Ignite.Core.Tests.csproj             |   1 +
 .../ApiParity/CacheParityTest.cs                |   2 -
 .../Cache/CacheQueryMetricsTest.cs              | 190 +++++++++++++++++++
 .../Cache/CacheTestAsyncWrapper.cs              |  10 +
 .../Apache.Ignite.Core.csproj                   |   2 +
 .../dotnet/Apache.Ignite.Core/Cache/ICache.cs   |  11 ++
 .../Apache.Ignite.Core/Cache/IQueryMetrics.cs   |  65 +++++++
 .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs  |  17 ++
 .../Apache.Ignite.Core/Impl/Cache/CacheOp.cs    |   4 +-
 .../Impl/Cache/QueryMetricsImpl.cs              |  71 +++++++
 12 files changed, 417 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
index 19dac83..c78f2d6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
@@ -39,6 +39,7 @@ import org.apache.ignite.cache.CacheMetrics;
 import org.apache.ignite.cache.CachePartialUpdateException;
 import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.cache.query.Query;
+import org.apache.ignite.cache.query.QueryMetrics;
 import org.apache.ignite.cache.query.ScanQuery;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.cache.query.SqlQuery;
@@ -326,6 +327,12 @@ public class PlatformCache extends PlatformAbstractTarget {
     /** */
     public static final int OP_GET_LOST_PARTITIONS = 84;
 
+    /** */
+    public static final int OP_QUERY_METRICS = 85;
+
+    /** */
+    public static final int OP_RESET_QUERY_METRICS = 86;
+
     /** Underlying JCache in binary mode. */
     private final IgniteCacheProxy cache;
 
@@ -988,6 +995,14 @@ public class PlatformCache extends PlatformAbstractTarget {
 
                 break;
 
+            case OP_QUERY_METRICS: {
+                QueryMetrics metrics = cache.queryMetrics();
+
+                writeQueryMetrics(writer, metrics);
+
+                break;
+            }
+
             default:
                 super.processOutStream(type, writer);
         }
@@ -1094,6 +1109,11 @@ public class PlatformCache extends PlatformAbstractTarget {
                 cache.removeAll();
 
                 return TRUE;
+
+            case OP_RESET_QUERY_METRICS:
+                cache.resetQueryMetrics();
+
+                return TRUE;
         }
         return super.processInLongOutLong(type, val);
     }
@@ -1486,6 +1506,23 @@ public class PlatformCache extends PlatformAbstractTarget {
     }
 
     /**
+     * Writes query metrics.
+     *
+     * @param writer Writer.
+     * @param metrics Metrics.
+     */
+    public static void writeQueryMetrics(BinaryRawWriter writer, QueryMetrics metrics) {
+        assert writer != null;
+        assert metrics != null;
+
+        writer.writeLong(metrics.minimumTime());
+        writer.writeLong(metrics.maximumTime());
+        writer.writeDouble(metrics.averageTime());
+        writer.writeInt(metrics.executions());
+        writer.writeInt(metrics.fails());
+    }
+
+    /**
      * Writes error with EntryProcessorException cause.
      */
     private static class GetAllWriter implements PlatformFutureUtils.Writer {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
index 93e3a53..34d4b4d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet.Tests/ExpiryCacheHolderTest.cs
@@ -513,6 +513,16 @@ namespace Apache.Ignite.AspNet.Tests
             {
                 throw new NotImplementedException();
             }
+
+            public IQueryMetrics GetQueryMetrics()
+            {
+                throw new NotImplementedException();
+            }
+
+            public void ResetQueryMetrics()
+            {
+                throw new NotImplementedException();
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 8cd64cc..a04509a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -106,6 +106,7 @@
     <Compile Include="Binary\Serializable\GenericCollectionsTest.cs" />
     <Compile Include="Cache\Affinity\AffinityAttributeTest.cs" />
     <Compile Include="Cache\CacheCreateTest.cs" />
+    <Compile Include="Cache\CacheQueryMetricsTest.cs" />
     <Compile Include="Cache\DataRegionMetricsTest.cs" />
     <Compile Include="Cache\DataStorageMetricsTest.cs" />
     <Compile Include="Cache\PersistenceTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
index 68b822c..6471ec5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
@@ -51,8 +51,6 @@ namespace Apache.Ignite.Core.Tests.ApiParity
         /** Members that are missing on .NET side and should be added in future. */
         private static readonly string[] MissingMembers =
         {
-            "queryMetrics",  // IGNITE-6681
-            "resetQueryMetrics",  // IGNITE-6681
             "queryDetailMetrics",  // IGNITE-6680
             "resetQueryDetailMetrics",  // IGNITE-6680
             "sizeLong",  // 	IGNITE-6563

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheQueryMetricsTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheQueryMetricsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheQueryMetricsTest.cs
new file mode 100644
index 0000000..5b85328
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheQueryMetricsTest.cs
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Local
+namespace Apache.Ignite.Core.Tests.Cache
+{
+    extern alias ExamplesDll;
+    using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Cache.Query;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Linq;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests query metrics propagation.
+    /// </summary>
+    public class CacheQueryMetricsTest
+    {
+        /// <summary>
+        /// Fixture set up.
+        /// </summary>
+        [TestFixtureSetUp]
+        public void FixtureSetUp()
+        {
+            Ignition.Start(TestUtils.GetTestConfiguration());
+        }
+
+        /// <summary>
+        /// Fixture tear down.
+        /// </summary>
+        [TestFixtureTearDown]
+        public void FixtureTearDown()
+        {
+            Ignition.StopAll(true);
+        }
+
+        /// <summary>
+        /// Tests query metrics.
+        /// </summary>
+        [Test]
+        public void TestQueryMetrics()
+        {
+            var cache = GetCache();
+
+            cache.ResetQueryMetrics();
+
+            ExecuteTwoQueries(cache);
+
+            CheckMetrics(cache.GetQueryMetrics());
+        }
+
+        /// <summary>
+        /// Tests failed queries count.
+        /// </summary>
+        [Test]
+        public void TestQueryFails()
+        {
+            var cache = GetCache();
+
+            Assert.Throws<IgniteException>(() => cache.Query(new SqlFieldsQuery("select * from NOT_A_TABLE")));
+
+            Assert.AreEqual(1, cache.GetQueryMetrics().Fails, "Check Fails count.");
+        }
+
+        /// <summary>
+        /// Tests query metrics reset.
+        /// </summary>
+        [Test]
+        public void TestQueryMetricsReset()
+        {
+            var cache = GetCache();
+
+            ExecuteTwoQueries(cache);
+
+            cache.ResetQueryMetrics();
+
+            IQueryMetrics metrics = cache.GetQueryMetrics();
+
+            Assert.AreEqual(0, metrics.Executions, "Check Executions count.");
+            Assert.AreEqual(0, metrics.Fails, "Check Fails count.");
+            Assert.AreEqual(0, metrics.MinimumTime, "Check MinimumTime.");
+            Assert.AreEqual(0, metrics.MaximumTime, "Check MaximumTime.");
+            Assert.AreEqual(0, metrics.AverageTime, 0.1, "Check AverageTime.");
+
+            ExecuteTwoQueries(cache);
+
+            CheckMetrics(cache.GetQueryMetrics());
+        }
+
+        /// <summary>
+        /// Get Cache instance.
+        /// </summary>
+        /// <returns>Cache instance.</returns>
+        private ICache<int, Person> GetCache()
+        {
+            var ignite = Ignition.GetIgnite();
+
+            var cache = ignite.GetOrCreateCache<int, Person>(GetCacheConfiguration());
+
+            if (cache.GetSize() == 0)
+            {
+                Person person = new Person()
+                {
+                    Name = "Adam",
+                    Age = 35000
+                };
+
+                cache.Put(1, person);
+            }
+
+            return cache;
+        }
+
+        /// <summary>
+        /// Check cache configuration.
+        /// </summary>
+        /// <returns>Cache configuration.</returns>
+        private CacheConfiguration GetCacheConfiguration()
+        {
+            return new CacheConfiguration("cacheName")
+            {
+                EnableStatistics = true,
+
+                QueryEntities = new List<QueryEntity>()
+                {
+                    new QueryEntity(typeof(int), typeof(Person))
+                }
+            };
+        }
+
+        /// <summary>
+        /// Person.
+        /// </summary>
+        private class Person
+        {
+            [QuerySqlField]
+            public string Name { get; set; }
+
+            [QuerySqlField]
+            public int Age { get; set; }
+        }
+
+        /// <summary>
+        /// Execute two queries.
+        /// </summary>
+        /// <param name="cache">Cache instance.</param>
+        [SuppressMessage("ReSharper", "ReturnValueOfPureMethodIsNotUsed")]
+        private static void ExecuteTwoQueries(ICache<int, Person> cache)
+        {
+            IQueryable<ICacheEntry<int, Person>> queryable = cache.AsCacheQueryable();
+
+            queryable.Count(p => p.Value.Age > 0);
+
+            queryable.Count(p => p.Value.Age > 1000);
+        }
+
+        /// <summary>
+        /// Check metrics after two queries are executed.
+        /// </summary>
+        /// <param name="metrics">Query metrics.</param>
+        private static void CheckMetrics(IQueryMetrics metrics)
+        {
+            Assert.AreEqual(2, metrics.Executions, "Check Executions count.");
+            Assert.AreEqual(0, metrics.Fails, "Check Fails count.");
+
+            Assert.GreaterOrEqual(metrics.MinimumTime, 0, "Check MinimumTime.");
+            Assert.GreaterOrEqual(metrics.MaximumTime, metrics.MinimumTime, "Check MaximumTime.");
+
+            Assert.AreEqual((double)(metrics.MinimumTime + metrics.MaximumTime) / 2, metrics.AverageTime, 1, "Check AverageTime.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs
index c4e50d1..0fe16a5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs
@@ -573,6 +573,16 @@ namespace Apache.Ignite.Core.Tests.Cache
         {
             return GetEnumerator();
         }
+
+        public IQueryMetrics GetQueryMetrics()
+        {
+            return _cache.GetQueryMetrics();
+        }
+
+        public void ResetQueryMetrics()
+        {
+            _cache.ResetQueryMetrics();
+        }
     }
 
     /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 93c45c3..f217a0d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -54,6 +54,7 @@
     <Compile Include="Binary\TimestampAttribute.cs" />
     <Compile Include="Cache\Configuration\CacheKeyConfiguration.cs" />
     <Compile Include="Cache\Configuration\DataPageEvictionMode.cs" />
+    <Compile Include="Cache\IQueryMetrics.cs" />
     <Compile Include="Client\Cache\CacheClientConfiguration.cs" />
     <Compile Include="Client\IgniteClientConfigurationSection.cs" />
     <Compile Include="Client\ISslStreamFactory.cs" />
@@ -72,6 +73,7 @@
     <Compile Include="Client\IgniteClientException.cs" />
     <Compile Include="Client\IIgniteClient.cs" />
     <Compile Include="Common\ExceptionFactory.cs" />
+    <Compile Include="Impl\Cache\QueryMetricsImpl.cs" />
     <Compile Include="Impl\Common\TaskRunner.cs" />
     <Compile Include="Ssl\ISslContextFactory.cs" />
     <Compile Include="Configuration\Package-Info.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Cache/ICache.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/ICache.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/ICache.cs
index 8a9fe59..8f52e03 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/ICache.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/ICache.cs
@@ -907,5 +907,16 @@ namespace Apache.Ignite.Core.Cache
         /// and <see cref="IIgnite.ResetLostPartitions(IEnumerable{string})"/>.
         /// </summary>
         ICollection<int> GetLostPartitions();
+
+        /// <summary>
+        /// Gets query metrics.
+        /// </summary>
+        /// <returns>Query metrics.</returns>
+        IQueryMetrics GetQueryMetrics();
+
+        /// <summary>
+        /// Reset query metrics.
+        /// </summary>
+        void ResetQueryMetrics();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Cache/IQueryMetrics.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/IQueryMetrics.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/IQueryMetrics.cs
new file mode 100644
index 0000000..232bf99
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/IQueryMetrics.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Cache
+{
+    /// <summary>
+    /// Cache query metrics used to obtain statistics on query.
+    /// </summary>
+    public interface IQueryMetrics
+    {
+        /// <summary>
+        /// Gets minimum execution time of query.
+        /// </summary>
+        /// <returns>
+        /// Minimum execution time of query.
+        /// </returns>
+        long MinimumTime { get; }
+
+        /// <summary>
+        /// Gets maximum execution time of query.
+        /// </summary>
+        /// <returns>
+        /// Maximum execution time of query.
+        /// </returns>
+        long MaximumTime { get; }
+
+        /// <summary>
+        /// Gets average execution time of query.
+        /// </summary>
+        /// <returns>
+        /// Average execution time of query.
+        /// </returns>
+        double AverageTime { get; }
+
+        /// <summary>
+        /// Gets total number execution of query.
+        /// </summary>
+        /// <returns>
+        /// Number of executions.
+        /// </returns>
+        int Executions { get; }
+
+        /// <summary>
+        /// Gets total number of times a query execution failed.
+        /// </summary>
+        /// <returns>
+        /// Total number of times a query execution failed.
+        /// </returns>
+        int Fails { get; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index 6661161..6e46f4d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -1408,5 +1408,22 @@ namespace Apache.Ignite.Core.Impl.Cache
             if (_txManager != null)
                 _txManager.StartTx();
         }
+
+        /** <inheritdoc /> */
+        public IQueryMetrics GetQueryMetrics()
+        {
+            return DoInOp((int)CacheOp.QueryMetrics, stream =>
+            {
+                IBinaryRawReader reader = Marshaller.StartUnmarshal(stream, false);
+
+                return new QueryMetricsImpl(reader);
+            });
+        }
+
+        /** <inheritdoc /> */
+        public void ResetQueryMetrics()
+        {
+            DoOutInOp((int)CacheOp.ResetQueryMetrics);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheOp.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheOp.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheOp.cs
index b3cbd95..00a7135 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheOp.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheOp.cs
@@ -104,6 +104,8 @@ namespace Apache.Ignite.Core.Impl.Cache
         PutIfAbsentAsync = 81,
         Extension = 82,
         GlobalMetrics = 83,
-        GetLostPartitions = 84
+        GetLostPartitions = 84,
+        QueryMetrics = 85,
+        ResetQueryMetrics = 86
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ea8bfac6/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/QueryMetricsImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/QueryMetricsImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/QueryMetricsImpl.cs
new file mode 100644
index 0000000..d71d40e0
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/QueryMetricsImpl.cs
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Cache
+{
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache;
+
+    /// <summary>
+    /// Cache query metrics used to obtain statistics on query.
+    /// </summary>
+    internal class QueryMetricsImpl : IQueryMetrics
+    {
+        /** */
+        private readonly long _minimumTime;
+
+        /** */
+        private readonly long _maximumTime;
+
+        /** */
+        private readonly double _averageTime;
+
+        /** */
+        private readonly int _executions;
+
+        /** */
+        private readonly int _fails;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="QueryMetricsImpl"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public QueryMetricsImpl(IBinaryRawReader reader)
+        {
+            _minimumTime = reader.ReadLong();
+            _maximumTime = reader.ReadLong();
+            _averageTime = reader.ReadDouble();
+            _executions = reader.ReadInt();
+            _fails = reader.ReadInt();
+        }
+
+        /** <inheritDoc /> */
+        public long MinimumTime { get { return _minimumTime; } }
+
+        /** <inheritDoc /> */
+        public long MaximumTime { get { return _maximumTime; } }
+
+        /** <inheritDoc /> */
+        public double AverageTime { get { return _averageTime; } }
+
+        /** <inheritDoc /> */
+        public int Executions { get { return _executions; } }
+
+        /** <inheritDoc /> */
+        public int Fails { get { return _fails; } }
+    }
+}
\ No newline at end of file