diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsRegistry.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsRegistry.java index 1ef74f4..531231c 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsRegistry.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsRegistry.java @@ -143,6 +143,7 @@ MutableCounterLong newCounter(MetricsInfo info, long iVal) { public MutableGaugeInt newGauge(String name, String desc, int iVal) { return newGauge(Interns.info(name, desc), iVal); } + /** * Create a mutable integer gauge * @param info metadata of the metric @@ -181,6 +182,30 @@ public synchronized MutableGaugeLong newGauge(MetricsInfo info, long iVal) { } /** + * Create a mutable float gauge + * @param name of the metric + * @param desc metric description + * @param iVal initial value + * @return a new gauge object + */ + public MutableGaugeFloat newGauge(String name, String desc, float iVal) { + return newGauge(Interns.info(name, desc), iVal); + } + + /** + * Create a mutable float gauge + * @param info metadata of the metric + * @param iVal initial value + * @return a new gauge object + */ + public synchronized MutableGaugeFloat newGauge(MetricsInfo info, float iVal) { + checkMetricName(info.name()); + MutableGaugeFloat ret = new MutableGaugeFloat(info, iVal); + metricsMap.put(info.name(), ret); + return ret; + } + + /** * Create a mutable metric that estimates quantiles of a stream of values * @param name of the metric * @param desc metric description @@ -420,4 +445,5 @@ public synchronized void snapshot(MetricsRecordBuilder builder, boolean all) { .add("info", metricsInfo).add("tags", tags()).add("metrics", metrics()) .toString(); } + } diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableGaugeFloat.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableGaugeFloat.java new file mode 100644 index 0000000..2729d44 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableGaugeFloat.java @@ -0,0 +1,77 @@ +/** + * 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. + */ + +package org.apache.hadoop.metrics2.lib; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; + +public class MutableGaugeFloat extends MutableGauge { + + private AtomicInteger value = new AtomicInteger(); + + MutableGaugeFloat(MetricsInfo info, float initValue) { + super(info); + this.value.set(Float.floatToIntBits(initValue)); + } + + public float value() { + return Float.intBitsToFloat(value.get()); + } + + @Override + public void incr() { + incr(1.0f); + } + + @Override + public void decr() { + incr(-1.0f); + } + + @Override + public void snapshot(MetricsRecordBuilder builder, boolean all) { + if (all || changed()) { + builder.addGauge(info(), value()); + clearChanged(); + } + } + + public void set(float value) { + this.value.set(Float.floatToIntBits(value)); + setChanged(); + } + + private final boolean compareAndSet(float expect, float update) { + return value.compareAndSet(Float.floatToIntBits(expect), + Float.floatToIntBits(update)); + } + + private void incr(float delta) { + while (true) { + float current = value.get(); + float next = current + delta; + if (compareAndSet(current, next)) { + setChanged(); + return; + } + } + } +} diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableMetricsFactory.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableMetricsFactory.java index a576772..7900332 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableMetricsFactory.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MutableMetricsFactory.java @@ -60,6 +60,9 @@ MutableMetric newForField(Field field, Metric annotation, if (cls == MutableGaugeLong.class) { return registry.newGauge(info, 0L); } + if (cls == MutableGaugeFloat.class) { + return registry.newGauge(info, 0f); + } if (cls == MutableRate.class) { return registry.newRate(info.name(), info.description(), annotation.always()); diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsAnnotations.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsAnnotations.java index 5b75e33..00c2165 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsAnnotations.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsAnnotations.java @@ -39,6 +39,7 @@ @Metric({"Counter2", "Counter2 desc"}) MutableCounterLong c2; @Metric MutableGaugeInt g1, g2; @Metric("g3 desc") MutableGaugeLong g3; + @Metric("g4 desc") MutableGaugeFloat g4; @Metric MutableRate r1; @Metric MutableStat s1; @Metric MutableRates rs1; @@ -53,6 +54,7 @@ metrics.g1.incr(); metrics.g2.incr(); metrics.g3.incr(); + metrics.g4.incr(); metrics.r1.add(1); metrics.s1.add(1); metrics.rs1.add("rs1", 1); @@ -64,6 +66,7 @@ verify(rb).addGauge(info("G1", "G1"), 1); verify(rb).addGauge(info("G2", "G2"), 1); verify(rb).addGauge(info("G3", "g3 desc"), 1L); + verify(rb).addGauge(info("G4", "g4 desc"), 1f); verify(rb).addCounter(info("R1NumOps", "Number of ops for r1"), 1L); verify(rb).addGauge(info("R1AvgTime", "Average time for r1"), 1.0); verify(rb).addCounter(info("S1NumOps", "Number of ops for s1"), 1L); diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsRegistry.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsRegistry.java index d916928..73ea43f 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsRegistry.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMetricsRegistry.java @@ -42,13 +42,15 @@ r.newCounter("c2", "c2 desc", 2L); r.newGauge("g1", "g1 desc", 3); r.newGauge("g2", "g2 desc", 4L); + r.newGauge("g3", "g3 desc", 5f); r.newStat("s1", "s1 desc", "ops", "time"); - assertEquals("num metrics in registry", 5, r.metrics().size()); + assertEquals("num metrics in registry", 6, r.metrics().size()); assertTrue("c1 found", r.get("c1") instanceof MutableCounterInt); assertTrue("c2 found", r.get("c2") instanceof MutableCounterLong); assertTrue("g1 found", r.get("g1") instanceof MutableGaugeInt); assertTrue("g2 found", r.get("g2") instanceof MutableGaugeLong); + assertTrue("g3 found", r.get("g3") instanceof MutableGaugeFloat); assertTrue("s1 found", r.get("s1") instanceof MutableStat); expectMetricsException("Metric name c1 already exists", new Runnable() { diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMutableMetrics.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMutableMetrics.java index 1faa361..fd716ae 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMutableMetrics.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/metrics2/lib/TestMutableMetrics.java @@ -59,6 +59,7 @@ registry.newCounter("c2", "long counter", 2L); registry.newGauge("g1", "int gauge", 3); registry.newGauge("g2", "long gauge", 4L); + registry.newGauge("g3", "float gauge", 5f); registry.newStat("s1", "stat", "Ops", "Time", true).add(0); registry.newRate("s2", "stat", false).add(0); @@ -74,6 +75,7 @@ verify(mb).addCounter(info("c2", "long counter"), 2L); verify(mb).addGauge(info("g1", "int gauge"), 3); verify(mb).addGauge(info("g2", "long gauge"), 4L); + verify(mb).addGauge(info("g3", "float gauge"), 5f); verify(mb).addCounter(info("S1NumOps", "Number of ops for stat"), 1L); verify(mb).addGauge(eq(info("S1AvgTime", "Average time for stat")), eq(0.0, EPSILON)); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java index aa60c9c..60e8404 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/AbstractCSQueue.java @@ -228,16 +228,6 @@ public boolean hasAccess(QueueACL acl, UserGroupInformation user) { null, null, Server.getRemoteAddress(), null)); } - @Override - public void setUsedCapacity(float usedCapacity) { - queueCapacities.setUsedCapacity(usedCapacity); - } - - @Override - public void setAbsoluteUsedCapacity(float absUsedCapacity) { - queueCapacities.setAbsoluteUsedCapacity(absUsedCapacity); - } - /** * Set maximum capacity - used only for testing. * @param maximumCapacity new max capacity @@ -735,7 +725,7 @@ public void incUsedResource(String nodeLabel, Resource resourceToInc, queueUsage.incUsed(nodeLabel, resourceToInc); CSQueueUtils.updateUsedCapacity(resourceCalculator, labelManager.getResourceByLabel(nodeLabel, Resources.none()), - minimumAllocation, queueUsage, queueCapacities, nodeLabel); + minimumAllocation, queueUsage, nodeLabel, this); if (null != parent) { parent.incUsedResource(nodeLabel, resourceToInc, null); } @@ -751,7 +741,7 @@ public void decUsedResource(String nodeLabel, Resource resourceToDec, queueUsage.decUsed(nodeLabel, resourceToDec); CSQueueUtils.updateUsedCapacity(resourceCalculator, labelManager.getResourceByLabel(nodeLabel, Resources.none()), - minimumAllocation, queueUsage, queueCapacities, nodeLabel); + minimumAllocation, queueUsage, nodeLabel, this); if (null != parent) { parent.decUsedResource(nodeLabel, resourceToDec, null); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java index 6d30386..c6726ec 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueue.java @@ -121,20 +121,6 @@ public float getAbsoluteUsedCapacity(); /** - * Set used capacity of the queue. - * @param usedCapacity - * used capacity of the queue - */ - public void setUsedCapacity(float usedCapacity); - - /** - * Set absolute used capacity of the queue. - * @param absUsedCapacity - * absolute used capacity of the queue - */ - public void setAbsoluteUsedCapacity(float absUsedCapacity); - - /** * Get the current used capacity of nodes without label(s) of the queue * and it's children (if any). * @return queue used capacity diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueMetrics.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueMetrics.java index 58c3984..a601b7b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueMetrics.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueMetrics.java @@ -23,6 +23,7 @@ import org.apache.hadoop.metrics2.annotation.Metric; import org.apache.hadoop.metrics2.annotation.Metrics; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.apache.hadoop.metrics2.lib.MutableGaugeFloat; import org.apache.hadoop.metrics2.lib.MutableGaugeLong; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.server.resourcemanager.scheduler.Queue; @@ -39,6 +40,10 @@ MutableGaugeLong usedAMResourceMB; @Metric("Used AM CPU limit in virtual cores") MutableGaugeLong usedAMResourceVCores; + @Metric("Percent of Capacity Used") + MutableGaugeFloat usedCapacity; + @Metric("Percent of Absolute Capacity Used") + MutableGaugeFloat absoluteUsedCapacity; CSQueueMetrics(MetricsSystem ms, String queueName, Queue parent, boolean enableUserMetrics, Configuration conf) { @@ -91,6 +96,22 @@ public void decAMUsed(String user, Resource res) { } } + public float getUsedCapacity() { + return usedCapacity.value(); + } + + public void setUsedCapacity(float usedCapacity) { + this.usedCapacity.set(usedCapacity); + } + + public float getAbsoluteUsedCapacity() { + return absoluteUsedCapacity.value(); + } + + public void setAbsoluteUsedCapacity(Float absoluteUsedCapacity) { + this.absoluteUsedCapacity.set(absoluteUsedCapacity); + } + public synchronized static CSQueueMetrics forQueue(String queueName, Queue parent, boolean enableUserMetrics, Configuration conf) { MetricsSystem ms = DefaultMetricsSystem.instance(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueUtils.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueUtils.java index d5cdb32..b284374 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueUtils.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/scheduler/capacity/CSQueueUtils.java @@ -182,8 +182,10 @@ private static void updateAbsoluteCapacitiesByNodeLabels( */ public static void updateUsedCapacity(final ResourceCalculator rc, final Resource totalPartitionResource, final Resource minimumAllocation, - ResourceUsage queueResourceUsage, QueueCapacities queueCapacities, - String nodePartition) { + ResourceUsage queueResourceUsage, String nodePartition, + AbstractCSQueue childQueue) { + QueueCapacities queueCapacities = childQueue.getQueueCapacities(); + CSQueueMetrics queueMetrics = childQueue.getMetrics(); float absoluteUsedCapacity = 0.0f; float usedCapacity = 0.0f; float reservedCapacity = 0.0f; @@ -225,6 +227,13 @@ public static void updateUsedCapacity(final ResourceCalculator rc, queueCapacities.setReservedCapacity(nodePartition, reservedCapacity); queueCapacities .setAbsoluteReservedCapacity(nodePartition, absoluteReservedCapacity); + + // TODO(YARN-XXXX): Right now QueueMetrics only reflects the no-label case. + if (nodePartition == null + || nodePartition == CommonNodeLabelsManager.NO_LABEL) { + queueMetrics.setUsedCapacity(usedCapacity); + queueMetrics.setAbsoluteUsedCapacity(absoluteUsedCapacity); + } } private static Resource getMaxAvailableResourceToQueue( @@ -271,7 +280,7 @@ private static Resource getMaxAvailableResourceToQueue( @Lock(CSQueue.class) public static void updateQueueStatistics( final ResourceCalculator rc, final Resource cluster, final Resource minimumAllocation, - final CSQueue childQueue, final RMNodeLabelsManager nlm, + final AbstractCSQueue childQueue, final RMNodeLabelsManager nlm, final String nodePartition) { QueueCapacities queueCapacities = childQueue.getQueueCapacities(); ResourceUsage queueResourceUsage = childQueue.getQueueResourceUsage(); @@ -281,11 +290,11 @@ public static void updateQueueStatistics( queueCapacities.getNodePartitionsSet(), queueResourceUsage.getNodePartitionsSet())) { updateUsedCapacity(rc, nlm.getResourceByLabel(partition, cluster), - minimumAllocation, queueResourceUsage, queueCapacities, partition); + minimumAllocation, queueResourceUsage, partition, childQueue); } } else { updateUsedCapacity(rc, nlm.getResourceByLabel(nodePartition, cluster), - minimumAllocation, queueResourceUsage, queueCapacities, nodePartition); + minimumAllocation, queueResourceUsage, nodePartition, childQueue); } // Update queue metrics w.r.t node labels. In a generic way, we can