Repository: reef
Updated Branches:
  refs/heads/master 92b21364c -> 09d56bcfb


[REEF-1675] Provide implementations of metrics utilities

This addressed the issue by
  * slightly modifying metrics interfaces.
  * providing the implementation of IMetricsCollector,
    IMetricsRecordBuilder, IMetricsRecord and IMetricsFilter.
  * providing tests for the implementations.

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

Pull request:
  This closes #1188


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

Branch: refs/heads/master
Commit: 09d56bcfbe2044c62ecb1509df48204f30c8171d
Parents: 92b2136
Author: dhruv <[email protected]>
Authored: Tue Nov 22 17:09:21 2016 -0800
Committer: Mariia Mykhailova <[email protected]>
Committed: Mon Dec 19 16:26:11 2016 -0800

----------------------------------------------------------------------
 .../Org.Apache.REEF.Common.Tests.csproj         |   1 +
 .../metrics/MetricTestUtils.cs                  |  41 +++-
 .../metrics/MetricsCollectorTests.cs            | 220 +++++++++++++++++++
 .../metrics/SnapshotRequestTest.cs              |  10 +
 .../Org.Apache.REEF.Common.csproj               |   6 +
 .../metrics/Api/IMetricsCollector.cs            |   9 +-
 .../metrics/Api/IMetricsFilter.cs               |   3 +
 .../metrics/Api/IMetricsRecord.cs               |   5 +-
 .../metrics/Api/IMetricsRecordBuilder.cs        |  15 ++
 .../MetricsSystem/DefaultMetricsFilter.cs       |  52 +++++
 .../MetricsSystem/IMetricsCollectorMutable.cs   |  36 +++
 .../MetricsSystem/MetricsCollectorMutable.cs    |  98 +++++++++
 .../metrics/MetricsSystem/MetricsRecord.cs      | 104 +++++++++
 .../MetricsSystem/MetricsRecordBuilder.cs       | 216 ++++++++++++++++++
 .../MetricsSystem/MetricsSystemConstants.cs     |  31 +++
 15 files changed, 840 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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 f49bbfb..a0ae90d 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
@@ -49,6 +49,7 @@ under the License.
     <Compile Include="Metrics\DefaultMetricSourceTests.cs" />
     <Compile Include="Metrics\ImmutableMetricImplTests.cs" />
     <Compile Include="Metrics\ImmutableMetricTest.cs" />
+    <Compile Include="Metrics\MetricsCollectorTests.cs" />
     <Compile Include="Metrics\MetricTestUtils.cs" />
     <Compile Include="Metrics\MutableMetricTest.cs" />
     <Compile Include="Metrics\SnapshotRequestTest.cs" />

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index 0a0738b..57f45c1 100644
--- a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricTestUtils.cs
@@ -16,6 +16,7 @@
 // under the License.
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using Org.Apache.REEF.Common.Metrics.Api;
 using Xunit;
@@ -104,6 +105,16 @@ namespace Org.Apache.REEF.Common.Tests.Metrics
                 throw new NotImplementedException();
             }
 
