You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@reef.apache.org by we...@apache.org on 2016/08/30 16:39:43 UTC
[3/3] reef git commit: [REEF-1481] Develop basic metrics APIs for
REEF.Net
[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 <dh...@apache.org>
Authored: Fri Jul 8 23:15:38 2016 -0700
Committer: Markus Weimer <we...@apache.org>
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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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 @@
+\ufeff// 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