[REEF-1481] Develop basic metrics APIs for REEF.Net

This adds the APIs for metrics in Org.Apache.REEF.Common.

JIRA:
  [REEF-1481](https://issues.apache.org/jira/browse/REEF-1481)

Pull Request:
  This closes #1073


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

Branch: refs/heads/master
Commit: 0b8da4cfc3761b38339b03870eb4bb75f90811d0
Parents: af63bf6
Author: dhruv <[email protected]>
Authored: Fri Jul 8 23:15:38 2016 -0700
Committer: Markus Weimer <[email protected]>
Committed: Tue Aug 30 09:37:22 2016 -0700

----------------------------------------------------------------------
 .../Org.Apache.REEF.Common.Tests.csproj         |  12 +-
 .../metrics/DefaultMetricSourceTests.cs         | 581 +++++++++++++++++++
 .../metrics/ImmutableMetricTest.cs              | 189 ++++++
 .../metrics/MetricTestUtils.cs                  | 179 ++++++
 .../metrics/MutableMetricTest.cs                | 213 +++++++
 .../metrics/SnapshotRequestTest.cs              | 100 ++++
 .../metrics/TestMetricsTag.cs                   |  82 +++
 .../Org.Apache.REEF.Common.csproj               |  36 ++
 .../metrics/Api/IImmutableMetric.cs             |  90 +++
 .../metrics/Api/IMetricsCollector.cs            |  47 ++
 .../metrics/Api/IMetricsFilter.cs               |  49 ++
 .../metrics/Api/IMetricsInfo.cs                 |  38 ++
 .../metrics/Api/IMetricsRecord.cs               |  63 ++
 .../metrics/Api/IMetricsRecordBuilder.cs        | 104 ++++
 .../metrics/Api/IMetricsSource.cs               |  42 ++
 .../metrics/Api/IMetricsSystem.cs               |  77 +++
 .../metrics/Api/IMetricsVisitor.cs              |  56 ++
 .../metrics/Api/ImmutableMetricImpl.cs          | 153 +++++
 .../metrics/Api/MetricType.cs                   |  39 ++
 .../metrics/Api/MetricsException.cs             |  58 ++
 .../metrics/Api/MetricsInfoImpl.cs              |  58 ++
 .../metrics/Api/MetricsTag.cs                   | 114 ++++
 .../metrics/Api/SnapshotRequest.cs              |  59 ++
 .../DefaultMetricsFactoryImpl.cs                | 163 ++++++
 .../DefaultMetricsSourceConfiguration.cs        |  62 ++
 .../DefaultMetricsSourceImpl.cs                 | 220 +++++++
 .../DefaultMetricsSourceParameters.cs           |  46 ++
 .../metrics/MutableMetricsLayer/ICounter.cs     |  40 ++
 .../metrics/MutableMetricsLayer/IDoubleGauge.cs |  57 ++
 .../IExtendedMutableMetric.cs                   |  41 ++
 .../metrics/MutableMetricsLayer/ILongGauge.cs   |  57 ++
 .../MutableMetricsLayer/IMetricContainer.cs     |  54 ++
 .../MutableMetricsLayer/IMetricsFactory.cs      | 128 ++++
 .../MutableMetricsLayer/IMutableMetric.cs       |  41 ++
 .../metrics/MutableMetricsLayer/IRate.cs        |  30 +
 .../metrics/MutableMetricsLayer/IStat.cs        |  35 ++
 .../MutableMetricsLayer/MutableCounter.cs       | 103 ++++
 .../MutableMetricsLayer/MutableDoubleGauge.cs   | 137 +++++
 .../MutableMetricsLayer/MutableLongGauge.cs     | 136 +++++
 .../MutableMetricsLayer/MutableMetricBase.cs    | 132 +++++
 .../MutableMetricContainer.cs                   | 111 ++++
 .../metrics/MutableMetricsLayer/MutableRate.cs  |  50 ++
 .../metrics/MutableMetricsLayer/MutableStat.cs  | 176 ++++++
 .../MutableMetricsLayer/StatsHelperClass.cs     | 175 ++++++
 44 files changed, 4432 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj 
b/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
index dd5e13d..f339a59 100644
--- a/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/Org.Apache.REEF.Common.Tests.csproj
@@ -43,6 +43,12 @@ under the License.
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Metrics\DefaultMetricSourceTests.cs" />
+    <Compile Include="Metrics\ImmutableMetricTest.cs" />
+    <Compile Include="Metrics\MetricTestUtils.cs" />
+    <Compile Include="Metrics\MutableMetricTest.cs" />
+    <Compile Include="Metrics\SnapshotRequestTest.cs" />
+    <Compile Include="Metrics\TestMetricsTag.cs" />
     <Compile Include="TestHttpSerialization.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
@@ -55,6 +61,10 @@ under the License.
       <Project>{79e7f89a-1dfb-45e1-8d43-d71a954aeb98}</Project>
       <Name>Org.Apache.REEF.Utilities</Name>
     </ProjectReference>
+    <ProjectReference 
Include="$(SolutionDir)\Org.Apache.REEF.Tang\Org.Apache.REEF.Tang.csproj">
+      <Project>{97dbb573-3994-417a-9f69-ffa25f00d2a6}</Project>
+      <Name>Org.Apache.REEF.Tang</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
@@ -65,4 +75,4 @@ under the License.
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" 
Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
   <Import 
Project="$(PackagesDir)\StyleCop.MSBuild.$(StyleCopVersion)\build\StyleCop.MSBuild.Targets"
 
Condition="Exists('$(PackagesDir)\StyleCop.MSBuild.$(StyleCopVersion)\build\StyleCop.MSBuild.Targets')"
 />
-</Project>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/DefaultMetricSourceTests.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/DefaultMetricSourceTests.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/DefaultMetricSourceTests.cs
new file mode 100644
index 0000000..bdf9e21
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/DefaultMetricSourceTests.cs
@@ -0,0 +1,581 @@
+// 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.
+
+using System.Linq;
+using Org.Apache.REEF.Common.Metrics.Api;
+using Org.Apache.REEF.Common.Metrics.MutableMetricsLayer;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Interface;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    ///  Tests different functionalities of <see 
cref="DefaultMetricsSourceImpl"/>
+    /// </summary>
+    public sealed class DefaultMetricSourceTests
+    {
+        /// <summary>
+        /// Tests <see cref="DefaultMetricsSourceConfiguration"/>
+        /// </summary>
+        [Fact]
+        public void TestMetricsSourceConfiguration()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            Assert.NotNull(metricsSource);
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+            metricsSource.GetMetrics(collector, true);
+            Assert.Equal(collector.CurrentRecordBuilder.Name, recordName);
+            Assert.Equal(collector.CurrentRecordBuilder.Context, 
sourceContext);
+            collector.CurrentRecordBuilder.Validate("TaskOrContextName", 
taskId);
+            collector.CurrentRecordBuilder.Validate("EvaluatorId", evalId);
+        }
+
+        /// <summary>
+        /// Tests creating, accessing and updating counters from  <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceCounters()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] counterNames = { "cname1", "cname2" };
+            const long counterIncr = 2;
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create Counters
+            foreach (var name in counterNames)
+            {
+                metricsSource.Counters.Create(name, name);
+            }
+   
+            // Update counters.
+            int counter = 1;
+            foreach (var name in counterNames)
+            {
+                metricsSource.Counters[name].Increment(counter * counterIncr);
+                counter++;
+            }
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+
+            // Validate counters
+            counter = 1;
+            foreach (var name in counterNames)
+            {
+                rb.Validate(name, counter * counterIncr);
+                counter++;
+            }           
+        }
+
+        /// <summary>
+        /// Tests creating, accessing and updating long gauge from <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceLongGauges()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] longGaugeNames = { "lname1", "lname2" };
+            const long longGaugeIncr = 3;
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create long gauge
+            foreach (var name in longGaugeNames)
+            {
+                metricsSource.LongGauges.Create(name, name);
+            }
+
+            // Update long gauge
+            int counter = 1;
+            foreach (var name in longGaugeNames)
+            {
+                metricsSource.LongGauges[name].Increment(counter * 
longGaugeIncr);
+                counter++;
+            }
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+
+            // Validate long gauges
+            counter = 1;
+            foreach (var name in longGaugeNames)
+            {
+                rb.Validate(name, counter * longGaugeIncr);
+                counter++;
+            }
+        }
+
+        /// <summary>
+        /// Tests creating, accessing and updating double gauge from <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceDoubleGauges()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] doubleGaugeNames = { "dname1", "dname2" };
+            const double doubleGaugeDecr = 1.2;
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create double gauge
+            foreach (var name in doubleGaugeNames)
+            {
+                metricsSource.DoubleGauges.Create(name, name);
+            }
+
+            // Update double gauge
+            int counter = 1;
+            foreach (var name in doubleGaugeNames)
+            {
+                metricsSource.DoubleGauges[name].Decrement(counter * 
doubleGaugeDecr);
+                counter++;
+            }
+        
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+
+            // Validate double gauges
+            counter = 1;
+            foreach (var name in doubleGaugeNames)
+            {
+                rb.Validate(name, -counter * doubleGaugeDecr, 1e-10);
+                counter++;
+            }
+        }
+
+        /// <summary>
+        /// Tests creating, accessing and updating rate from <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceRate()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            const string rateName = "rname1";
+            double[] samples = { 2, 3 };
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create rate.
+            metricsSource.Rates.Create(rateName, rateName);
+
+            // Update rate
+            foreach (var sample in samples)
+            {
+                metricsSource.Rates[rateName].Sample(sample);
+            }
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+          
+            // Validate rate
+            rb.Validate(rateName + "-Num", samples.Length);
+            rb.Validate(rateName + "-RunningAvg", samples.Sum() / 
samples.Length, 1e-10);
+        }
+
+        /// <summary>
+        /// Tests creating and accessing tags from <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceTags()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] tagNames = { "tname1", "tname2" };
+            string[] tagValues = { "tvalue1", "tValue2" };
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create tags
+            for (int i = 0; i < tagNames.Length; i++)
+            {
+                metricsSource.AddTag(tagNames[i], tagNames[i], tagValues[i]);
+            }
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+
+            // Validate tags
+            for (int i = 0; i < tagNames.Length; i++)
+            {
+                rb.Validate(tagNames[i], tagValues[i]);
+            }
+
+            // Verify GetTag functionality
+            var tag = metricsSource.GetTag(tagNames[0]);
+            Assert.NotNull(tag);
+            Assert.Equal(tag.Name, tagNames[0]);
+            Assert.Equal(tag.Value, tagValues[0]);
+
+            string inValidName = "invalid";
+            tag = metricsSource.GetTag(inValidName);
+            Assert.Null(tag);
+        }
+
+        /// <summary>
+        /// Tests whether we can externally subscribe metrics to <see 
cref="DefaultMetricsSourceImpl"/> 
+        /// and then unsubscribe.
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceExternalMetricsSubscription()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            const string subscribedCounterName = "subscribedcounter";
+            const long subscribedCounterValue = 1001;
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+         
+            var extraCounter = factory.CreateCounter(subscribedCounterName,
+                subscribedCounterName,
+                subscribedCounterValue);
+            extraCounter.Subscribe(metricsSource);
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+            rb.Validate(subscribedCounterName, subscribedCounterValue);
+
+            extraCounter.Increment();
+            extraCounter.OnCompleted(); // This should remove the counter from 
the metrics source.
+            metricsSource.GetMetrics(collector, true);
+            rb = collector.CurrentRecordBuilder;
+            Assert.False(rb.LongKeyPresent(subscribedCounterName), "The 
counter should not be present now in the source");
+        }
+
+        /// <summary>
+        /// Tests whether exceptions are thrown while trying to access not 
created 
+        /// metrics in <see cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceInvalidAccessExceptions()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+           
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+    
+            // Checks that exception is thrown while trying to get metrics 
that are not created.
+            string inValidName = "invalid";
+            Assert.Throws<MetricsException>(() => 
metricsSource.Counters[inValidName]);
+            Assert.Throws<MetricsException>(() => 
metricsSource.DoubleGauges[inValidName]);
+            Assert.Throws<MetricsException>(() => 
metricsSource.LongGauges[inValidName]);
+            Assert.Throws<MetricsException>(() => 
metricsSource.Rates[inValidName]);
+        }
+
+        /// <summary>
+        /// Tests whether exceptions are thrown while trying to recreate 
already 
+        /// existing metrics in <see cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceRecreationExceptions()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string counterName = "cname1";
+            string longGaugeName = "lname1";
+            string doubleGaugeName = "dname1";
+            const string rateName = "rname1";
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            metricsSource.Counters.Create(counterName, counterName);
+            metricsSource.LongGauges.Create(longGaugeName, longGaugeName);
+            metricsSource.DoubleGauges.Create(doubleGaugeName, 
doubleGaugeName);
+            metricsSource.Rates.Create(rateName, rateName);
+
+            Assert.Throws<MetricsException>(() => 
metricsSource.Counters.Create(counterName, counterName));
+            Assert.Throws<MetricsException>(
+                () => metricsSource.DoubleGauges.Create(doubleGaugeName, 
doubleGaugeName));
+            Assert.Throws<MetricsException>(
+                () => metricsSource.LongGauges.Create(longGaugeName, 
longGaugeName));
+            Assert.Throws<MetricsException>(() => 
metricsSource.Rates.Create(rateName, rateName));
+        }
+
+        /// <summary>
+        /// Tests whether metrics are properly deleted from <see 
cref="DefaultMetricsSourceImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceMetricDeletion()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string counterName = "cname1";
+            string longGaugeName = "lname1";
+            string doubleGaugeName = "dname1";
+            const string rateName = "rname1";
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            metricsSource.Counters.Create(counterName, counterName);
+            metricsSource.LongGauges.Create(longGaugeName, longGaugeName);
+            metricsSource.DoubleGauges.Create(doubleGaugeName, 
doubleGaugeName);
+            metricsSource.Rates.Create(rateName, rateName);
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            metricsSource.Counters.Delete(counterName);
+            Assert.Throws<MetricsException>(() => 
metricsSource.Counters[counterName]);
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+            Assert.False(rb.LongKeyPresent(counterName), "Counter was removed, 
so it should not be present");
+        }
+
+        /// <summary>
+        ///  Verifies that record builder does not get old stats if the flag 
is set to false. 
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceGetMetricsFlag()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] counterNames = { "cname1", "cname2" };
+ 
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create Counters
+            foreach (var name in counterNames)
+            {
+                metricsSource.Counters.Create(name, name);
+            }
+
+            metricsSource.GetMetrics(collector, true);
+
+            // Do not increment second counter.
+            metricsSource.Counters[counterNames[0]].Increment();
+            
+            // Verifies that record builder does not get old stats if the flag 
is set to false. 
+            // Only first counter should be present.
+            metricsSource.GetMetrics(collector, false);
+            var rb = collector.CurrentRecordBuilder;
+            Assert.True(rb.LongKeyPresent(counterNames[0]), "Counter was 
updated, so it should be present");
+            Assert.False(rb.LongKeyPresent(counterNames[1]), "Counter was not 
updated, so it should not be present");
+        }
+
+        /// <summary>
+        /// Tests inserting counters, gauges, rates in one go to <see 
cref="DefaultMetricsSourceImpl"/> 
+        /// to make sure there are no across container bugs.
+        /// </summary>
+        [Fact]
+        public void TestDefaultMetricsSourceHetergeneousFunctionalities()
+        {
+            const string evalId = "evalId";
+            const string taskId = "taskId";
+            const string sourceContext = "test";
+            const string recordName = "testrecord";
+            string[] counterNames = { "cname1", "cname2" };
+            string[] longGaugeNames = { "lname1", "lname2" };
+            string[] doubleGaugeNames = { "dname1", "dname2" };
+            const string rateName = "rname1";
+            double[] samples = { 2, 3 };
+            string[] tagNames = { "tname1", "tname2" };
+            string[] tagValues = { "tvalue1", "tValue2" };
+            const long counterIncr = 2;
+            const long longGaugeIncr = 3;
+            const double doubleGaugeDecr = 1.2;
+            const string subscribedCounterName = "subscribedcounter";
+            const long subscribedCounterValue = 1001;
+
+            DefaultMetricsSourceImpl metricsSource = 
TangFactory.GetTang().NewInjector(
+                GenerateMetricsSourceConfiguration(evalId, taskId, 
sourceContext, recordName))
+                .GetInstance<DefaultMetricsSourceImpl>();
+
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+
+            MetricTestUtils.MetricsCollectorTestImpl collector = new 
MetricTestUtils.MetricsCollectorTestImpl();
+
+            // Create Counters
+            foreach (var name in counterNames)
+            {
+                metricsSource.Counters.Create(name, name);
+            }
+
+            // Create long gauge
+            foreach (var name in longGaugeNames)
+            {
+                metricsSource.LongGauges.Create(name, name);
+            }
+
+            // Create double gauge
+            foreach (var name in doubleGaugeNames)
+            {
+                metricsSource.DoubleGauges.Create(name, name);
+            }
+
+            // Create rate.
+            metricsSource.Rates.Create(rateName, rateName);
+
+            // Update counters.
+            int counter = 1;
+            foreach (var name in counterNames)
+            {
+                metricsSource.Counters[name].Increment(counter * counterIncr);
+                counter++;
+            }
+
+            // Update long gauge
+            counter = 1;
+            foreach (var name in longGaugeNames)
+            {
+                metricsSource.LongGauges[name].Increment(counter * 
longGaugeIncr);
+                counter++;
+            }
+
+            // Update double gauge
+            counter = 1;
+            foreach (var name in doubleGaugeNames)
+            {
+                metricsSource.DoubleGauges[name].Decrement(counter * 
doubleGaugeDecr);
+                counter++;
+            }
+
+            // Update rate
+            foreach (var sample in samples)
+            {
+                metricsSource.Rates[rateName].Sample(sample);
+            }
+
+            // Create tags
+            for (int i = 0; i < tagNames.Length; i++)
+            {
+                metricsSource.AddTag(tagNames[i], tagNames[i], tagValues[i]);
+            }
+
+            var extraCounter = factory.CreateCounter(subscribedCounterName,
+                subscribedCounterName,
+                subscribedCounterValue);
+            extraCounter.Subscribe(metricsSource);
+
+            metricsSource.GetMetrics(collector, true);
+            var rb = collector.CurrentRecordBuilder;
+
+            // Validate counters
+            counter = 1;
+            foreach (var name in counterNames)
+            {
+                rb.Validate(name, counter * counterIncr);
+                counter++;
+            }
+            rb.Validate(subscribedCounterName, subscribedCounterValue);
+
+            // Validate long gauges
+            counter = 1;
+            foreach (var name in longGaugeNames)
+            {
+                rb.Validate(name, counter * longGaugeIncr);
+                counter++;
+            }
+
+            // Validate double gauges
+            counter = 1;
+            foreach (var name in doubleGaugeNames)
+            {
+                rb.Validate(name, -counter * doubleGaugeDecr, 1e-10);
+                counter++;
+            }
+
+            // Validate tags
+            for (int i = 0; i < tagNames.Length; i++)
+            {
+                rb.Validate(tagNames[i], tagValues[i]);
+            }
+
+            // Validate rate
+            rb.Validate(rateName + "-Num", samples.Length);
+            rb.Validate(rateName + "-RunningAvg", samples.Sum() / 
samples.Length, 1e-10);         
+        }
+
+        private static IConfiguration 
GenerateMetricsSourceConfiguration(string evalId, string taskId, string 
sourceContext, string recordName)
+        {
+            return
+                
DefaultMetricsSourceConfiguration.ConfigurationModule.Set(DefaultMetricsSourceConfiguration.EvaluatorId,
+                    evalId)
+                    .Set(DefaultMetricsSourceConfiguration.TaskOrContextId, 
taskId)
+                    .Set(DefaultMetricsSourceConfiguration.RecordId, 
recordName)
+                    .Set(DefaultMetricsSourceConfiguration.SourceContext, 
sourceContext)
+                    .Build();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/ImmutableMetricTest.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/ImmutableMetricTest.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/ImmutableMetricTest.cs
new file mode 100644
index 0000000..67ed5b0
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/ImmutableMetricTest.cs
@@ -0,0 +1,189 @@
+// 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.
+
+using Org.Apache.REEF.Common.Metrics.Api;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    /// Tests various functionalities of <see cref="ImmutableMetricsImpl"/>
+    /// </summary>
+    public sealed class ImmutableMetricTest
+    {
+        /// <summary>
+        /// Tests properties for numeric value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestNumericImmutableMetricProperties()
+        {
+            const double dValue = 5.0;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+
+            ImmutableMetricsImpl metric = new ImmutableMetricsImpl(info,
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.Equal(metric.Info.Name, name);
+            Assert.Equal(metric.Info.Description, desc);
+            Assert.False(metric.LongValue != null);
+            Assert.Equal(metric.NumericValue, dValue);
+            Assert.Equal(metric.TypeOfMetric, MetricType.Counter);
+        }
+
+        /// <summary>
+        /// Tests properties for long value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestLongImmutableMetricProperties()
+        {
+            const long lValue = 6;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+
+            var metric = new ImmutableMetricsImpl(info, lValue, 
MetricType.Counter, (metricsVisitor) => { });
+            Assert.Equal(metric.Info.Name, name);
+            Assert.Equal(metric.Info.Description, desc);
+            Assert.False(metric.NumericValue != null);
+            Assert.Equal(metric.LongValue, lValue);
+            Assert.Equal(metric.TypeOfMetric, MetricType.Counter);
+        }
+
+        /// <summary>
+        /// Tests Equality function for numeric value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestNumericImmutableMetricEqualityFunction()
+        {
+            const double dValue = 5.0;
+            const long lValue = 6;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+
+            ImmutableMetricsImpl metric = new ImmutableMetricsImpl(info,
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+
+            ImmutableMetricsImpl otherMetric = new ImmutableMetricsImpl(info,
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.True(metric.Equals(otherMetric));
+            otherMetric = new ImmutableMetricsImpl(info, lValue, 
MetricType.Counter, (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            otherMetric = new ImmutableMetricsImpl(new 
MetricsInfoImpl("wrongname", desc),
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            otherMetric = new ImmutableMetricsImpl(new MetricsInfoImpl(name, 
"wrongdesc"),
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            otherMetric = new ImmutableMetricsImpl(info, dValue, 
MetricType.Gauge, (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+        }
+
+        /// <summary>
+        /// Tests Equality function for long value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestLongImmutableMetricEqualityFunction()
+        {
+            const double dValue = 5.0;
+            const long lValue = 6;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+
+            ImmutableMetricsImpl metric = new ImmutableMetricsImpl(info,
+                lValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+
+            var otherMetric = new ImmutableMetricsImpl(info, lValue, 
MetricType.Counter, (metricsVisitor) => { });
+            otherMetric = new ImmutableMetricsImpl(info, dValue, 
MetricType.Counter, (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            
+            otherMetric = new ImmutableMetricsImpl(new 
MetricsInfoImpl("wrongname", desc),
+                lValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            
+            otherMetric = new ImmutableMetricsImpl(new MetricsInfoImpl(name, 
"wrongdesc"),
+                lValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+            
+            otherMetric = new ImmutableMetricsImpl(info, lValue, 
MetricType.Gauge, (metricsVisitor) => { });
+            Assert.False(metric.Equals(otherMetric));
+        }
+
+        /// <summary>
+        /// Tests ToString function for numeric value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestNumericImmutableMetricToStringFunction()
+        {
+            const double dValue = 5.0;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+            string expectedDoubleString = string.Format("Metric Type: {0}, 
Metric Information: {1}, Metric Value: {2}",
+                MetricType.Counter,
+                info,
+                dValue);
+
+            ImmutableMetricsImpl metric = new ImmutableMetricsImpl(info,
+                dValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.Equal(metric.ToString(), expectedDoubleString);
+        }
+
+        /// <summary>
+        /// Tests ToString function for long value in <see 
cref="ImmutableMetricsImpl"/>
+        /// </summary>
+        [Fact]
+        public void TestLongImmutableMetricToStringFunction()
+        {
+            const long lValue = 6;
+            const string name = "testname";
+            const string desc = "testdesc";
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+
+            string expectedLongString = string.Format("Metric Type: {0}, 
Metric Information: {1}, Metric Value: {2}",
+                MetricType.Counter,
+                info,
+                lValue);
+
+            ImmutableMetricsImpl metric = new ImmutableMetricsImpl(info,
+                lValue,
+                MetricType.Counter,
+                (metricsVisitor) => { });
+            Assert.Equal(metric.ToString(), expectedLongString);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs
new file mode 100644
index 0000000..357e8a5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs
@@ -0,0 +1,179 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using Org.Apache.REEF.Common.Metrics.Api;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    internal static class MetricTestUtils
+    {
+        /// <summary>
+        /// Implementation of <see cref="IMetricsRecordBuilder"/> to test 
Snapshot functions of 
+        /// different Mutable metrics.
+        /// </summary>
+        internal sealed class RecordBuilderForTests : IMetricsRecordBuilder
+        {
+            private readonly Dictionary<string, long> _longMetricVals = new 
Dictionary<string, long>();
+            private readonly Dictionary<string, double> _doubleMetricVals = 
new Dictionary<string, double>();
+            private readonly Dictionary<string, string> _tagVals = new 
Dictionary<string, string>();
+
+            public RecordBuilderForTests()
+            {
+            }
+
+            public RecordBuilderForTests(string name)
+            {
+                Name = name;
+            }
+
+            public string Name { get; private set; }
+
+            public string Context { get; private set; }
+
+            public IMetricsRecordBuilder AddTag(string name, string value)
+            {
+                _tagVals[name] = value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder AddTag(IMetricsInfo info, string 
value)
+            {
+                _tagVals[info.Name] = value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder Add(MetricsTag tag)
+            {
+                _tagVals[tag.Name] = tag.Value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder Add(IImmutableMetric metric)
+            {
+                throw new NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder SetContext(string value)
+            {
+                Context = value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder AddCounter(IMetricsInfo info, long 
value)
+            {
+                _longMetricVals[info.Name] = value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder AddGauge(IMetricsInfo info, double 
value)
+            {
+                _doubleMetricVals[info.Name] = value;
+                return this;
+            }
+
+            public IMetricsRecordBuilder AddGauge(IMetricsInfo info, long 
value)
+            {
+                _longMetricVals[info.Name] = value;
+                return this;
+            }
+
+            public IMetricsCollector ParentCollector()
+            {
+                throw new NotImplementedException();
+            }
+
+            public IMetricsCollector EndRecord()
+            {
+                throw new NotImplementedException();
+            }
+
+            public void Validate(string name, long expected)
+            {
+                if (!_longMetricVals.ContainsKey(name))
+                {
+                    Assert.True(false, "Metric name not present");
+                }
+                Assert.Equal(expected, _longMetricVals[name]);
+            }
+
+            public void Validate(string name, double expected, double delta)
+            {
+                if (!_doubleMetricVals.ContainsKey(name))
+                {
+                    Assert.True(false, "Metric name not present");
+                }
+                Assert.True(Math.Abs(expected - _doubleMetricVals[name]) < 
delta);
+            }
+
+            public void Validate(string tagName, string expectedTagVal)
+            {
+                if (!_tagVals.ContainsKey(tagName))
+                {
+                    Assert.True(false, "Tag name not present");
+                }
+                Assert.Equal(expectedTagVal, _tagVals[tagName]);
+            }
+
+            public bool LongKeyPresent(string name)
+            {
+                return _longMetricVals.ContainsKey(name);
+            }
+
+            public bool DoubleKeyPresent(string name)
+            {
+                return _doubleMetricVals.ContainsKey(name);
+            }
+
+            public bool MetricsEmpty()
+            {
+                return _doubleMetricVals.Count == 0 && _longMetricVals.Count 
== 0;
+            }
+
+            public void Reset()
+            {
+                _longMetricVals.Clear();
+                _doubleMetricVals.Clear();
+                _tagVals.Clear();
+            }
+        }
+
+        /// <summary>
+        /// <see cref="IMetricsCollector"/> implementation for test purposes.
+        /// </summary>
+        internal sealed class MetricsCollectorTestImpl : IMetricsCollector
+        {
+            public RecordBuilderForTests CurrentRecordBuilder
+            {
+                get;
+                private set;
+            }
+            public IMetricsRecordBuilder CreateRecord(string name)
+            {
+                CurrentRecordBuilder = new RecordBuilderForTests(name);
+                return CurrentRecordBuilder;
+            }
+
+            public IMetricsRecordBuilder CreateRecord(IMetricsInfo info)
+            {
+                throw new System.NotImplementedException();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MutableMetricTest.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MutableMetricTest.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MutableMetricTest.cs
new file mode 100644
index 0000000..5a74aa3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MutableMetricTest.cs
@@ -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.
+
+using System;
+using System.Linq;
+using Org.Apache.REEF.Common.Metrics.Api;
+using Org.Apache.REEF.Common.Metrics.MutableMetricsLayer;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    /// Tests various classes in REEF.Common.metrics.MutableMetricsLib.
+    /// </summary>
+    public sealed class TestMutableMetrics
+    {
+        /// <summary>
+        /// Tests various functions of <see cref="MutableCounter"/>
+        /// </summary>
+        [Fact]
+        public void TestCounterMetrics()
+        {
+            const string name = "countertest";
+            const string desc = "countertestdesc";
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+
+            var longCounter = factory.CreateCounter(name, desc, 5);
+            Assert.Equal(name, longCounter.Info.Name);
+            Assert.Equal(desc, longCounter.Info.Description);
+
+            MetricTestUtils.RecordBuilderForTests recordBuilder = new 
MetricTestUtils.RecordBuilderForTests();
+            SnapshotRequest request = new SnapshotRequest(recordBuilder, 
false);
+
+            longCounter.OnNext(request);
+            recordBuilder.Validate(name, 5);
+            recordBuilder.Reset();
+
+            longCounter.Increment();
+            longCounter.OnNext(request);
+            recordBuilder.Validate(name, 6);
+            recordBuilder.Reset();
+
+            longCounter.OnNext(request);
+            Assert.False(recordBuilder.LongKeyPresent(name), "Metric is not 
supposed to be recorded.");
+
+            request = new SnapshotRequest(recordBuilder, true);
+            longCounter.OnNext(request);
+            recordBuilder.Validate(name, 6);
+            recordBuilder.Reset();
+        }
+
+        /// <summary>
+        /// Tests various functions of <see cref="MutableDoubleGauge"/> and 
<see cref="MutableLongGauge"/>.
+        /// </summary>
+        [Fact]
+        public void TestGaugeMetrics()
+        {
+            const string name = "gaugetest";
+            const string desc = "guagetestdesc";
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+
+            var doubleGauge = factory.CreateDoubleGauge(name, desc, 5);
+            Assert.Equal(name, doubleGauge.Info.Name);
+            Assert.Equal(desc, doubleGauge.Info.Description);
+
+            MetricTestUtils.RecordBuilderForTests recordBuilder = new 
MetricTestUtils.RecordBuilderForTests();
+            SnapshotRequest request = new SnapshotRequest(recordBuilder, 
false);
+
+            doubleGauge.OnNext(request);
+            recordBuilder.Validate(name, 5.0, 1e-10);
+            recordBuilder.Reset();
+
+            doubleGauge.Increment(2.2);
+            doubleGauge.OnNext(request);
+            recordBuilder.Validate(name, 7.2, 1e-10);
+            recordBuilder.Reset();
+
+            doubleGauge.Decrement(1);
+            doubleGauge.OnNext(request);
+            recordBuilder.Validate(name, 6.2, 1e-10);
+            recordBuilder.Reset();
+
+            doubleGauge.OnNext(request);
+            Assert.False(recordBuilder.DoubleKeyPresent(name), "Metric is not 
supposed to be recorded.");
+
+            request = new SnapshotRequest(recordBuilder, true);
+            doubleGauge.OnNext(request);
+            recordBuilder.Validate(name, 6.2, 1e-10);
+            recordBuilder.Reset();
+
+            request = new SnapshotRequest(recordBuilder, false);
+            var longGauge = factory.CreateLongGauge(name, desc, 5);
+            Assert.Equal(name, longGauge.Info.Name);
+            Assert.Equal(desc, longGauge.Info.Description);
+
+            longGauge.OnNext(request);
+            recordBuilder.Validate(name, (long)5);
+            recordBuilder.Reset();
+
+            longGauge.Increment(2);
+            longGauge.OnNext(request);
+            recordBuilder.Validate(name, (long)7);
+            recordBuilder.Reset();
+
+            longGauge.Decrement(1);
+            longGauge.OnNext(request);
+            recordBuilder.Validate(name, (long)6);
+            recordBuilder.Reset();
+
+            longGauge.OnNext(request);
+            Assert.False(recordBuilder.LongKeyPresent(name), "Metric is not 
supposed to be recorded.");
+
+            request = new SnapshotRequest(recordBuilder, true);
+            longGauge.OnNext(request);
+            recordBuilder.Validate(name, (long)6);
+            recordBuilder.Reset();
+        }
+
+        /// <summary>
+        /// Tests various functions of <see cref="MutableStat"/>.
+        /// </summary>
+        [Fact]
+        public void TestStatMetrics()
+        {
+            const string name = "stattest";
+            const string desc = "stattestdesc";
+            const string valueName = "statValName";
+            const double delta = 1e-10;
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+
+            double[] array1 = new double[3];
+            double[] array2 = new double[3];
+            Random randGen = new Random();
+
+            array1 = array1.Select(x => randGen.NextDouble()).ToArray();
+            array2 = array2.Select(x => randGen.NextDouble()).ToArray();
+
+            var stat = factory.CreateStatMetric(name, desc, valueName);
+            MetricTestUtils.RecordBuilderForTests recordBuilder = new 
MetricTestUtils.RecordBuilderForTests();
+            var request = new SnapshotRequest(recordBuilder, false);
+
+            foreach (var entry in array1)
+            {
+                stat.Sample(entry);
+            }
+
+            double expectedMean = array1.Sum() / 3;
+            double expectedStd = Math.Sqrt(array1.Select(x => Math.Pow(x - 
expectedMean, 2)).Sum() / 2);
+
+            stat.OnNext(request);
+            recordBuilder.Validate(name + "-Num", (long)3);
+            recordBuilder.Validate(name + "-RunningAvg", expectedMean, delta);
+            recordBuilder.Validate(name + "-RunningStdev", expectedStd, delta);
+            recordBuilder.Validate(name + "-IntervalAvg", expectedMean, delta);
+            recordBuilder.Validate(name + "-IntervalStdev", expectedStd, 
delta);
+            recordBuilder.Validate(name + "-RunningMin", array1.Min(), delta);
+            recordBuilder.Validate(name + "-IntervalMin", array1.Min(), delta);
+            recordBuilder.Validate(name + "-RunningMax", array1.Max(), delta);
+            recordBuilder.Validate(name + "-IntervalMax", array1.Max(), delta);
+
+            recordBuilder.Reset();
+            foreach (var entry in array2)
+            {
+                stat.Sample(entry);
+            }
+
+            double expectedIntervalMean = array2.Sum() / 3;
+            double expectedIntervalStd = Math.Sqrt(array2.Select(x => 
Math.Pow(x - expectedIntervalMean, 2)).Sum() / 2);
+            double expectedIntervalMin = array2.Min();
+            double expectedIntervalMax = array2.Max();
+            double expectedRunningMean = (array1.Sum() + array2.Sum()) / 6;
+            double expectedRunningStd =
+                Math.Sqrt((array1.Select(x => Math.Pow(x - 
expectedRunningMean, 2)).Sum() +
+                           array2.Select(x => Math.Pow(x - 
expectedRunningMean, 2)).Sum()) / 5);
+            double expectedRunningMin = Math.Min(array1.Min(), array2.Min());
+            double expectedRunningMax = Math.Max(array1.Max(), array2.Max());
+
+            stat.OnNext(request);
+            recordBuilder.Validate(name + "-Num", (long)6);
+            recordBuilder.Validate(name + "-RunningAvg", expectedRunningMean, 
delta);
+            recordBuilder.Validate(name + "-RunningStdev", expectedRunningStd, 
delta);
+            recordBuilder.Validate(name + "-IntervalAvg", 
expectedIntervalMean, delta);
+            recordBuilder.Validate(name + "-IntervalStdev", 
expectedIntervalStd, delta);
+            recordBuilder.Validate(name + "-RunningMin", expectedRunningMin, 
delta);
+            recordBuilder.Validate(name + "-IntervalMin", expectedIntervalMin, 
delta);
+            recordBuilder.Validate(name + "-RunningMax", expectedRunningMax, 
delta);
+            recordBuilder.Validate(name + "-IntervalMax", expectedIntervalMax, 
delta);
+
+            recordBuilder.Reset();
+            stat.OnNext(request);
+            Assert.False(recordBuilder.LongKeyPresent(name + "-Num"), "Metric 
is not supposed to be recorded.");
+
+            request = new SnapshotRequest(recordBuilder, true);
+            stat.OnNext(request);
+            Assert.True(recordBuilder.LongKeyPresent(name + "-Num"), "Metric 
is supposed to be recorded.");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs
new file mode 100644
index 0000000..05b1aa1
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs
@@ -0,0 +1,100 @@
+// 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.
+
+using Org.Apache.REEF.Common.Metrics.Api;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    /// Contains functions to test <see cref="SnapshotRequest"/> clkass.
+    /// </summary>
+    public sealed class SnapshotRequestTest
+    {
+        /// <summary>
+        /// Tests <see cref="SnapshotRequest"/>.
+        /// </summary>
+        [Fact]
+        public void TestSnapshotRequest()
+        {
+            var request = new SnapshotRequest(new 
MetricsRecordBuilderTestImpl(), true);
+            Assert.NotNull(request.Builder);
+            Assert.Equal(request.FullSnapshot, true);
+
+            request = new SnapshotRequest(new MetricsRecordBuilderTestImpl(), 
false);
+            Assert.NotNull(request.Builder);
+            Assert.Equal(request.FullSnapshot, false);
+
+            request = new SnapshotRequest(new MetricsRecordBuilderTestImpl());
+            Assert.NotNull(request.Builder);
+            Assert.Equal(request.FullSnapshot, false);
+        }
+
+        private class MetricsRecordBuilderTestImpl : IMetricsRecordBuilder
+        {
+            public IMetricsRecordBuilder AddTag(string name, string value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder AddTag(IMetricsInfo info, string 
value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder Add(MetricsTag tag)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder Add(IImmutableMetric metric)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder SetContext(string value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder AddCounter(IMetricsInfo info, long 
value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder AddGauge(IMetricsInfo info, long 
value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsRecordBuilder AddGauge(IMetricsInfo info, double 
value)
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsCollector ParentCollector()
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public IMetricsCollector EndRecord()
+            {
+                throw new System.NotImplementedException();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/TestMetricsTag.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/TestMetricsTag.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/TestMetricsTag.cs
new file mode 100644
index 0000000..fb0908e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/TestMetricsTag.cs
@@ -0,0 +1,82 @@
+// 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.
+
+using Org.Apache.REEF.Common.Metrics.Api;
+using Org.Apache.REEF.Common.Metrics.MutableMetricsLayer;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    /// Contains functions to test <see cref="MetricsTag"/> clkass.
+    /// </summary>
+    public sealed class TestMetricsTag
+    {
+        /// <summary>
+        /// Tests <see cref="MetricsInfoImpl"/>.
+        /// </summary>
+        [Fact]
+        public void TestMetricsInfoImpl()
+        {
+            const string name = "testname";
+            const string desc = "testdesc";
+
+            MetricsInfoImpl impl = new MetricsInfoImpl(name, desc);
+            Assert.Equal(name, impl.Name);
+            Assert.Equal(desc, impl.Description);
+        }
+
+        /// <summary>
+        /// Tests different functions of <see cref="MetricsTag"/>
+        /// </summary>
+        [Fact]
+        public void TestMetricsTagClass()
+        {
+            const string name = "tagtest";
+            const string otherName = "othertagtest";
+            const string desc = "tagtestdesc";
+            const string otherDesc = "othertagtestdesc";
+            const string tagValue = "tagvalue";
+            const string otherTagValue = "othertagvalue";
+            IMetricsFactory factory = 
TangFactory.GetTang().NewInjector().GetInstance<IMetricsFactory>();
+
+            IMetricsInfo info = new MetricsInfoImpl(name, desc);
+            MetricsTag tag = factory.CreateTag(info, tagValue);
+
+            Assert.Equal(name, tag.Name);
+            Assert.Equal(desc, tag.Description);
+            Assert.Equal(tagValue, tag.Value);
+
+            MetricsTag sameTag = factory.CreateTag(info, tagValue);
+            Assert.True(tag.Equals(sameTag));
+
+            MetricsTag otherTag = factory.CreateTag(info, otherTagValue);
+            Assert.False(tag.Equals(otherTag));
+
+            otherTag = factory.CreateTag(new MetricsInfoImpl(otherName, desc), 
tagValue);
+            Assert.False(tag.Equals(otherTag));
+
+            otherTag = factory.CreateTag(new MetricsInfoImpl(name, otherDesc), 
otherTagValue);
+            Assert.False(tag.Equals(otherTag));
+
+            string expectedToString = "Tag Information: " + "Name: " + 
info.Name + ", Description: " + info.Description +
+                                      ", Tag Value: " + tagValue;
+            Assert.Equal(expectedToString, tag.ToString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj 
b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
index cc14799..492ab5c 100644
--- a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
+++ b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
@@ -119,6 +119,42 @@ under the License.
     <Compile Include="Jar\ResourceHelper.cs" />
     <Compile Include="ITaskSubmittable.cs" />
     <Compile Include="Client\Parameters\DriverConfigurationProviders.cs" />
+    <Compile Include="Metrics\Api\ImmutableMetricImpl.cs" />
+    <Compile Include="Metrics\Api\IImmutableMetric.cs" />
+    <Compile Include="Metrics\Api\IMetricsCollector.cs" />
+    <Compile Include="Metrics\Api\IMetricsFilter.cs" />
+    <Compile Include="Metrics\Api\IMetricsInfo.cs" />
+    <Compile Include="Metrics\Api\IMetricsRecord.cs" />
+    <Compile Include="Metrics\Api\IMetricsRecordBuilder.cs" />
+    <Compile Include="Metrics\Api\IMetricsSource.cs" />
+    <Compile Include="Metrics\Api\IMetricsSystem.cs" />
+    <Compile Include="Metrics\Api\IMetricsVisitor.cs" />
+    <Compile Include="Metrics\Api\MetricsInfoImpl.cs" />
+    <Compile Include="Metrics\Api\MetricsException.cs" />
+    <Compile Include="Metrics\Api\MetricsTag.cs" />
+    <Compile Include="Metrics\Api\MetricType.cs" />
+    <Compile Include="Metrics\Api\SnapshotRequest.cs" />
+    <Compile 
Include="Metrics\MutableMetricsLayer\DefaultMetricsFactoryImpl.cs" />
+    <Compile 
Include="Metrics\MutableMetricsLayer\DefaultMetricsSourceConfiguration.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\DefaultMetricsSourceImpl.cs" 
/>
+    <Compile Include="Metrics\MutableMetricsLayer\ICounter.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IDoubleGauge.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IExtendedMutableMetric.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\ILongGauge.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IMetricsFactory.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IMutableMetric.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IRate.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IStat.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableCounter.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableDoubleGauge.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableLongGauge.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableMetricBase.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\IMetricContainer.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableMetricContainer.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableRate.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\MutableStat.cs" />
+    <Compile 
Include="Metrics\MutableMetricsLayer\DefaultMetricsSourceParameters.cs" />
+    <Compile Include="Metrics\MutableMetricsLayer\StatsHelperClass.cs" />
     <Compile Include="Poison\PoisonedEventHandler.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Protobuf\ReefProtocol\ClientRuntime.pb.cs">

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IImmutableMetric.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IImmutableMetric.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IImmutableMetric.cs
new file mode 100644
index 0000000..0241ee5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IImmutableMetric.cs
@@ -0,0 +1,90 @@
+// 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.
+
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Immutable metric interface. All the metrics put in the <see 
cref="IMetricsRecord"/> 
+    /// by <see cref="IMetricsSource"/> are kept as <see 
cref="IImmutableMetric"/>.
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IImmutableMetric
+    {
+        /// <summary>
+        /// Long Value of the metric. Immutable metrics of 
+        /// type integrals, byte, bool are all type casted to long before 
storing
+        /// them as immutable metrics. For a given instance of this interface, 
either this property 
+        /// or <see cref="NumericValue"/> returns a valid value.
+        /// </summary>
+        long? LongValue { get; }
+
+        /// <summary>
+        /// Numeric Value of the metric. Immutable metrics of 
+        /// non integral numerical types are all type casted to double before 
storing
+        /// them as immutable metrics. For a given instance of this interface, 
either this property 
+        /// or <see cref="LongValue"/> returns a valid value.
+        /// </summary>
+        double? NumericValue { get; }
+
+        /// <summary>
+        /// Meta-data of the metric.
+        /// </summary>
+        IMetricsInfo Info { get; }
+
+        /// <summary>
+        /// String representation of a metric for display.
+        /// </summary>
+        /// <returns>The string representation of the metric.</returns>
+        string ToString();
+
+        /// <summary>
+        /// Checks whether two metrics are equal. Relies on Equals 
+        /// function of <see cref="IMetricsInfo"/> implementations.
+        /// </summary>
+        /// <param name="obj">Object to compare against.</param>
+        /// <returns>True if both represent the same metric.</returns>
+        bool Equals(object obj);
+
+        /// <summary>
+        /// Return hash code of the metric object. Simply uses the hash of 
ToString() method.
+        /// </summary>
+        /// <returns>Hash code.</returns>
+        int GetHashCode();
+
+        /// <summary>
+        /// Type of metric - counter or gauge. Filled in by exact 
+        /// metric type. It is assumed that converting complex 
+        /// metrics like Stats and Rates in to immutable ones require 
+        /// their decomposition in to multiple instances of <see 
cref="IImmutableMetric"/>, 
+        /// for example: number of samples will be of type counter, mean, 
variance etc. 
+        /// will be of type gauge, etc.
+        /// </summary>
+        MetricType TypeOfMetric { get; }
+
+        /// <summary>
+        /// Accepts a visitor interface. This function is used to get exact 
+        /// metric specfic information (for example, if visitor implementation 
+        /// wants to determine whether it is a counter or gauge, etc., by 
making 
+        /// the exact implementation of <see cref="IImmutableMetric"/> call 
the 
+        /// appropriate function in <see cref="IMetricsVisitor"/>. 
+        /// </summary>
+        /// <param name="visitor">Metrics visitor interface.</param>
+        void Visit(IMetricsVisitor visitor);
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs
new file mode 100644
index 0000000..c9b51c5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs
@@ -0,0 +1,47 @@
+// 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.
+
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Interface for collecting the metrics. This interface is passed to 
+    /// the <see cref="IMetricsSource"/> to add and fill in the records.
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsCollector
+    {
+        /// <summary>
+        /// Creates a metric record by name. The exact semantics of what to do 
if another 
+        /// record of same name exists - (create another with same name, 
return existing one, 
+        /// or throw exception) is left to the implementation.
+        /// </summary>
+        /// <param name="name">Name of the record.</param>
+        /// <returns>Record builder for the record.</returns>
+        IMetricsRecordBuilder CreateRecord(string name);
+
+        /// <summary>
+        /// Creates a metric record by meta-data info. The exact semantics of 
what to do if another 
+        /// record of same name exists - (create another with same name, 
return existing one, 
+        /// or throw exception) is left to the implementation.
+        /// </summary>
+        /// <param name="info">Meta-data info of the record.</param>
+        /// <returns>Record builder for the record.</returns>
+        IMetricsRecordBuilder CreateRecord(IMetricsInfo info);
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs
new file mode 100644
index 0000000..3ef811b
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs
@@ -0,0 +1,49 @@
+// 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.
+
+using System;
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Metrics filter interface used to filter metrics at different levels - 
+    /// source and sink names, record, individual tag, individual metric.
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsFilter
+    {
+        /// <summary>
+        /// Returns a function indicating whether to accept the name string
+        /// (can be from metric, source, sink, record etc.). Returns True if 
accepted, 
+        /// false otherwise.
+        /// </summary>
+        Func<string, bool> AcceptsName { get; }
+
+        /// <summary>
+        /// Returns a function indicating whether to accept the tag. Returns 
True if accepted, 
+        /// false otherwise.
+        /// </summary>
+        Func<MetricsTag, bool> AcceptsTag { get; }
+
+        /// <summary>
+        /// Returns a function indicating whether to accept the record. 
Returns True if accepted, 
+        /// false otherwise.
+        /// </summary>
+        Func<IMetricsRecord, bool> AcceptsRecord { get; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsInfo.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsInfo.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsInfo.cs
new file mode 100644
index 0000000..2389dc3
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsInfo.cs
@@ -0,0 +1,38 @@
+// 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.
+
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Interface to provide immutable meta info. for metrics
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsInfo
+    {
+        /// <summary>
+        /// The name of the metric or tag.
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// Description of the metric or tag.
+        /// </summary>
+        string Description { get; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs
new file mode 100644
index 0000000..71cb138
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs
@@ -0,0 +1,63 @@
+// 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.
+
+using System.Collections.Generic;
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Immutable record of the metric. Represents snapshot of set of metrics
+    /// with a timestamp.
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsRecord
+    {
+        /// <summary>
+        /// Gets the timestamp of the metric in seconds.
+        /// Exact semantics is left to the default implementation. 
+        /// One option is to create the seconds-since-the-UNIX-epoch mentioned 
at this page.
+        /// 
https://blogs.msdn.microsoft.com/brada/2004/03/20/seconds-since-the-unix-epoch-in-c/
 
+        /// </summary>
+        long Timestamp { get; }
+
+        /// <summary>
+        /// Name of the record.
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// Description of the record.
+        /// </summary>
+        string Description { get; }
+
+        /// <summary>
+        /// Context name of the record.
+        /// </summary>
+        string Context { get; }
+
+        /// <summary>
+        /// Get the tags of the record.
+        /// </summary>
+        IEnumerable<MetricsTag> Tags { get; }
+
+        /// <summary>
+        /// Get the metrics of the record.
+        /// </summary>
+        IEnumerable<IImmutableMetric> Metrics { get; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs
new file mode 100644
index 0000000..36f6d0e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs
@@ -0,0 +1,104 @@
+// 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.
+
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Builder used to build a metrics record. Used by <see 
cref="IMetricsCollector"/> to 
+    /// add a record, typically in <see cref="IMetricsSource"/>. Note that 
this interface will 
+    /// be used to take Mutable metrics and convert them to immutable ones 
(<see cref="IImmutableMetric"/> 
+    /// so that they can be consumed possibly at some later time also.
+    /// </summary>
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsRecordBuilder
+    {
+        /// <summary>
+        /// Adds metrics tag (<see cref="MetricsTag"/>) to the record
+        /// </summary>
+        /// <param name="name">Name of the tag.</param>
+        /// <param name="value">Value of the tag.</param>
+        /// <returns>Self to add more metrics/tags.</returns>
+        IMetricsRecordBuilder AddTag(string name, string value);
+
+        /// <summary>
+        /// Adds metrics tag (<see cref="MetricsTag"/>) to the record
+        /// </summary>
+        /// <param name="info">Meta data for the tag.</param>
+        /// <param name="value">Value of the tag.</param>
+        /// <returns>Self to add more metrics/tags.</returns>
+        IMetricsRecordBuilder AddTag(IMetricsInfo info, string value);
+
+        /// <summary>
+        /// Adds an immutable metrics tag(<see cref="MetricsTag"/>)  object. 
Avoids making a copy.
+        /// </summary>
+        /// <param name="tag">A pre-made tags object.</param>
+        /// <returns>Self to add more metrics/tags.</returns>
+        IMetricsRecordBuilder Add(MetricsTag tag);
+
+        /// <summary>
+        /// Adds an immutable metric to the record. Saves making a new metric 
object.
+        /// </summary>
+        /// <param name="metric">A pre-made metric object.</param>
+        /// <returns>Self to add more metrics/tags.</returns>
+        IMetricsRecordBuilder Add(IImmutableMetric metric);
+
+        /// <summary>
+        /// Sets the special context tag of the record.
+        /// </summary>
+        /// <param name="value">Value of the context</param>
+        /// <returns>Self to add more metrics/tags.</returns>
+        IMetricsRecordBuilder SetContext(string value);
+
+        /// <summary>
+        /// Adds counter metric
+        /// </summary>
+        /// <param name="info">Meta data of the metric</param>
+        /// <param name="value">Value of the metric</param>
+        /// <returns></returns>
+        IMetricsRecordBuilder AddCounter(IMetricsInfo info, long value);
+
+        /// <summary>
+        /// Adds long gauge metric
+        /// </summary>
+        /// <param name="info">Meta data of the metric</param>
+        /// <param name="value">Value of the metric</param>
+        /// <returns></returns>
+        IMetricsRecordBuilder AddGauge(IMetricsInfo info, long value);
+
+        /// <summary>
+        /// Adds double gauge metric
+        /// </summary>
+        /// <param name="info">Meta data of the metric</param>
+        /// <param name="value">Value of the metric</param>
+        /// <returns></returns>
+        IMetricsRecordBuilder AddGauge(IMetricsInfo info, double value);
+
+        /// <summary>
+        /// Returns the parent <see cref="IMetricsCollector"/> object.
+        /// </summary>
+        /// <returns>Parent <see cref="IMetricsCollector"/> object</returns>
+        IMetricsCollector ParentCollector();
+
+        /// <summary>
+        /// Finalizes the record and enables adding multiple records in one 
line.
+        /// </summary>
+        /// <returns>Parent <see cref="IMetricsCollector"/> object</returns>
+        IMetricsCollector EndRecord();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/0b8da4cf/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsSource.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsSource.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsSource.cs
new file mode 100644
index 0000000..a705b7e
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsSource.cs
@@ -0,0 +1,42 @@
+// 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.
+
+using System;
+using Org.Apache.REEF.Common.Metrics.MutableMetricsLayer;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.Attributes;
+
+namespace Org.Apache.REEF.Common.Metrics.Api
+{
+    /// <summary>
+    /// Metrics source interface. The current snapshot of metrics is taken via 
this 
+    /// interface which are then later on pushed to sink. Derived from <see 
cref="IObservable{IMetricsRecordBuilder}"/>. 
+    /// <see cref="GetMetrics"/> will call OnNext() of different mutable 
metrics that implement 
+    /// <see cref="IObserver{IMetricsRecordBuilder}"/>
+    /// </summary>
+    [DefaultImplementation(typeof(DefaultMetricsSourceImpl))]
+    [Unstable("0.16", "Contract may change.")]
+    public interface IMetricsSource : IObservable<SnapshotRequest>
+    {
+        /// <summary>
+        /// Gets metrics from the source.
+        /// </summary>
+        /// <param name="collector">Collector that stores the resulting 
metrics snapshot as records.</param>
+        /// <param name="all">If true, gets metric values even if they are 
unchanged.</param>
+        void GetMetrics(IMetricsCollector collector, bool all);
+    }
+}
\ No newline at end of file

Reply via email to