From 4e886eb9cbd2dcb128bbfd17309c734083093a4c Mon Sep 17 00:00:00 2001 From: Jian He Date: Thu, 19 Mar 2015 22:27:21 -0700 Subject: [PATCH] YARN-3379. Fixed missing data in localityTable and ResourceRequests table in RM WebUI. Contributed by Xuan Gong --- hadoop-yarn-project/CHANGES.txt | 3 + .../yarn/server/webapp/AppAttemptBlock.java | 71 +------ .../hadoop/yarn/server/webapp/AppBlock.java | 87 +-------- .../webapp/AppAttemptPage.java | 3 +- .../resourcemanager/webapp/AppPage.java | 3 +- .../webapp/RMAppAttemptBlock.java | 177 ++++++++++++++++++ .../resourcemanager/webapp/RMAppBlock.java | 94 ++++++++++ 7 files changed, 290 insertions(+), 148 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppAttemptBlock.java create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppBlock.java diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index 0a143ddf027..4685eb702bc 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -796,6 +796,9 @@ Release 2.7.0 - UNRELEASED YARN-3349. Treat all exceptions as failure in TestFSRMStateStore#testFSRMStateStoreClientRetry. (Zhihai Xu via ozawa) + YARN-3379. Fixed missing data in localityTable and ResourceRequests table + in RM WebUI. (Xuan Gong via jianhe) + Release 2.6.0 - 2014-11-18 INCOMPATIBLE CHANGES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppAttemptBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppAttemptBlock.java index eeccf0fc0e3..dca39d6d3c0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppAttemptBlock.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppAttemptBlock.java @@ -19,12 +19,6 @@ package org.apache.hadoop.yarn.server.webapp; import static org.apache.hadoop.yarn.util.StringHelper.join; import static org.apache.hadoop.yarn.webapp.YarnWebParams.APPLICATION_ATTEMPT_ID; -import static org.apache.hadoop.yarn.webapp.YarnWebParams.WEB_UI_TYPE; -import static org.apache.hadoop.yarn.webapp.view.JQueryUI._EVEN; -import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP; -import static org.apache.hadoop.yarn.webapp.view.JQueryUI._ODD; -import static org.apache.hadoop.yarn.webapp.view.JQueryUI._TH; - import java.security.PrivilegedExceptionAction; import java.util.Collection; @@ -43,20 +37,18 @@ import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState; import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo; import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo; import org.apache.hadoop.yarn.util.ConverterUtils; -import org.apache.hadoop.yarn.webapp.YarnWebParams; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; -import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import org.apache.hadoop.yarn.webapp.view.InfoBlock; - import com.google.inject.Inject; public class AppAttemptBlock extends HtmlBlock { private static final Log LOG = LogFactory.getLog(AppAttemptBlock.class); protected ApplicationBaseProtocol appBaseProt; + protected ApplicationAttemptId appAttemptId = null; @Inject public AppAttemptBlock(ApplicationBaseProtocol appBaseProt, ViewContext ctx) { @@ -66,14 +58,12 @@ public class AppAttemptBlock extends HtmlBlock { @Override protected void render(Block html) { - String webUiType = $(WEB_UI_TYPE); String attemptid = $(APPLICATION_ATTEMPT_ID); if (attemptid.isEmpty()) { puts("Bad request: requires application attempt ID"); return; } - ApplicationAttemptId appAttemptId = null; try { appAttemptId = ConverterUtils.toApplicationAttemptId(attemptid); } catch (IllegalArgumentException e) { @@ -183,17 +173,7 @@ public class AppAttemptBlock extends HtmlBlock { return; } - // TODO need to render applicationHeadRoom value from - // ApplicationAttemptMetrics after YARN-3284 - if (webUiType.equals(YarnWebParams.RM_WEB_UI)) { - if (!isApplicationInFinalState(appAttempt.getAppAttemptState())) { - DIV pdiv = html._(InfoBlock.class).div(_INFO_WRAP); - info("Application Attempt Overview").clear(); - info("Application Attempt Metrics")._( - "Application Attempt Headroom : ", 0); - pdiv._(); - } - } + createAttemptHeadRoomTable(html); html._(InfoBlock.class); // Container Table @@ -236,45 +216,6 @@ public class AppAttemptBlock extends HtmlBlock { ._("var containersTableData=" + containersTableData)._(); tbody._()._(); - - if (webUiType.equals(YarnWebParams.RM_WEB_UI)) { - createContainerLocalityTable(html); // TODO:YARN-3284 - } - } - - //TODO: YARN-3284 - //The containerLocality metrics will be exposed from AttemptReport - private void createContainerLocalityTable(Block html) { - int totalAllocatedContainers = 0; //TODO: YARN-3284 - int[][] localityStatistics = new int[0][0];//TODO:YARN-3284 - DIV div = html.div(_INFO_WRAP); - TABLE> table = - div.h3( - "Total Allocated Containers: " - + totalAllocatedContainers).h3("Each table cell" - + " represents the number of NodeLocal/RackLocal/OffSwitch containers" - + " satisfied by NodeLocal/RackLocal/OffSwitch resource requests.").table( - "#containerLocality"); - table. - tr(). - th(_TH, ""). - th(_TH, "Node Local Request"). - th(_TH, "Rack Local Request"). - th(_TH, "Off Switch Request"). - _(); - - String[] containersType = - { "Num Node Local Containers (satisfied by)", "Num Rack Local Containers (satisfied by)", - "Num Off Switch Containers (satisfied by)" }; - boolean odd = false; - for (int i = 0; i < localityStatistics.length; i++) { - table.tr((odd = !odd) ? _ODD : _EVEN).td(containersType[i]) - .td(String.valueOf(localityStatistics[i][0])) - .td(i == 0 ? "" : String.valueOf(localityStatistics[i][1])) - .td(i <= 1 ? "" : String.valueOf(localityStatistics[i][2]))._(); - } - table._(); - div._(); } private boolean hasAMContainer(ContainerId containerId, @@ -286,10 +227,8 @@ public class AppAttemptBlock extends HtmlBlock { } return false; } - - private boolean isApplicationInFinalState(YarnApplicationAttemptState state) { - return state == YarnApplicationAttemptState.FINISHED - || state == YarnApplicationAttemptState.FAILED - || state == YarnApplicationAttemptState.KILLED; + + protected void createAttemptHeadRoomTable(Block html) { + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java index 5fc5fa06ac0..abb6b9cebf3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java @@ -21,11 +21,8 @@ package org.apache.hadoop.yarn.server.webapp; import static org.apache.hadoop.yarn.util.StringHelper.join; import static org.apache.hadoop.yarn.webapp.YarnWebParams.APPLICATION_ID; import static org.apache.hadoop.yarn.webapp.YarnWebParams.WEB_UI_TYPE; -import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP; import java.security.PrivilegedExceptionAction; import java.util.Collection; -import java.util.List; - import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,12 +36,9 @@ import org.apache.hadoop.yarn.api.protocolrecords.GetContainerReportRequest; import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationReport; -import org.apache.hadoop.yarn.api.records.ApplicationResourceUsageReport; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerReport; import org.apache.hadoop.yarn.api.records.FinalApplicationStatus; -import org.apache.hadoop.yarn.api.records.Resource; -import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.api.records.YarnApplicationState; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.ContainerNotFoundException; @@ -53,10 +47,8 @@ import org.apache.hadoop.yarn.server.webapp.dao.AppInfo; import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo; import org.apache.hadoop.yarn.util.Apps; import org.apache.hadoop.yarn.util.Times; -import org.apache.hadoop.yarn.util.resource.Resources; import org.apache.hadoop.yarn.webapp.YarnWebParams; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; -import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; import org.apache.hadoop.yarn.webapp.view.HtmlBlock; @@ -69,9 +61,11 @@ public class AppBlock extends HtmlBlock { private static final Log LOG = LogFactory.getLog(AppBlock.class); protected ApplicationBaseProtocol appBaseProt; protected Configuration conf; + protected ApplicationId appID = null; @Inject - AppBlock(ApplicationBaseProtocol appBaseProt, ViewContext ctx, Configuration conf) { + protected AppBlock(ApplicationBaseProtocol appBaseProt, ViewContext ctx, + Configuration conf) { super(ctx); this.appBaseProt = appBaseProt; this.conf = conf; @@ -86,7 +80,6 @@ public class AppBlock extends HtmlBlock { return; } - ApplicationId appID = null; try { appID = Apps.toAppID(aid); } catch (Exception e) { @@ -213,31 +206,7 @@ public class AppBlock extends HtmlBlock { return; } - //TODO:YARN-3284 - //The preemption metrics will be exposed from ApplicationReport - // and ApplicationAttemptReport - ApplicationResourceUsageReport usageReport = - appReport.getApplicationResourceUsageReport(); - DIV pdiv = html. - _(InfoBlock.class). - div(_INFO_WRAP); - info("Application Overview").clear(); - info("Application Metrics") - ._("Total Resource Preempted:", - Resources.none()) // TODO: YARN-3284 - ._("Total Number of Non-AM Containers Preempted:", - String.valueOf(0)) // TODO: YARN-3284 - ._("Total Number of AM Containers Preempted:", - String.valueOf(0)) // TODO: YARN-3284 - ._("Resource Preempted from Current Attempt:", - Resources.none()) // TODO: YARN-3284 - ._("Number of Non-AM Containers Preempted from Current Attempt:", - 0) // TODO: YARN-3284 - ._("Aggregate Resource Allocation:", - String.format("%d MB-seconds, %d vcore-seconds", usageReport == null - ? 0 : usageReport.getMemorySeconds(), usageReport == null ? 0 - : usageReport.getVcoreSeconds())); - pdiv._(); + createApplicationMetricsTable(html); html._(InfoBlock.class); @@ -319,49 +288,6 @@ public class AppBlock extends HtmlBlock { ._("var attemptsTableData=" + attemptsTableData)._(); tbody._()._(); - - if (webUiType != null && webUiType.equals(YarnWebParams.RM_WEB_UI)) { - createResourceRequestsTable(html, null); // TODO:YARN-3284 - } - } - - //TODO:YARN-3284 - //The resource requests metrics will be exposed from attemptReport - private void createResourceRequestsTable(Block html, List resouceRequests) { - TBODY> tbody = - html.table("#ResourceRequests").thead().tr() - .th(".priority", "Priority") - .th(".resourceName", "ResourceName") - .th(".totalResource", "Capability") - .th(".numContainers", "NumContainers") - .th(".relaxLocality", "RelaxLocality") - .th(".nodeLabelExpression", "NodeLabelExpression")._()._().tbody(); - - Resource totalResource = Resource.newInstance(0, 0); - if (resouceRequests != null) { - for (ResourceRequest request : resouceRequests) { - if (request.getNumContainers() == 0) { - continue; - } - - tbody.tr() - .td(String.valueOf(request.getPriority())) - .td(request.getResourceName()) - .td(String.valueOf(request.getCapability())) - .td(String.valueOf(request.getNumContainers())) - .td(String.valueOf(request.getRelaxLocality())) - .td(request.getNodeLabelExpression() == null ? "N/A" : request - .getNodeLabelExpression())._(); - if (request.getResourceName().equals(ResourceRequest.ANY)) { - Resources.addTo(totalResource, - Resources.multiply(request.getCapability(), - request.getNumContainers())); - } - } - } - html.div().$class("totalResourceRequests") - .h3("Total Outstanding Resource Requests: " + totalResource)._(); - tbody._()._(); } private String clarifyAppState(YarnApplicationState state) { @@ -389,4 +315,9 @@ public class AppBlock extends HtmlBlock { } return status.toString(); } + + // The preemption metrics only need to be shown in RM WebUI + protected void createApplicationMetricsTable(Block html) { + + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppAttemptPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppAttemptPage.java index 6e4cfade9ff..df5fb9e8a59 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppAttemptPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppAttemptPage.java @@ -23,7 +23,6 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES; import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES_ID; import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID; -import org.apache.hadoop.yarn.server.webapp.AppAttemptBlock; import org.apache.hadoop.yarn.server.webapp.WebPageUtils; import org.apache.hadoop.yarn.webapp.SubView; import org.apache.hadoop.yarn.webapp.YarnWebParams; @@ -51,7 +50,7 @@ public class AppAttemptPage extends RmView { @Override protected Class content() { - return AppAttemptBlock.class; + return RMAppAttemptBlock.class; } } \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppPage.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppPage.java index 9f9b7c969d2..0c5516a304a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppPage.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/AppPage.java @@ -23,7 +23,6 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES; import static org.apache.hadoop.yarn.webapp.view.JQueryUI.DATATABLES_ID; import static org.apache.hadoop.yarn.webapp.view.JQueryUI.initID; -import org.apache.hadoop.yarn.server.webapp.AppBlock; import org.apache.hadoop.yarn.server.webapp.WebPageUtils; import org.apache.hadoop.yarn.webapp.SubView; import org.apache.hadoop.yarn.webapp.YarnWebParams; @@ -50,6 +49,6 @@ public class AppPage extends RmView { @Override protected Class content() { - return AppBlock.class; + return RMAppBlock.class; } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppAttemptBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppAttemptBlock.java new file mode 100644 index 00000000000..419c0ce6753 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppAttemptBlock.java @@ -0,0 +1,177 @@ +/** + * 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.webapp; + +import static org.apache.hadoop.yarn.webapp.view.JQueryUI._EVEN; +import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP; +import static org.apache.hadoop.yarn.webapp.view.JQueryUI._ODD; +import static org.apache.hadoop.yarn.webapp.view.JQueryUI._TH; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.api.records.ResourceRequest; +import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState; +import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptMetrics; +import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; +import org.apache.hadoop.yarn.server.webapp.AppAttemptBlock; +import org.apache.hadoop.yarn.util.resource.Resources; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; +import org.apache.hadoop.yarn.webapp.util.WebAppUtils; +import org.apache.hadoop.yarn.webapp.view.InfoBlock; +import com.google.inject.Inject; + +public class RMAppAttemptBlock extends AppAttemptBlock{ + + private final ResourceManager rm; + protected Configuration conf; + + @Inject + RMAppAttemptBlock(ViewContext ctx, ResourceManager rm, Configuration conf) { + super(rm.getClientRMService(), ctx); + this.rm = rm; + this.conf = conf; + } + + @Override + protected void render(Block html) { + super.render(html); + createContainerLocalityTable(html); + createResourceRequestsTable(html); + } + + private void createResourceRequestsTable(Block html) { + AppInfo app = + new AppInfo(rm, rm.getRMContext().getRMApps() + .get(this.appAttemptId.getApplicationId()), true, + WebAppUtils.getHttpSchemePrefix(conf)); + TBODY> tbody = + html.table("#ResourceRequests").thead().tr() + .th(".priority", "Priority") + .th(".resourceName", "ResourceName") + .th(".totalResource", "Capability") + .th(".numContainers", "NumContainers") + .th(".relaxLocality", "RelaxLocality") + .th(".nodeLabelExpression", "NodeLabelExpression")._()._().tbody(); + + Resource totalResource = Resource.newInstance(0, 0); + if (app.getResourceRequests() != null) { + for (ResourceRequest request : app.getResourceRequests()) { + if (request.getNumContainers() == 0) { + continue; + } + + tbody.tr() + .td(String.valueOf(request.getPriority())) + .td(request.getResourceName()) + .td(String.valueOf(request.getCapability())) + .td(String.valueOf(request.getNumContainers())) + .td(String.valueOf(request.getRelaxLocality())) + .td(request.getNodeLabelExpression() == null ? "N/A" : request + .getNodeLabelExpression())._(); + if (request.getResourceName().equals(ResourceRequest.ANY)) { + Resources.addTo(totalResource, + Resources.multiply(request.getCapability(), + request.getNumContainers())); + } + } + } + html.div().$class("totalResourceRequests") + .h3("Total Outstanding Resource Requests: " + totalResource)._(); + tbody._()._(); + } + + private void createContainerLocalityTable(Block html) { + RMAppAttemptMetrics attemptMetrics = null; + RMAppAttempt attempt = getRMAppAttempt(); + if (attempt != null) { + attemptMetrics = attempt.getRMAppAttemptMetrics(); + } + + if (attemptMetrics == null) { + return; + } + + DIV div = html.div(_INFO_WRAP); + TABLE> table = + div.h3( + "Total Allocated Containers: " + + attemptMetrics.getTotalAllocatedContainers()).h3("Each table cell" + + " represents the number of NodeLocal/RackLocal/OffSwitch containers" + + " satisfied by NodeLocal/RackLocal/OffSwitch resource requests.").table( + "#containerLocality"); + table. + tr(). + th(_TH, ""). + th(_TH, "Node Local Request"). + th(_TH, "Rack Local Request"). + th(_TH, "Off Switch Request"). + _(); + + String[] containersType = + { "Num Node Local Containers (satisfied by)", "Num Rack Local Containers (satisfied by)", + "Num Off Switch Containers (satisfied by)" }; + boolean odd = false; + for (int i = 0; i < attemptMetrics.getLocalityStatistics().length; i++) { + table.tr((odd = !odd) ? _ODD : _EVEN).td(containersType[i]) + .td(String.valueOf(attemptMetrics.getLocalityStatistics()[i][0])) + .td(i == 0 ? "" : String.valueOf(attemptMetrics.getLocalityStatistics()[i][1])) + .td(i <= 1 ? "" : String.valueOf(attemptMetrics.getLocalityStatistics()[i][2]))._(); + } + table._(); + div._(); + } + + private boolean isApplicationInFinalState(YarnApplicationAttemptState state) { + return state == YarnApplicationAttemptState.FINISHED + || state == YarnApplicationAttemptState.FAILED + || state == YarnApplicationAttemptState.KILLED; + } + + @Override + protected void createAttemptHeadRoomTable(Block html) { + RMAppAttempt attempt = getRMAppAttempt(); + if (attempt != null) { + if (!isApplicationInFinalState(YarnApplicationAttemptState + .valueOf(attempt.getAppAttemptState().toString()))) { + DIV pdiv = html._(InfoBlock.class).div(_INFO_WRAP); + info("Application Attempt Overview").clear(); + info("Application Attempt Metrics")._( + "Application Attempt Headroom : ", 0); + pdiv._(); + } + } + } + + private RMAppAttempt getRMAppAttempt() { + ApplicationId appId = this.appAttemptId.getApplicationId(); + RMAppAttempt attempt = null; + RMApp rmApp = rm.getRMContext().getRMApps().get(appId); + if (rmApp != null) { + attempt = rmApp.getAppAttempts().get(appAttemptId); + } + return attempt; + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppBlock.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppBlock.java new file mode 100644 index 00000000000..64c57476f79 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppBlock.java @@ -0,0 +1,94 @@ +/** + * 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.webapp; + +import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.api.records.Resource; +import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptMetrics; +import org.apache.hadoop.yarn.server.webapp.AppBlock; +import org.apache.hadoop.yarn.util.resource.Resources; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; +import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.DIV; +import org.apache.hadoop.yarn.webapp.view.InfoBlock; + +import com.google.inject.Inject; + +public class RMAppBlock extends AppBlock{ + + private final ResourceManager rm; + + @Inject + RMAppBlock(ViewContext ctx, Configuration conf, ResourceManager rm) { + super(rm.getClientRMService(), ctx, conf); + this.rm = rm; + } + + @Override + protected void render(Block html) { + super.render(html); + } + + @Override + protected void createApplicationMetricsTable(Block html){ + RMApp rmApp = this.rm.getRMContext().getRMApps().get(appID); + RMAppMetrics appMetrics = rmApp == null ? null : rmApp.getRMAppMetrics(); + // Get attempt metrics and fields, it is possible currentAttempt of RMApp is + // null. In that case, we will assume resource preempted and number of Non + // AM container preempted on that attempt is 0 + RMAppAttemptMetrics attemptMetrics; + if (rmApp == null || null == rmApp.getCurrentAppAttempt()) { + attemptMetrics = null; + } else { + attemptMetrics = rmApp.getCurrentAppAttempt().getRMAppAttemptMetrics(); + } + Resource attemptResourcePreempted = + attemptMetrics == null ? Resources.none() : attemptMetrics + .getResourcePreempted(); + int attemptNumNonAMContainerPreempted = + attemptMetrics == null ? 0 : attemptMetrics + .getNumNonAMContainersPreempted(); + DIV pdiv = html. + _(InfoBlock.class). + div(_INFO_WRAP); + info("Application Overview").clear(); + info("Application Metrics") + ._("Total Resource Preempted:", + appMetrics == null ? "N/A" : appMetrics.getResourcePreempted()) + ._("Total Number of Non-AM Containers Preempted:", + appMetrics == null ? "N/A" + : appMetrics.getNumNonAMContainersPreempted()) + ._("Total Number of AM Containers Preempted:", + appMetrics == null ? "N/A" + : appMetrics.getNumAMContainersPreempted()) + ._("Resource Preempted from Current Attempt:", + attemptResourcePreempted) + ._("Number of Non-AM Containers Preempted from Current Attempt:", + attemptNumNonAMContainerPreempted) + ._("Aggregate Resource Allocation:", + String.format("%d MB-seconds, %d vcore-seconds", + appMetrics == null ? "N/A" : appMetrics.getMemorySeconds(), + appMetrics == null ? "N/A" : appMetrics.getVcoreSeconds())); + pdiv._(); + } +}