+            public IMetricsRecord GetRecord()
+            {
+                throw new NotImplementedException();
+            }
+
+            public bool IsEmpty()
+            {
+                return false;
+            }
+
             public void Validate(string name, long expected)
             {
                 if (!_longMetricVals.ContainsKey(name))
@@ -159,11 +170,8 @@ namespace Org.Apache.REEF.Common.Tests.Metrics
         /// </summary>
         internal sealed class MetricsCollectorTestImpl : IMetricsCollector
         {
-            public RecordBuilderForTests CurrentRecordBuilder
-            {
-                get;
-                private set;
-            }
+            public RecordBuilderForTests CurrentRecordBuilder { get; private 
set; }
+
             public IMetricsRecordBuilder CreateRecord(string name)
             {
                 CurrentRecordBuilder = new RecordBuilderForTests(name);
@@ -174,6 +182,29 @@ namespace Org.Apache.REEF.Common.Tests.Metrics
             {
                 throw new System.NotImplementedException();
             }
+
+            public void Clear()
+            {
+                throw new NotImplementedException();
+            }
+
+            public IEnumerable<IMetricsRecord> GetRecords()
+            {
+                throw new NotImplementedException();
+            }
+
+            public IEnumerator<IMetricsRecordBuilder> GetEnumerator()
+            {
+                return new List<IMetricsRecordBuilder>
+                {
+                    CurrentRecordBuilder
+                }.GetEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricsCollectorTests.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricsCollectorTests.cs 
b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricsCollectorTests.cs
new file mode 100644
index 0000000..78ebe38
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/MetricsCollectorTests.cs
@@ -0,0 +1,220 @@
+// 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 System.Linq;
+using Org.Apache.REEF.Common.Metrics.Api;
+using Org.Apache.REEF.Common.Metrics.MetricsSystem;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Util;
+using Xunit;
+
+namespace Org.Apache.REEF.Common.Tests.Metrics
+{
+    /// <summary>
+    /// Tests for <see cref="MetricsCollectorMutable"/>, <see 
cref="MetricsRecord"/> 
+    /// and <see cref="MetricsRecordBuilder"/>.
+    /// </summary>
+    public sealed class MetricsCollectorTests
+    {
+        /// <summary>
+        /// Tests <see cref="MetricsRecord"/>. Creates immutable metrics of 
+        /// various types and verifies that they are properly passed and 
stored 
+        /// in the record.
+        /// </summary>
+        [Fact]
+        public void TestMetricsRecord()
+        {
+            const string name = "recname";
+            const string desc = "rec desc";
+            const long timeStamp = 1000;
+            const string context = "context";
+            const string counterName = "counter";
+            const long counterValue = 2;
+            const string gaugeName = "gauge";
+            const double gaugeValue = 3.0;
+            const string tagName = "tagName";
+            const string tagValue = "tagValue";
+
+            IList<IImmutableMetric> metrics = new List<IImmutableMetric>();
+            metrics.Add(new ImmutableCounter(new MetricsInfoImpl(counterName, 
counterName), counterValue));
+            metrics.Add(new ImmutableDoubleGauge(new 
MetricsInfoImpl(gaugeName, gaugeName), gaugeValue));
+
+            IList<MetricsTag> tags = new List<MetricsTag>();
+            tags.Add(new MetricsTag(new MetricsInfoImpl(tagName, tagName), 
tagValue));
+
+            MetricsInfoImpl info = new MetricsInfoImpl(name, desc);
+            MetricsRecord record = new MetricsRecord(info, timeStamp, metrics, 
tags, context);
+
+            Assert.Equal(name, record.Name);
+            Assert.Equal(desc, record.Description);
+            Assert.Equal(context, record.Context);
+            Assert.Equal(timeStamp, record.Timestamp);
+            Assert.Equal(metrics, record.Metrics);
+            Assert.Equal(tags, record.Tags);
+        }
+
+        /// <summary>
+        /// Tests various functions of <see cref="MetricsRecordBuilder"/>. 
Adds various 
+        /// metrics using function calls in <see cref="MetricsRecordBuilder"/> 
and then verify 
+        /// that the created record has all the metric values pushed via 
relevant function calls.
+        /// </summary>
+        [Fact]
+        public void TestMetricsRecordBuilder()
+        {
+            const string name = "collName";
+            const string desc = "coll desc";
+            const string context = "context";
+            IList<string> counterName = new List<string>() { "counter1", 
"counter2" };
+            IList<long> counterValue = new List<long>() { 2, 6 };
+            const string doubleGaugeName = "doublegauge";
+            const double doubleGaugeValue = 3.0;
+            const string longGaugeName = "longgauge";
+            const long longGaugeValue = 4;
+            IList<string> tagName = new List<string>() { "tagName1", 
"tagName2", "tagName3" };
+            IList<string> tagValue = new List<string>() { "tagValue1", 
"tagValue2", "tagValue3" };
+            IList<string> tagDesc = new List<string>() { "tagName1", 
"tagDesc2", "tagDesc3" };
+
+            var collector = new MetricTestUtils.MetricsCollectorTestImpl();
+            MetricsRecordBuilder rb = new MetricsRecordBuilder(collector, new 
MetricsInfoImpl(name, desc));
+
+            // Push different metrics via relevant function calls.
+            rb.AddCounter(new MetricsInfoImpl(counterName[0], counterName[0]), 
counterValue[0])
+                .Add(new ImmutableCounter(new MetricsInfoImpl(counterName[1], 
counterName[1]), counterValue[1]))
+                .AddGauge(new MetricsInfoImpl(longGaugeName, longGaugeName), 
longGaugeValue)
+                .AddGauge(new MetricsInfoImpl(doubleGaugeName, 
doubleGaugeName), doubleGaugeValue)
+                .AddTag(tagName[0], tagValue[0])
+                .AddTag(new MetricsInfoImpl(tagName[1], tagDesc[1]), 
tagValue[1])
+                .Add(new MetricsTag(new MetricsInfoImpl(tagName[2], 
tagDesc[2]), tagValue[2]))
+                .SetContext(context)
+                .EndRecord();
+
+            TimeSpan t = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1));
+            long expectedTimeStamp = (long)t.TotalSeconds;
+
+            // Get the created record.
+            var record = rb.GetRecord();
+            Assert.Equal(name, record.Name);
+            Assert.Equal(desc, record.Description);
+            Assert.True(record.Timestamp >= expectedTimeStamp);
+            Assert.Equal(context, record.Context);
+
+            int counter = 0;
+            Assert.Equal(tagName.Count + 1, record.Tags.Count());
+
+            // Verify that relevant tags are present.
+            foreach (var tag in record.Tags)
+            {
+                if (counter < tagName.Count)
+                {
+                    Assert.Equal(tagName[counter], tag.Name);
+                    Assert.Equal(tagValue[counter], tag.Value);
+                    Assert.Equal(tagDesc[counter], tag.Description);
+                }
+                else
+                {
+                    Assert.Equal(MetricsSystemConstants.Context, tag.Name);
+                    Assert.Equal(MetricsSystemConstants.Context, 
tag.Description);
+                    Assert.Equal(context, tag.Value);
+                }
+                counter++;
+            }
+
+            counter = 0;
+            Assert.Equal(counterName.Count + 2, record.Metrics.Count());
+
+            // Verify that relevant counters and gauges are there.
+            foreach (var metric in record.Metrics)
+            {
+                if (counter < 2)
+                {
+                    Assert.Equal(MetricType.Counter, metric.TypeOfMetric);
+                    Assert.Equal(counterName[counter], metric.Info.Name);
+                    Assert.Equal(counterValue[counter], metric.LongValue);
+                }
+                else
+                {
+                    Assert.Equal(MetricType.Gauge, metric.TypeOfMetric);
+
+                    if (counter == 2)
+                    {
+                        Assert.Equal(longGaugeName, metric.Info.Name);
+                        Assert.Equal(longGaugeValue, metric.LongValue);
+                    }
+                    else
+                    {
+                        Assert.Equal(doubleGaugeName, metric.Info.Name);
+                        Assert.Equal(doubleGaugeValue, metric.NumericValue);
+                    }
+                }
+                counter++;
+            }
+        }
+
+        /// <summary>
+        /// Tests various fucntions of <see cref="MetricsCollectorMutable"/>. 
Creates two records 
+        /// using the collector and verify that they are correctly created and 
returned.
+        /// </summary>
+        [Fact]
+        public void TestMetricsCollector()
+        {
+            IList<string> recNames = new List<string>() { "recName1", 
"recName2" };
+            const string counterName = "counter";
+            const long counterValue = 2;
+            const string doubleGaugeName = "gauge";
+            const double doubleGaugeValue = 3.0;
+
+            var collector =
+                TangFactory.GetTang()
+                    .NewInjector(
+                        TangFactory.GetTang()
+                            .NewConfigurationBuilder()
+                            
.BindImplementation(GenericType<IMetricsCollectorMutable>.Class,
+                                
GenericType<MetricsCollectorMutable>.Class).Build())
+                    .GetInstance<IMetricsCollectorMutable>();
+
+            collector.CreateRecord(recNames[0])
+                .AddCounter(new MetricsInfoImpl(counterName, counterName), 
counterValue)
+                .EndRecord()
+                .CreateRecord(new MetricsInfoImpl(recNames[1], recNames[1]))
+                .AddGauge(new MetricsInfoImpl(doubleGaugeName, 
doubleGaugeName), doubleGaugeValue)
+                .EndRecord();
+
+            var records = collector.GetRecords();
+            Assert.Equal(recNames.Count, records.Count());
+
+            int counter = 0;
+            foreach (var record in records)
+            {
+                Assert.Equal(recNames[counter], record.Name);
+                if (counter == 0)
+                {
+                    Assert.Equal(counterValue, 
record.Metrics.First().LongValue);
+                }
+                else
+                {
+                    Assert.Equal(doubleGaugeValue, 
record.Metrics.First().NumericValue);
+                }
+                counter++;
+            }
+
+            collector.Clear();
+            Assert.Equal(0, collector.GetRecords().Count());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index 05b1aa1..33de9cf 100644
--- a/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs
+++ b/lang/cs/Org.Apache.REEF.Common.Tests/metrics/SnapshotRequestTest.cs
@@ -95,6 +95,16 @@ namespace Org.Apache.REEF.Common.Tests.Metrics
             {
                 throw new System.NotImplementedException();
             }
+
+            public IMetricsRecord GetRecord()
+            {
+                throw new System.NotImplementedException();
+            }
+
+            public bool IsEmpty()
+            {
+                throw new System.NotImplementedException();
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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 936bc01..bd896b5 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
@@ -137,9 +137,15 @@ under the License.
     <Compile Include="Metrics\Api\MetricsTag.cs" />
     <Compile Include="Metrics\Api\MetricType.cs" />
     <Compile Include="Metrics\Api\SnapshotRequest.cs" />
+    <Compile Include="Metrics\MetricsSystem\DefaultMetricsFilter.cs" />
+    <Compile Include="Metrics\MetricsSystem\IMetricsCollectorMutable.cs" />
     <Compile Include="Metrics\MetricsSystem\ImmutableCounter.cs" />
     <Compile Include="Metrics\MetricsSystem\ImmutableDoubleGauge.cs" />
     <Compile Include="Metrics\MetricsSystem\ImmutableLongGauge.cs" />
+    <Compile Include="Metrics\MetricsSystem\MetricsCollectorMutable.cs" />
+    <Compile Include="Metrics\MetricsSystem\MetricsRecord.cs" />
+    <Compile Include="Metrics\MetricsSystem\MetricsRecordBuilder.cs" />
+    <Compile Include="Metrics\MetricsSystem\MetricsSystemConstants.cs" />
     <Compile 
Include="Metrics\MutableMetricsLayer\DefaultMetricsFactoryImpl.cs" />
     <Compile 
Include="Metrics\MutableMetricsLayer\DefaultMetricsSourceConfiguration.cs" />
     <Compile Include="Metrics\MutableMetricsLayer\DefaultMetricsSourceImpl.cs" 
/>

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index c9b51c5..811a65d 100644
--- a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsCollector.cs
@@ -15,6 +15,7 @@
 // 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
@@ -24,7 +25,7 @@ namespace Org.Apache.REEF.Common.Metrics.Api
     /// the <see cref="IMetricsSource"/> to add and fill in the records.
     /// </summary>
     [Unstable("0.16", "Contract may change.")]
-    public interface IMetricsCollector
+    public interface IMetricsCollector : IEnumerable<IMetricsRecordBuilder>
     {
         /// <summary>
         /// Creates a metric record by name. The exact semantics of what to do 
if another 
@@ -43,5 +44,11 @@ namespace Org.Apache.REEF.Common.Metrics.Api
         /// <param name="info">Meta-data info of the record.</param>
         /// <returns>Record builder for the record.</returns>
         IMetricsRecordBuilder CreateRecord(IMetricsInfo info);
+
+        /// <summary>
+        /// Creates record from underlying collection of <see 
cref="IMetricsRecordBuilder"/>
+        /// </summary>
+        /// <returns>Enumerator over records.</returns>
+        IEnumerable<IMetricsRecord> GetRecords();
     }
 }

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index 3ef811b..5e0a3bd 100644
--- a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsFilter.cs
@@ -16,6 +16,8 @@
 // under the License.
 
 using System;
+using Org.Apache.REEF.Common.Metrics.MetricsSystem;
+using Org.Apache.REEF.Tang.Annotations;
 using Org.Apache.REEF.Utilities.Attributes;
 
 namespace Org.Apache.REEF.Common.Metrics.Api
@@ -25,6 +27,7 @@ namespace Org.Apache.REEF.Common.Metrics.Api
     /// source and sink names, record, individual tag, individual metric.
     /// </summary>
     [Unstable("0.16", "Contract may change.")]
+    [DefaultImplementation(typeof(DefaultMetricsFilter))]
     public interface IMetricsFilter
     {
         /// <summary>

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index 71cb138..d8246e0 100644
--- a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecord.cs
@@ -16,6 +16,8 @@
 // under the License.
 
 using System.Collections.Generic;
+using Org.Apache.REEF.Common.Metrics.MetricsSystem;
+using Org.Apache.REEF.Tang.Annotations;
 using Org.Apache.REEF.Utilities.Attributes;
 
 namespace Org.Apache.REEF.Common.Metrics.Api
@@ -25,6 +27,7 @@ namespace Org.Apache.REEF.Common.Metrics.Api
     /// with a timestamp.
     /// </summary>
     [Unstable("0.16", "Contract may change.")]
+    [DefaultImplementation(typeof(MetricsRecord))]
     public interface IMetricsRecord
     {
         /// <summary>
@@ -60,4 +63,4 @@ namespace Org.Apache.REEF.Common.Metrics.Api
         /// </summary>
         IEnumerable<IImmutableMetric> Metrics { get; }
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/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
index 36f6d0e..1a8422b 100644
--- a/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/Api/IMetricsRecordBuilder.cs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+using Org.Apache.REEF.Common.Metrics.MetricsSystem;
+using Org.Apache.REEF.Tang.Annotations;
 using Org.Apache.REEF.Utilities.Attributes;
 
 namespace Org.Apache.REEF.Common.Metrics.Api
@@ -26,6 +28,7 @@ namespace Org.Apache.REEF.Common.Metrics.Api
     /// so that they can be consumed possibly at some later time also.
     /// </summary>
     [Unstable("0.16", "Contract may change.")]
+    [DefaultImplementation(typeof(MetricsRecordBuilder))]
     public interface IMetricsRecordBuilder
     {
         /// <summary>
@@ -100,5 +103,17 @@ namespace Org.Apache.REEF.Common.Metrics.Api
         /// </summary>
         /// <returns>Parent <see cref="IMetricsCollector"/> object</returns>
         IMetricsCollector EndRecord();
+
+        /// <summary>
+        /// Gives the underlying record.
+        /// </summary>
+        /// <returns>Underlying record.</returns>
+        IMetricsRecord GetRecord();
+
+        /// <summary>
+        /// Checks whether some record or tag has been added.
+        /// </summary>
+        /// <returns>True if none is added, false otherwise.</returns>
+        bool IsEmpty();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/DefaultMetricsFilter.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/DefaultMetricsFilter.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/DefaultMetricsFilter.cs
new file mode 100644
index 0000000..12b8d73
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/DefaultMetricsFilter.cs
@@ -0,0 +1,52 @@
+// 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.Api;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Default metrics filter. Accepts everything.
+    /// </summary>
+    internal sealed class DefaultMetricsFilter : IMetricsFilter
+    {
+        [Inject]
+        DefaultMetricsFilter()
+        {
+            AcceptsName = s => true;
+            AcceptsTag = s => true;
+            AcceptsRecord = s => true;
+        }
+
+        /// <summary>
+        /// Accepts any name.
+        /// </summary>
+        public Func<string, bool> AcceptsName { get; private set; }
+
+        /// <summary>
+        /// Accepts any tag.
+        /// </summary>
+        public Func<MetricsTag, bool> AcceptsTag { get; private set; }
+
+        /// <summary>
+        /// Accepts any record.
+        /// </summary>
+        public Func<IMetricsRecord, bool> AcceptsRecord { get; private set; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/IMetricsCollectorMutable.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/IMetricsCollectorMutable.cs
 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/IMetricsCollectorMutable.cs
new file mode 100644
index 0000000..98db1c9
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/IMetricsCollectorMutable.cs
@@ -0,0 +1,36 @@
+// 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.Tang.Annotations;
+
+namespace Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Extension of <see cref="IMetricsCollector"/>. Used to clear the 
collector 
+    /// for future use. Makes the class mutable. However, the Clear() function 
call 
+    /// is internal and not visible to external users.
+    /// </summary>
+    [DefaultImplementation(typeof(MetricsCollectorMutable))]
+    internal interface IMetricsCollectorMutable : IMetricsCollector
+    {
+        /// <summary>
+        /// Clears up the metrics collector. Removes all record builders and 
records.
+        /// </summary>
+        void Clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsCollectorMutable.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsCollectorMutable.cs
 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsCollectorMutable.cs
new file mode 100644
index 0000000..72ead9b
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsCollectorMutable.cs
@@ -0,0 +1,98 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using Org.Apache.REEF.Common.Metrics.Api;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Default implementation of the <see cref="IMetricsCollectorMutable"/> 
class. 
+    /// It is used to create and maintain collection of records from sources 
in the 
+    /// Metrics System.
+    /// </summary>
+    internal sealed class MetricsCollectorMutable : IMetricsCollectorMutable
+    {
+        [Inject]
+        private MetricsCollectorMutable()
+        {
+        }
+
+        private readonly IList<IMetricsRecordBuilder> _recordBuilder = new 
List<IMetricsRecordBuilder>();
+
+        /// <summary>
+        /// Creates a new Record builder by name.
+        /// </summary>
+        /// <param name="name">Name of the record.</param>
+        /// <returns>Newly created Record builder.</returns>
+        public IMetricsRecordBuilder CreateRecord(string name)
+        {
+            var value = new MetricsRecordBuilder(this, new 
MetricsInfoImpl(name, name));
+            _recordBuilder.Add(value);
+            return value;
+        }
+
+        /// <summary>
+        /// Creates a metric record by meta-data info. Creates the new record 
even 
+        /// if another one with same meta-data already exists.
+        /// </summary>
+        /// <param name="info">Meta-data info of the record.</param>
+        /// <returns>Record builder for the record.</returns>
+        public IMetricsRecordBuilder CreateRecord(IMetricsInfo info)
+        {
+            var value = new MetricsRecordBuilder(this, info);
+            _recordBuilder.Add(value);
+            return value;
+        }
+
+        /// <summary>
+        /// Creates record from underlying collection of <see 
cref="IMetricsRecordBuilder"/>
+        /// </summary>
+        /// <returns>Enumerator over records.</returns>
+        public IEnumerable<IMetricsRecord> GetRecords()
+        {
+            return
+                _recordBuilder.Where(builder => !builder.IsEmpty())
+                    .Select(builder => builder.GetRecord()).ToArray();
+        }
+
+        /// <summary>
+        /// Returns an enumerator of <see cref="IMetricsRecordBuilder"/>
+        /// </summary>
+        /// <returns>Enumerator of <see 
cref="IMetricsRecordBuilder"/></returns>
+        public IEnumerator<IMetricsRecordBuilder> GetEnumerator()
+        {
+            return _recordBuilder.GetEnumerator();
+        }
+
+        /// <summary>
+        /// Clears up the metrics collector. Removes all record builders and 
records.
+        /// </summary>
+        public void Clear()
+        {
+            _recordBuilder.Clear();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecord.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecord.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecord.cs
new file mode 100644
index 0000000..d315fa8
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecord.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 System;
+using System.Collections.Generic;
+using Org.Apache.REEF.Common.Metrics.Api;
+
+namespace Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Default implementation of <see cref="IMetricsRecord"/>. This class 
+    /// maintains a collection of immutable metrics and tags.
+    /// </summary>
+    internal sealed class MetricsRecord : IMetricsRecord
+    {
+        /// <summary>
+        /// Constructor for the metric record.
+        /// </summary>
+        /// <param name="info">Meta-data info for the record.</param>
+        /// <param name="timeStamp">Unix time stamp for the record measured as 
total 
+        /// seconds relative to Jan 01 1970. (UTC)</param>
+        /// <param name="metrics">Collection of metrics in the record.</param>
+        /// <param name="tags">Collection of tags in the record.</param>
+        /// <param name="context">Context of the record.</param>
+        public MetricsRecord(IMetricsInfo info,
+            long timeStamp,
+            IEnumerable<IImmutableMetric> metrics,
+            IEnumerable<MetricsTag> tags,
+            string context)
+        {
+            if (info == null)
+            {
+                throw new MetricsException("Record info cannot be null", new 
ArgumentNullException("info"));
+            }
+
+            if (timeStamp < 0)
+            {
+                throw new MetricsException(string.Empty,
+                    new ArgumentException("Timestamp cannot be less than 
zero", "timeStamp"));
+            }
+
+            if (metrics == null)
+            {
+                throw new MetricsException("Metrics list is null", new 
ArgumentNullException("metrics"));
+            }
+
+            if (tags == null)
+            {
+                throw new MetricsException("Tag list is null", new 
ArgumentNullException("tags"));
+            }
+
+            Name = info.Name;
+            Description = info.Description;
+            Timestamp = timeStamp;
+            Metrics = metrics;
+            Tags = tags;
+            Context = context;
+        }
+
+        /// <summary>
+        /// Unix time stamp (in seconds) of the record.
+        /// </summary>
+        public long Timestamp { get; private set; }
+
+        /// <summary>
+        /// Name of the record.
+        /// </summary>
+        public string Name { get; private set; }
+
+        /// <summary>
+        /// Description of the record.
+        /// </summary>
+        public string Description { get; private set; }
+
+        /// <summary>
+        /// Context of the record.
+        /// </summary>
+        public string Context { get; private set; }
+
+        /// <summary>
+        /// Tags in the record.
+        /// </summary>
+        public IEnumerable<MetricsTag> Tags { get; private set; }
+
+        /// <summary>
+        /// Metrics in the record.
+        /// </summary>
+        public IEnumerable<IImmutableMetric> Metrics { get; private set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecordBuilder.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecordBuilder.cs 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecordBuilder.cs
new file mode 100644
index 0000000..0e4f7f8
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsRecordBuilder.cs
@@ -0,0 +1,216 @@
+// 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;
+
+namespace Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Default implementation of <see cref="IMetricsRecordBuilder"/>.
+    /// This class is used to collect records from <see 
cref="IMetricsSource"/> 
+    /// and convert them to <see cref="IMetricsRecord"/>. Mutable metrics from 
+    /// sources are observed and stores as immutable instances.
+    /// </summary>
+    internal sealed class MetricsRecordBuilder : IMetricsRecordBuilder
+    {
+        private readonly IList<IImmutableMetric> _metrics = new 
List<IImmutableMetric>();
+        private readonly IList<MetricsTag> _tags = new List<MetricsTag>();
+        private readonly IMetricsCollector _parentCollector;
+        private readonly IMetricsInfo _info;
+        private string _contextValue;
+        private bool _recordBuilderFinalized;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="collector">The parent collector that creates the 
record builder.</param>
+        /// <param name="info">Meta-data info of the record-builder.</param>
+        public MetricsRecordBuilder(IMetricsCollector collector, IMetricsInfo 
info)
+        {
+            _parentCollector = collector;
+            _info = info;
+        }
+
+        /// <summary>
+        /// Adds a tag to the record builder.
+        /// </summary>
+        /// <param name="name">Name of the tag.</param>
+        /// <param name="value">Value of the tag.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder AddTag(string name, string value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more tags can be added.");
+            }
+            _tags.Add(new MetricsTag(new MetricsInfoImpl(name, name), value));
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a tag to the record builder.
+        /// </summary>
+        /// <param name="info">Meta-data info of the tag.</param>
+        /// <param name="value">Value of the tag.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder AddTag(IMetricsInfo info, string value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more tags can be added.");
+            }
+            _tags.Add(new MetricsTag(info, value));
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a tag to the record builder. This functions removes 
duplication in 
+        /// case tag has already been created by the caller.
+        /// </summary>
+        /// <param name="tag">Tag to add.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder Add(MetricsTag tag)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more tags can be added.");
+            }
+            _tags.Add(tag);
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a metric to the record builder. This functions removes 
duplication in 
+        /// case metric has already been created by the caller.
+        /// </summary>
+        /// <param name="metric">Metric to add.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder Add(IImmutableMetric metric)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more metrics can be added.");
+            }
+            _metrics.Add(metric);
+            return this;
+        }
+
+        /// <summary>
+        /// Sets a context for the record builder. Creates the corresponding 
tag.
+        /// </summary>
+        /// <param name="value">Value of the context.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder SetContext(string value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more metrics can be added.");
+            }
+            _contextValue = value;
+            return AddTag(MetricsSystemConstants.Context, value);
+        }
+
+        /// <summary>
+        /// Adds a counter to the record builder.
+        /// </summary>
+        /// <param name="info">Meta data info of the counter.</param>
+        /// <param name="value">Value of the counter.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder AddCounter(IMetricsInfo info, long value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more metrics can be added.");
+            }
+            _metrics.Add(new ImmutableCounter(info, value));
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a long gauge to the record builder.
+        /// </summary>
+        /// <param name="info">Meta data info of the gauge.</param>
+        /// <param name="value">Value of the gauge.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder AddGauge(IMetricsInfo info, long value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more metrics can be added.");
+            }
+            _metrics.Add(new ImmutableLongGauge(info, value));
+            return this;
+        }
+
+        /// <summary>
+        /// Adds a double gauge to the record builder.
+        /// </summary>
+        /// <param name="info">Meta data info of the gauge.</param>
+        /// <param name="value">Value of the gauge.</param>
+        /// <returns>Self reference.</returns>
+        public IMetricsRecordBuilder AddGauge(IMetricsInfo info, double value)
+        {
+            if (_recordBuilderFinalized)
+            {
+                throw new MetricsException("Record builder is already 
finalized. No more metrics can be added.");
+            }
+            _metrics.Add(new ImmutableDoubleGauge(info, value));
+            return this;
+        }
+
+        /// <summary>
+        /// Returns the parent collector.
+        /// </summary>
+        public IMetricsCollector ParentCollector()
+        {
+            return _parentCollector;
+        }
+
+        /// <summary>
+        /// Ends the record building and returns the parent collector.
+        /// </summary>
+        /// <returns>The parent collector.</returns>
+        public IMetricsCollector EndRecord()
+        {
+            _recordBuilderFinalized = true;
+            return _parentCollector;
+        }
+
+        /// <summary>
+        /// Creates the record from record builder.
+        /// </summary>
+        /// <returns>The newly created record. Return null if no metric or tag 
exists.</returns>
+        public IMetricsRecord GetRecord()
+        {
+            TimeSpan t = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1));
+            long timeStamp = (long)t.TotalSeconds;
+
+            return !IsEmpty() ? new MetricsRecord(_info, timeStamp, _metrics, 
_tags, _contextValue) : null;
+        }
+
+        /// <summary>
+        /// Determines if record has any entry.
+        /// </summary>
+        /// <returns>True if it is empty.</returns>
+        public bool IsEmpty()
+        {
+            return _metrics.Count == 0 && _tags.Count == 0;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/09d56bcf/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsSystemConstants.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsSystemConstants.cs
 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsSystemConstants.cs
new file mode 100644
index 0000000..251f615
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/metrics/MetricsSystem/MetricsSystemConstants.cs
@@ -0,0 +1,31 @@
+// 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 Org.Apache.REEF.Common.Metrics.MetricsSystem
+{
+    /// <summary>
+    /// Class declaring constants for the metrics system.
+    /// </summary>
+    public static class MetricsSystemConstants
+    {
+        /// <summary>
+        /// Specifies name and description for the context tag. As a example 
context can 
+        /// be "Evaluator metrics", "ML", etc.
+        /// </summary>
+        public static readonly string Context = "Metrics Context";
+    }
+}

Reply via email to