You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2018/04/23 07:12:19 UTC
[23/50] [abbrv] ignite git commit: IGNITE-6681 .NET: QueryMetrics
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/ignite-6083
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