diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/AbstractSchedulerPlanFollower.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/AbstractSchedulerPlanFollower.java index 90357e3..2041d7d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/AbstractSchedulerPlanFollower.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/AbstractSchedulerPlanFollower.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.server.resourcemanager.reservation; +import org.apache.hadoop.util.StopWatch; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ReservationId; import org.apache.hadoop.yarn.api.records.Resource; @@ -45,6 +46,8 @@ private static final Logger LOG = LoggerFactory .getLogger(AbstractSchedulerPlanFollower.class); + private PlanFollowerMetrics planFollowerMetrics; + protected Collection plans = new ArrayList(); protected YarnScheduler scheduler; protected Clock clock; @@ -54,6 +57,7 @@ public void init(Clock clock, ResourceScheduler sched, Collection plans) { this.clock = clock; this.scheduler = sched; this.plans.addAll(plans); + this.planFollowerMetrics = PlanFollowerMetrics.getMetrics(); } @Override @@ -75,6 +79,8 @@ public synchronized void synchronizePlan(Plan plan, boolean shouldReplan) { if (LOG.isDebugEnabled()) { LOG.debug("Running plan follower edit policy for plan: " + planQueueName); } + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); // align with plan step long step = plan.getStep(); long now = clock.getTime(); @@ -83,7 +89,6 @@ public synchronized void synchronizePlan(Plan plan, boolean shouldReplan) { } Queue planQueue = getPlanQueue(planQueueName); if (planQueue == null) return; - // first we publish to the plan the current availability of resources Resource clusterResources = scheduler.getClusterResource(); Resource planResources = getPlanResources(plan, planQueue, @@ -214,10 +219,10 @@ public synchronized void synchronizePlan(Plan plan, boolean shouldReplan) { } catch (PlanningException e) { LOG.error("Exception in archiving completed reservations: ", e); } + this.planFollowerMetrics.setPlanFollowerSynchronizeMetrics(stopWatch.now()); LOG.info("Finished iteration of plan follower edit policy for plan: " + planQueueName); - // Extension: update plan with app states, - // useful to support smart replanning + // Extension: update plan with app states, to support smart replanning. } protected String getReservationIdFromQueueName(String resQueueName) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/InMemoryPlan.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/InMemoryPlan.java index 783fd09..9a36bae 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/InMemoryPlan.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/InMemoryPlan.java @@ -31,6 +31,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.apache.hadoop.util.StopWatch; import org.apache.hadoop.yarn.api.records.ReservationId; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.server.resourcemanager.reservation.RLESparseResourceAllocation.RLEOperator; @@ -90,6 +91,8 @@ private Resource totalCapacity; + private PlanMetrics planMetrics; + public InMemoryPlan(QueueMetrics queueMetrics, SharingPolicy policy, ReservationAgent agent, Resource totalCapacity, long step, ResourceCalculator resCalc, Resource minAlloc, Resource maxAlloc, @@ -119,6 +122,7 @@ public InMemoryPlan(QueueMetrics queueMetrics, SharingPolicy policy, this.getMoveOnExpiry = getMoveOnExpiry; this.clock = clock; this.rmStateStore = rmContext.getStateStore(); + this.planMetrics = PlanMetrics.getMetrics(); } @Override @@ -214,6 +218,8 @@ private void decrementAllocation(ReservationAllocation reservation) { @Override public boolean addReservation(ReservationAllocation reservation, boolean isRecovering) throws PlanningException { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); // Verify the allocation is memory based otherwise it is not supported InMemoryReservationAllocation inMemReservation = (InMemoryReservationAllocation) reservation; @@ -223,8 +229,10 @@ public boolean addReservation(ReservationAllocation reservation, + inMemReservation.getReservationId() + " is not mapped to any user"; LOG.error(errMsg); + planMetrics.setPlanAddReservationMetrics(stopWatch.now(), false); throw new IllegalArgumentException(errMsg); } + writeLock.lock(); try { if (reservationTable.containsKey(inMemReservation.getReservationId())) { @@ -257,6 +265,7 @@ public boolean addReservation(ReservationAllocation reservation, if (!reservations.add(inMemReservation)) { LOG.error("Unable to add reservation: {} to plan.", inMemReservation.getReservationId()); + planMetrics.setPlanAddReservationMetrics(stopWatch.now(), false); return false; } currentReservations.put(searchInterval, reservations); @@ -265,7 +274,11 @@ public boolean addReservation(ReservationAllocation reservation, incrementAllocation(inMemReservation); LOG.info("Successfully added reservation: {} to plan.", inMemReservation.getReservationId()); + planMetrics.setPlanAddReservationMetrics(stopWatch.now(), true); return true; + } catch (Exception e) { + planMetrics.setPlanAddReservationMetrics(stopWatch.now(), false); + throw e; } finally { writeLock.unlock(); } @@ -274,6 +287,8 @@ public boolean addReservation(ReservationAllocation reservation, @Override public boolean updateReservation(ReservationAllocation reservation) throws PlanningException { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); writeLock.lock(); boolean result = false; try { @@ -313,6 +328,7 @@ public boolean updateReservation(ReservationAllocation reservation) } } finally { writeLock.unlock(); + planMetrics.setPlanUpdateReservationMetrics(stopWatch.now(), result); } } @@ -352,6 +368,8 @@ private boolean removeReservation(ReservationAllocation reservation) { @Override public boolean deleteReservation(ReservationId reservationID) { + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); writeLock.lock(); try { ReservationAllocation reservation = getReservationById(reservationID); @@ -362,7 +380,12 @@ public boolean deleteReservation(ReservationId reservationID) { LOG.error(errMsg); throw new IllegalArgumentException(errMsg); } - return removeReservation(reservation); + boolean result = removeReservation(reservation); + planMetrics.setPlanDeleteReservationMetrics(stopWatch.now(), result); + return result; + } catch (Exception e){ + planMetrics.setPlanDeleteReservationMetrics(stopWatch.now(), false); + throw e; } finally { writeLock.unlock(); } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanFollowerMetrics.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanFollowerMetrics.java new file mode 100644 index 0000000..03937eb --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanFollowerMetrics.java @@ -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. + ******************************************************************************/ + +package org.apache.hadoop.yarn.server.resourcemanager.reservation; + +import static org.apache.hadoop.metrics2.lib.Interns.info; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsSystem; +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.MetricsRegistry; +import org.apache.hadoop.metrics2.lib.MutableCounterInt; +import org.apache.hadoop.metrics2.lib.MutableQuantiles; + +/** + * {@link PlanFollowerMetrics} is used to collect metrics for the + * {@link PlanFollower#synchronizePlan} method. + */ +@InterfaceAudience.Private +@Metrics(context = "yarn") +public final class PlanFollowerMetrics { + + private static AtomicBoolean isInitialized = new AtomicBoolean(false); + private static PlanFollowerMetrics instance = null; + private static MetricsRegistry registry; + + private MutableQuantiles planFollowerSynchronizeLatency; + + @Metric("Plan Follower Synchronize Count") + private MutableCounterInt planFollowerSynchronizeCount; + + private static final MetricsInfo RECORD_INFO = + info("PlanFollowerMetrics", "Metrics for the Yarn PlanFollower"); + + private PlanFollowerMetrics() { + } + + public static PlanFollowerMetrics getMetrics() { + if (!isInitialized.get()) { + synchronized (PlanFollowerMetrics.class) { + if (instance == null) { + instance = new PlanFollowerMetrics(); + registerMetrics(); + instance.initialize(); + isInitialized.set(true); + } + } + } + return instance; + } + + private static void registerMetrics() { + registry = new MetricsRegistry(RECORD_INFO); + registry.tag(RECORD_INFO, "ResourceManager"); + MetricsSystem ms = DefaultMetricsSystem.instance(); + if (ms != null) { + ms.register("PlanFollowerMetrics", "Metrics for the Yarn PlanFollower", + instance); + } + } + + private void initialize() { + planFollowerSynchronizeLatency = + registry.newQuantiles("PlanFollowerSynchronizeLatency", + "Latency for plan follower execution", "ops", "latency", 5); + } + + public void setPlanFollowerSynchronizeMetrics(long latency) { + planFollowerSynchronizeLatency.add(latency); + planFollowerSynchronizeCount.incr(); + } +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanMetrics.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanMetrics.java new file mode 100644 index 0000000..3005e5b --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/PlanMetrics.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * 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.yarn.server.resourcemanager.reservation; + +import static org.apache.hadoop.metrics2.lib.Interns.info; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsSystem; +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.MetricsRegistry; +import org.apache.hadoop.metrics2.lib.MutableCounterInt; +import org.apache.hadoop.metrics2.lib.MutableQuantiles; + +/** + * {@link PlanMetrics} is used to collect metrics for the + * {@link Plan}. Specifically, the latency, total count, and failure count of + * the addReservation, updateReservation, and deleteReservation methods are + * collected. + */ +@InterfaceAudience.Private +@Metrics(context = "yarn") +public final class PlanMetrics { + + private static AtomicBoolean isInitialized = new AtomicBoolean(false); + private static PlanMetrics instance = null; + private static MetricsRegistry registry; + + private MutableQuantiles planAddReservationLatency; + + private MutableQuantiles planUpdateReservationLatency; + + private MutableQuantiles planDeleteReservationLatency; + + @Metric("Plan Add Reservation Total Count") + private MutableCounterInt planAddReservationTotalCount; + + @Metric("Plan Update Reservation Total Count") + private MutableCounterInt planUpdateReservationTotalCount; + + @Metric("Plan Delete Reservation Total Count") + private MutableCounterInt planDeleteReservationTotalCount; + + @Metric("Plan Add Reservation Failure Count") + private MutableCounterInt planAddReservationFailureCount; + + @Metric("Plan Update Reservation Failure Count") + private MutableCounterInt planUpdateReservationFailureCount; + + @Metric("Plan Delete Reservation Failure Count") + private MutableCounterInt planDeleteReservationFailureCount; + + private static final MetricsInfo RECORD_INFO = + info("PlanMetrics", "Plan Metrics for Yarn"); + + private PlanMetrics() { + } + + public static PlanMetrics getMetrics() { + if (!isInitialized.get()) { + synchronized (PlanMetrics.class) { + if (instance == null) { + instance = new PlanMetrics(); + registerMetrics(); + instance.initialize(); + isInitialized.set(true); + } + } + } + return instance; + } + + private static void registerMetrics() { + registry = new MetricsRegistry(RECORD_INFO); + registry.tag(RECORD_INFO, "ResourceManager"); + MetricsSystem ms = DefaultMetricsSystem.instance(); + if (ms != null) { + ms.register("PlanMetrics", "Plan Metrics for Yarn", + instance); + } + } + + private void initialize() { + planAddReservationLatency = + registry.newQuantiles("ReservationAgentAddReservationLatency", + "Latency for create reservation", "ops", "latency", 5); + + planUpdateReservationLatency = + registry.newQuantiles("ReservationAgentUpdateReservationLatency", + "Latency for update reservation", "ops", "latency", 5); + + planDeleteReservationLatency = + registry.newQuantiles("ReservationAgentDeleteReservationLatency", + "Latency for remove reservation", "ops", "latency", 5); + } + + public void setPlanAddReservationMetrics(long latency, boolean success) { + planAddReservationLatency.add(latency); + planAddReservationTotalCount.incr(); + if (!success) { + planAddReservationFailureCount.incr(); + } + } + + public void setPlanUpdateReservationMetrics(long latency, boolean success) { + planUpdateReservationLatency.add(latency); + planUpdateReservationTotalCount.incr(); + if (!success) { + planUpdateReservationFailureCount.incr(); + } + } + + public void setPlanDeleteReservationMetrics(long latency, boolean success) { + planDeleteReservationLatency.add(latency); + planDeleteReservationTotalCount.incr(); + if (!success) { + planDeleteReservationFailureCount.incr(); + } + } +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AbstractReservationAgent.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AbstractReservationAgent.java new file mode 100644 index 0000000..b46eb0d --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AbstractReservationAgent.java @@ -0,0 +1,132 @@ +/** + * 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.yarn.server.resourcemanager.reservation.planning; + +import org.apache.hadoop.util.StopWatch; +import org.apache.hadoop.yarn.api.records.ReservationDefinition; +import org.apache.hadoop.yarn.api.records.ReservationId; +import org.apache.hadoop.yarn.server.resourcemanager.reservation.Plan; +import org.apache.hadoop.yarn.server.resourcemanager.reservation.exceptions.PlanningException; +import org.slf4j.Logger; + +/** + * This agent wraps the implementation of {@link ReservationAgent} to provide + * common functionality. An example is logging, and gathering metrics. + */ +abstract class AbstractReservationAgent implements ReservationAgent { + + private ReservationAgentMetrics reservationAgentMetrics; + + protected AbstractReservationAgent() { + reservationAgentMetrics = ReservationAgentMetrics.getMetrics(); + } + + protected abstract Logger getLogger(); + + protected abstract boolean createReservationImpl(ReservationId reservationId, + String user, Plan plan, ReservationDefinition contract) + throws PlanningException; + + @Override + public boolean createReservation(ReservationId reservationId, String user, + Plan plan, ReservationDefinition contract) throws PlanningException { + + getLogger().info("placing the following ReservationRequest: " + contract); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + try { + boolean res = createReservationImpl(reservationId, user, plan, contract); + + if (res) { + getLogger().info("OUTCOME: SUCCESS, Reservation ID: " + + reservationId.toString() + ", Contract: " + contract.toString()); + } else { + getLogger().info("OUTCOME: FAILURE, Reservation ID: " + + reservationId.toString() + ", Contract: " + contract.toString()); + } + + reservationAgentMetrics.setAgentCreateReservationMetrics(stopWatch.now(), + res); + return res; + } catch (PlanningException e) { + getLogger().info("OUTCOME: FAILURE, Reservation ID: " + + reservationId.toString() + ", Contract: " + contract.toString()); + reservationAgentMetrics.setAgentCreateReservationMetrics(stopWatch.now(), + false); + throw e; + } + } + + protected abstract boolean updateReservationImpl(ReservationId reservationId, + String user, Plan plan, ReservationDefinition contract) + throws PlanningException; + + @Override + public boolean updateReservation(ReservationId reservationId, String user, + Plan plan, ReservationDefinition contract) throws PlanningException { + + getLogger().info("updating the following ReservationRequest: " + contract); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + try { + boolean status = + updateReservationImpl(reservationId, user, plan, contract); + reservationAgentMetrics.setAgentUpdateReservationMetrics(stopWatch.now(), + status); + return status; + } catch (PlanningException e) { + getLogger().info("OUTCOME: FAILURE, Reservation ID: " + + reservationId.toString() + ", Contract: " + contract.toString()); + reservationAgentMetrics.setAgentUpdateReservationMetrics(stopWatch.now(), + false); + throw e; + } + } + + public abstract boolean deleteReservationImpl(ReservationId reservationId, + String user, Plan plan) throws PlanningException; + + @Override + public boolean deleteReservation(ReservationId reservationId, String user, + Plan plan) throws PlanningException { + + getLogger().info("removing the following ReservationId: " + reservationId); + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + try { + boolean status = deleteReservationImpl(reservationId, user, plan); + reservationAgentMetrics.setAgentDeleteReservationMetrics(stopWatch.now(), + status); + return status; + } catch (PlanningException e) { + getLogger().info( + "OUTCOME: FAILURE, Reservation ID: " + reservationId.toString()); + reservationAgentMetrics.setAgentDeleteReservationMetrics(stopWatch.now(), + false); + throw e; + } + } + +} diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AlignedPlannerWithGreedy.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AlignedPlannerWithGreedy.java index 3853f41..20a11d3 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AlignedPlannerWithGreedy.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/AlignedPlannerWithGreedy.java @@ -33,7 +33,7 @@ * A planning algorithm that first runs LowCostAligned, and if it fails runs * Greedy. */ -public class AlignedPlannerWithGreedy implements ReservationAgent { +public class AlignedPlannerWithGreedy extends AbstractReservationAgent { // Default smoothness factor public static final int DEFAULT_SMOOTHNESS_FACTOR = 10; @@ -84,49 +84,25 @@ public void init(Configuration conf) { planner = new TryManyReservationAgents(listAlg); } + public Logger getLogger() { + return LOG; + } + @Override - public boolean createReservation(ReservationId reservationId, String user, + public boolean createReservationImpl(ReservationId reservationId, String user, Plan plan, ReservationDefinition contract) throws PlanningException { - - LOG.info("placing the following ReservationRequest: " + contract); - - try { - boolean res = - planner.createReservation(reservationId, user, plan, contract); - - if (res) { - LOG.info("OUTCOME: SUCCESS, Reservation ID: " - + reservationId.toString() + ", Contract: " + contract.toString()); - } else { - LOG.info("OUTCOME: FAILURE, Reservation ID: " - + reservationId.toString() + ", Contract: " + contract.toString()); - } - return res; - } catch (PlanningException e) { - LOG.info("OUTCOME: FAILURE, Reservation ID: " + reservationId.toString() - + ", Contract: " + contract.toString()); - throw e; - } - + return planner.createReservation(reservationId, user, plan, contract); } @Override - public boolean updateReservation(ReservationId reservationId, String user, + public boolean updateReservationImpl(ReservationId reservationId, String user, Plan plan, ReservationDefinition contract) throws PlanningException { - - LOG.info("updating the following ReservationRequest: " + contract); - return planner.updateReservation(reservationId, user, plan, contract); - } @Override - public boolean deleteReservation(ReservationId reservationId, String user, + public boolean deleteReservationImpl(ReservationId reservationId, String user, Plan plan) throws PlanningException { - - LOG.info("removing the following ReservationId: " + reservationId); - return planner.deleteReservation(reservationId, user, plan); - } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/GreedyReservationAgent.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/GreedyReservationAgent.java index 637a17b..8adbdc4 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/GreedyReservationAgent.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/GreedyReservationAgent.java @@ -39,7 +39,7 @@ * size). */ -public class GreedyReservationAgent implements ReservationAgent { +public class GreedyReservationAgent extends AbstractReservationAgent { // Log private static final Logger LOG = LoggerFactory @@ -74,50 +74,27 @@ public void init(Configuration conf) { public boolean isAllocateLeft(){ return allocateLeft; } - @Override - public boolean createReservation(ReservationId reservationId, String user, - Plan plan, ReservationDefinition contract) throws PlanningException { - - LOG.info("placing the following ReservationRequest: " + contract); - - try { - boolean res = - planner.createReservation(reservationId, user, plan, contract); - - if (res) { - LOG.info("OUTCOME: SUCCESS, Reservation ID: " - + reservationId.toString() + ", Contract: " + contract.toString()); - } else { - LOG.info("OUTCOME: FAILURE, Reservation ID: " - + reservationId.toString() + ", Contract: " + contract.toString()); - } - return res; - } catch (PlanningException e) { - LOG.info("OUTCOME: FAILURE, Reservation ID: " + reservationId.toString() - + ", Contract: " + contract.toString()); - throw e; - } + public Logger getLogger() { + return LOG; } @Override - public boolean updateReservation(ReservationId reservationId, String user, + public boolean createReservationImpl(ReservationId reservationId, String user, Plan plan, ReservationDefinition contract) throws PlanningException { + return planner.createReservation(reservationId, user, plan, contract); + } - LOG.info("updating the following ReservationRequest: " + contract); - + @Override + public boolean updateReservationImpl(ReservationId reservationId, String user, + Plan plan, ReservationDefinition contract) throws PlanningException { return planner.updateReservation(reservationId, user, plan, contract); - } @Override - public boolean deleteReservation(ReservationId reservationId, String user, + public boolean deleteReservationImpl(ReservationId reservationId, String user, Plan plan) throws PlanningException { - - LOG.info("removing the following ReservationId: " + reservationId); - return planner.deleteReservation(reservationId, user, plan); - } } diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/ReservationAgentMetrics.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/ReservationAgentMetrics.java new file mode 100644 index 0000000..a953a5b --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/reservation/planning/ReservationAgentMetrics.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * 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.yarn.server.resourcemanager.reservation.planning; + +import static org.apache.hadoop.metrics2.lib.Interns.info; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsSystem; +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.MetricsRegistry; +import org.apache.hadoop.metrics2.lib.MutableCounterInt; +import org.apache.hadoop.metrics2.lib.MutableQuantiles; + +/** + * {@link ReservationAgentMetrics} is used to collect metrics for the + * {@link ReservationAgent}. Specifically, the latency, total count, and + * failure count of the createReservation, updateReservation, and + * deleteReservation methods are collected. + */ +@InterfaceAudience.Private +@Metrics(context = "yarn") +public final class ReservationAgentMetrics { + + private static AtomicBoolean isInitialized = new AtomicBoolean(false); + private static ReservationAgentMetrics instance = null; + private static MetricsRegistry registry; + + private MutableQuantiles reservationAgentCreateReservationLatency; + + private MutableQuantiles reservationAgentUpdateReservationLatency; + + private MutableQuantiles reservationAgentDeleteReservationLatency; + + @Metric("Reservation Agent Create Reservation Total Count") + private MutableCounterInt reservationAgentCreateReservationTotalCount; + + @Metric("Reservation Agent Update Reservation Total Count") + private MutableCounterInt reservationAgentUpdateReservationTotalCount; + + @Metric("Reservation Agent Delete Reservation Total Count") + private MutableCounterInt reservationAgentDeleteReservationTotalCount; + + @Metric("Reservation Agent Create Reservation Failure Count") + private MutableCounterInt reservationAgentCreateReservationFailureCount; + + @Metric("Reservation Agent Update Reservation Failure Count") + private MutableCounterInt reservationAgentUpdateReservationFailureCount; + + @Metric("Reservation Agent Delete Reservation Failure Count") + private MutableCounterInt reservationAgentDeleteReservationFailureCount; + + private static final MetricsInfo RECORD_INFO = + info("ReservationAgentMetrics", "Metrics for the Yarn ReservationAgent"); + + private ReservationAgentMetrics() { + } + + public static ReservationAgentMetrics getMetrics() { + if (!isInitialized.get()) { + synchronized (ReservationAgentMetrics.class) { + if (instance == null) { + instance = new ReservationAgentMetrics(); + registerMetrics(); + instance.initialize(); + isInitialized.set(true); + } + } + } + return instance; + } + + private static void registerMetrics() { + registry = new MetricsRegistry(RECORD_INFO); + registry.tag(RECORD_INFO, "ResourceManager"); + MetricsSystem ms = DefaultMetricsSystem.instance(); + if (ms != null) { + ms.register("ReservationAgentMetrics", + "Metrics for the Yarn ReservationAgent", instance); + } + } + + private void initialize() { + reservationAgentCreateReservationLatency = + registry.newQuantiles("ReservationAgentCreateReservationLatency", + "Latency for create reservation", "ops", "latency", 5); + + reservationAgentUpdateReservationLatency = + registry.newQuantiles("ReservationAgentUpdateReservationLatency", + "Latency for update reservation", "ops", "latency", 5); + + reservationAgentDeleteReservationLatency = + registry.newQuantiles("ReservationAgentDeleteReservationLatency", + "Latency for delete reservation", "ops", "latency", 5); + } + + public void setAgentCreateReservationMetrics(long latency, boolean success) { + reservationAgentCreateReservationLatency.add(latency); + reservationAgentCreateReservationTotalCount.incr(); + if (!success) { + reservationAgentCreateReservationFailureCount.incr(); + } + } + + public void setAgentUpdateReservationMetrics(long latency, boolean success) { + reservationAgentUpdateReservationLatency.add(latency); + reservationAgentUpdateReservationTotalCount.incr(); + if (!success) { + reservationAgentUpdateReservationFailureCount.incr(); + } + } + + public void setAgentDeleteReservationMetrics(long latency, boolean success) { + reservationAgentDeleteReservationLatency.add(latency); + reservationAgentDeleteReservationTotalCount.incr(); + if (!success) { + reservationAgentDeleteReservationFailureCount.incr(); + } + } +}