Repository: reef Updated Branches: refs/heads/master 26f98be43 -> 076b98c9a
[REEF-1738] Create Evaluator Metrics interface and implementations * Add Counters interface and impl * Add EvalatorMetrics interface and impl * Add test cases. JIRA: [REEF-1738](https://issues.apache.org/jira/browse/REEF-1738) Pull Request: This closes #1252 Project: http://git-wip-us.apache.org/repos/asf/reef/repo Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/076b98c9 Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/076b98c9 Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/076b98c9 Branch: refs/heads/master Commit: 076b98c9a6112a1d26699d00c4fd4222ec708f3b Parents: 26f98be Author: Julia Wang <[email protected]> Authored: Mon Feb 6 16:13:01 2017 -0800 Committer: Markus Weimer <[email protected]> Committed: Wed Feb 15 15:01:47 2017 -0800 ---------------------------------------------------------------------- .../Org.Apache.REEF.Common.Tests.csproj | 1 + .../Telemetry/CounterTests.cs | 92 ++++++++++++ .../Org.Apache.REEF.Common.csproj | 6 + .../Org.Apache.REEF.Common/Telemetry/Counter.cs | 133 +++++++++++++++++ .../Telemetry/Counters.cs | 142 +++++++++++++++++++ .../Telemetry/EvaluatorMetrics.cs | 65 +++++++++ .../Telemetry/ICounter.cs | 46 ++++++ .../Telemetry/ICounters.cs | 65 +++++++++ .../Telemetry/IEvaluatorMetrics.cs | 39 +++++ 9 files changed, 589 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/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 a0ae90d..30339dc 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 @@ -54,6 +54,7 @@ under the License. <Compile Include="Metrics\MutableMetricTest.cs" /> <Compile Include="Metrics\SnapshotRequestTest.cs" /> <Compile Include="Metrics\TestMetricsTag.cs" /> + <Compile Include="Telemetry\CounterTests.cs" /> <Compile Include="TestHttpSerialization.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common.Tests/Telemetry/CounterTests.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common.Tests/Telemetry/CounterTests.cs b/lang/cs/Org.Apache.REEF.Common.Tests/Telemetry/CounterTests.cs new file mode 100644 index 0000000..3973ad2 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common.Tests/Telemetry/CounterTests.cs @@ -0,0 +1,92 @@ +// 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.Telemetry; +using Org.Apache.REEF.Tang.Implementations.Tang; +using Xunit; + +namespace Org.Apache.REEF.Common.Tests.Telemetry +{ + public class CounterTests + { + /// <summary> + /// Test ICounters and IEvaluatorMetrics API. + /// </summary> + [Fact] + public void TestEvaluatorMetrics() + { + var metrics = TangFactory.GetTang().NewInjector().GetInstance<IEvaluatorMetrics>(); + var counters = metrics.GetMetricsCounters(); + counters.TryRegisterCounter("counter1", "counter1 description"); + counters.TryRegisterCounter("counter2", "counter2 description"); + ValidateCounter(counters, "counter1", 0); + ValidateCounter(counters, "counter2", 0); + + counters.Increment("counter1", 3); + counters.Increment("counter1", 1); + counters.Increment("counter2", 2); + counters.Increment("counter2", 3); + ValidateCounter(counters, "counter1", 4); + ValidateCounter(counters, "counter2", 5); + + var counterStr = metrics.Serialize(); + + var metrics2 = new EvaluatorMetrics(counterStr); + var counters2 = metrics2.GetMetricsCounters(); + ValidateCounter(counters2, "counter1", 4); + ValidateCounter(counters2, "counter2", 5); + } + + /// <summary> + /// Test TryRegisterCounter with a duplicated counter name + /// </summary> + [Fact] + public void TestDuplicatedCounters() + { + var counters = CreateCounters(); + counters.TryRegisterCounter("counter1", "counter1 description"); + Assert.False(counters.TryRegisterCounter("counter1", "counter1 description")); + } + + /// <summary> + /// Test Increment for a non-registered counter. + /// </summary> + [Fact] + public void TestNoExistCounter() + { + var counters = CreateCounters(); + Action increment = () => counters.Increment("counter1", 2); + Assert.Throws<ApplicationException>(increment); + } + + private static void ValidateCounter(ICounters counters, string name, int expectedValue) + { + ICounter c1; + counters.TryGetValue(name, out c1); + Assert.Equal(expectedValue, c1.Value); + } + + private static ICounters CreateCounters() + { + var m = TangFactory.GetTang().NewInjector().GetInstance<IEvaluatorMetrics>(); + var c = m.GetMetricsCounters(); + return c; + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/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 bd896b5..dc868af 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 @@ -246,6 +246,12 @@ under the License. <Compile Include="Tasks\TaskConfiguration.cs" /> <Compile Include="Tasks\TaskConfigurationOptions.cs" /> <Compile Include="Tasks\TaskMessage.cs" /> + <Compile Include="Telemetry\Counter.cs" /> + <Compile Include="Telemetry\Counters.cs" /> + <Compile Include="Telemetry\EvaluatorMetrics.cs" /> + <Compile Include="Telemetry\ICounter.cs" /> + <Compile Include="Telemetry\ICounters.cs" /> + <Compile Include="Telemetry\IEvaluatorMetrics.cs" /> </ItemGroup> <ItemGroup> <None Include="Avro\README.md" /> http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/Counter.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/Counter.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/Counter.cs new file mode 100644 index 0000000..de46bae --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/Counter.cs @@ -0,0 +1,133 @@ +// 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.Runtime.Serialization; +using Newtonsoft.Json; +using Org.Apache.REEF.Utilities.Attributes; + +namespace Org.Apache.REEF.Common.Telemetry +{ + /// <summary> + /// Counter implementation + /// The properties that need to be serialized will be revisited later. We should only serialize minimum data to reduce the network load + /// For example, the name can be mapped to a unique number (byte) and description should not be serialized. + /// </summary> + [Unstable("0.16", "This is a simple counter for evaluator metrics.")] + [DataContract] + internal sealed class Counter : ICounter + { + /// <summary> + /// Name of the counter. + /// </summary> + private readonly string _name; + + /// <summary> + /// Description of the counter. + /// </summary> + private readonly string _description; + + /// <summary> + /// Time that the counter is updated. + /// </summary> + private long _timeStamp; + + /// <summary> + /// Value of the counter. + /// </summary> + private int _value; + + /// <summary> + /// Constructor to create a new counter. + /// </summary> + /// <param name="name"></param> + /// <param name="description"></param> + internal Counter(string name, string description) + { + _name = name; + _description = description; + _timeStamp = DateTime.Now.Ticks; + _value = 0; + } + + /// <summary> + /// Constructor to create a counter from a serialized counter string + /// </summary> + [JsonConstructor] + internal Counter(string name, string description, long timeStamp, int value) + { + _name = name; + _description = description; + _timeStamp = timeStamp; + _value = value; + } + + /// <summary> + /// Description of the counter. + /// </summary> + [DataMember] + public string Description + { + get + { + return _description; + } + } + + /// <summary> + /// Name of the counter. + /// </summary> + [DataMember] + public string Name + { + get + { + return _name; + } + } + + /// <summary> + /// Time that the counter is updated in the form of ticks. + /// </summary> + [DataMember] + public long Timestamp + { + get + { + return _timeStamp; + } + } + + /// <summary> + /// Value of the counter. + /// </summary> + [DataMember] + public int Value + { + get + { + return _value; + } + } + + /// <summary> + /// Increase the counter value and update the time stamp. + /// </summary> + /// <param name="number"></param> + public void Increment(int number) + { + _value += number; + _timeStamp = DateTime.Now.Ticks; + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/Counters.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/Counters.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/Counters.cs new file mode 100644 index 0000000..d681ec6 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/Counters.cs @@ -0,0 +1,142 @@ +// 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 Newtonsoft.Json; +using Org.Apache.REEF.Tang.Annotations; +using Org.Apache.REEF.Utilities.Attributes; +using Org.Apache.REEF.Utilities.Logging; + +namespace Org.Apache.REEF.Common.Telemetry +{ + [Unstable("0.16", "This is to build a collection of counters for evaluator metrics.")] + internal sealed class Counters : ICounters + { + private static readonly Logger Logger = Logger.GetLogger(typeof(Counters)); + + /// <summary> + /// It contains name and count pairs + /// </summary> + private readonly IDictionary<string, ICounter> _counters = new Dictionary<string, ICounter>(); + + /// <summary> + /// The lock for counters + /// </summary> + private readonly object _counterLock = new object(); + + [Inject] + private Counters() + { + } + + /// <summary> + /// Deserialize a counters serialized string into a Counters object + /// </summary> + /// <param name="serializedCountersString"></param> + internal Counters(string serializedCountersString) + { + var c = JsonConvert.DeserializeObject<IEnumerable<Counter>>(serializedCountersString); + foreach (var ct in c) + { + _counters.Add(ct.Name, ct); + } + } + + public IEnumerable<ICounter> GetCounters() + { + return _counters.Values; + } + + /// <summary> + /// Register a new counter with a specified name. + /// If name does not exist, the counter will be added and true will be returned + /// Otherwise the counter will be not added and false will be returned. + /// </summary> + /// <param name="name">Counter name</param> + /// <param name="description">Counter description</param> + /// <returns>Returns a boolean to indicate if the counter is added.</returns> + public bool TryRegisterCounter(string name, string description) + { + lock (_counterLock) + { + if (_counters.ContainsKey(name)) + { + Logger.Log(Level.Warning, "The counter [{0}] already exists.", name); + return false; + } + _counters.Add(name, new Counter(name, description)); + } + return true; + } + + /// <summary> + /// Get counter for a given name + /// return false if the counter doesn't exist + /// </summary> + /// <param name="name">Name of the counter</param> + /// <param name="value">Value of the counter returned</param> + /// <returns>Returns a boolean to indicate if the value is found.</returns> + public bool TryGetValue(string name, out ICounter value) + { + lock (_counterLock) + { + return _counters.TryGetValue(name, out value); + } + } + + /// <summary> + /// Increase the counter with the given number + /// </summary> + /// <param name="name">Name of the counter</param> + /// <param name="number">number to increase</param> + public void Increment(string name, int number) + { + ICounter counter; + if (TryGetValue(name, out counter)) + { + lock (_counterLock) + { + counter.Increment(number); + } + } + else + { + Logger.Log(Level.Error, "The counter [{0}] has not registered.", name); + throw new ApplicationException("Counter has not registered:" + name); + } + } + + /// <summary> + /// return serialized string of counter data + /// TODO: [REEF-] use an unique number for the counter name mapping to reduce the data transfer over the wire + /// TODO: [REEF-] use Avro schema if that can make the serialized string more compact + /// </summary> + /// <returns>Returns serialized string of the counters.</returns> + public string Serialize() + { + lock (_counterLock) + { + if (_counters.Count > 0) + { + return JsonConvert.SerializeObject(_counters.Values); + } + return null; + } + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/EvaluatorMetrics.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/EvaluatorMetrics.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/EvaluatorMetrics.cs new file mode 100644 index 0000000..38f789c --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/EvaluatorMetrics.cs @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Org.Apache.REEF.Tang.Annotations; +using Org.Apache.REEF.Utilities.Attributes; + +namespace Org.Apache.REEF.Common.Telemetry +{ + [Unstable("0.16", "This is to build a simple metrics with counters only. More metrics will be added in future.")] + internal sealed class EvaluatorMetrics : IEvaluatorMetrics + { + private readonly Counters _counters; + + [Inject] + private EvaluatorMetrics(Counters counters) + { + _counters = counters; + } + + /// <summary> + /// Create an EvaluatorMetrics from a serialized metrics string. + /// </summary> + /// <param name="serializedMsg"></param> + internal EvaluatorMetrics(string serializedMsg) + { + _counters = new Counters(serializedMsg); + } + + /// <summary> + /// Returns counters + /// </summary> + /// <returns>Returns counters.</returns> + public ICounters GetMetricsCounters() + { + return _counters; + } + + /// <summary> + /// return serialized string of metrics counters data + /// </summary> + /// <returns>Returns serialized string of counters.</returns> + public string Serialize() + { + if (_counters != null) + { + return _counters.Serialize(); + } + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounter.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounter.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounter.cs new file mode 100644 index 0000000..be2e3c9 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounter.cs @@ -0,0 +1,46 @@ +// 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.Telemetry +{ + [Unstable("0.16", "This is a simple counter for evaluator metrics.")] + public interface ICounter + { + /// <summary> + /// Time the counter is updated. + /// </summary> + long Timestamp { get; } + + /// <summary> + /// Name of the counter. + /// </summary> + string Name { get; } + + /// <summary> + /// The description of the counter. + /// </summary> + string Description { get; } + + /// <summary> + /// The value of the counter. + /// </summary> + int Value { get; } + + /// <summary> + /// Increase the current counter value with the number specified. + /// </summary> + void Increment(int number); + } +} http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounters.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounters.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounters.cs new file mode 100644 index 0000000..b6f8809 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/ICounters.cs @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Collections.Generic; +using Org.Apache.REEF.Tang.Annotations; +using Org.Apache.REEF.Utilities.Attributes; + +namespace Org.Apache.REEF.Common.Telemetry +{ + [Unstable("0.16", "This is to build a collection of counters for evaluator metrics.")] + [DefaultImplementation(typeof(Counters))] + public interface ICounters + { + /// <summary> + /// Register a new counter with a specified name. + /// If name does not exist, the counter will be added and true will be returned + /// Otherwise the counter will be not added and false will be returned. + /// </summary> + /// <param name="name">Name of the counter to be registered.</param> + /// <param name="description">Description of the counter to be registered.</param> + /// <returns>Returns a boolean to indicate if the counter is added.</returns> + bool TryRegisterCounter(string name, string description); + + /// <summary> + /// Get counter value for a given counter name + /// </summary> + /// <param name="name">Name of the counter</param> + /// <param name="counter">The counter object returned</param> + /// <returns>Returns a boolean to indicate if the value is found.</returns> + bool TryGetValue(string name, out ICounter counter); + + /// <summary> + /// Increase the counter with the given number + /// </summary> + /// <param name="name">Name of the counter</param> + /// <param name="number">number to increase</param> + void Increment(string name, int number); + + /// <summary> + /// Returns all the counters + /// </summary> + /// <returns></returns> + IEnumerable<ICounter> GetCounters(); + + /// <summary> + /// Serialize the counter into a string + /// </summary> + /// <returns>Returns serialized string of the counters.</returns> + string Serialize(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/reef/blob/076b98c9/lang/cs/Org.Apache.REEF.Common/Telemetry/IEvaluatorMetrics.cs ---------------------------------------------------------------------- diff --git a/lang/cs/Org.Apache.REEF.Common/Telemetry/IEvaluatorMetrics.cs b/lang/cs/Org.Apache.REEF.Common/Telemetry/IEvaluatorMetrics.cs new file mode 100644 index 0000000..f4476f5 --- /dev/null +++ b/lang/cs/Org.Apache.REEF.Common/Telemetry/IEvaluatorMetrics.cs @@ -0,0 +1,39 @@ +// 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.Tang.Annotations; +using Org.Apache.REEF.Utilities.Attributes; + +namespace Org.Apache.REEF.Common.Telemetry +{ + [Unstable("0.16", "This is to build a simple metrics with counters only. More metrics will be added in future.")] + [DefaultImplementation(typeof(EvaluatorMetrics))] + public interface IEvaluatorMetrics + { + /// <summary> + /// Returns metrics counters + /// </summary> + /// <returns>Returns ICounters.</returns> + ICounters GetMetricsCounters(); + + /// <summary> + /// Serialize the metrics data into a string + /// </summary> + /// <returns>Returns serialized string of metrics</returns> + string Serialize(); + } +} \ No newline at end of file
