Browse Source

YARN-3544. Got back AM logs link on the RM web UI for a completed app. Contributed by Xuan Gong.

Zhijie Shen 10 years ago
parent
commit
04dd05989e

+ 3 - 0
hadoop-yarn-project/CHANGES.txt

@@ -47,6 +47,9 @@ Release 2.7.1 - UNRELEASED
     YARN-3485. FairScheduler headroom calculation doesn't consider 
     YARN-3485. FairScheduler headroom calculation doesn't consider 
     maxResources for Fifo and FairShare policies. (kasha)
     maxResources for Fifo and FairShare policies. (kasha)
 
 
+    YARN-3544. Got back AM logs link on the RM web UI for a completed app.
+    (Xuan Gong via zjshen)
+
 Release 2.7.0 - 2015-04-20
 Release 2.7.0 - 2015-04-20
 
 
   INCOMPATIBLE CHANGES
   INCOMPATIBLE CHANGES

+ 7 - 1
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/java/org/apache/hadoop/yarn/server/webapp/AppBlock.java

@@ -62,6 +62,7 @@ public class AppBlock extends HtmlBlock {
   protected ApplicationBaseProtocol appBaseProt;
   protected ApplicationBaseProtocol appBaseProt;
   protected Configuration conf;
   protected Configuration conf;
   protected ApplicationId appID = null;
   protected ApplicationId appID = null;
+  protected UserGroupInformation callerUGI;
 
 
   @Inject
   @Inject
   protected AppBlock(ApplicationBaseProtocol appBaseProt, ViewContext ctx,
   protected AppBlock(ApplicationBaseProtocol appBaseProt, ViewContext ctx,
@@ -87,7 +88,7 @@ public class AppBlock extends HtmlBlock {
       return;
       return;
     }
     }
 
 
-    UserGroupInformation callerUGI = getCallerUGI();
+    callerUGI = getCallerUGI();
     ApplicationReport appReport = null;
     ApplicationReport appReport = null;
     try {
     try {
       final GetApplicationReportRequest request =
       final GetApplicationReportRequest request =
@@ -211,6 +212,11 @@ public class AppBlock extends HtmlBlock {
     html._(InfoBlock.class);
     html._(InfoBlock.class);
 
 
     // Application Attempt Table
     // Application Attempt Table
+    createApplicationAttemptTable(html, attempts);
+  }
+
+  protected void createApplicationAttemptTable(Block html,
+      Collection<ApplicationAttemptReport> attempts) {
     TBODY<TABLE<Hamlet>> tbody =
     TBODY<TABLE<Hamlet>> tbody =
         html.table("#attempts").thead().tr().th(".id", "Attempt ID")
         html.table("#attempts").thead().tr().th(".id", "Attempt ID")
           .th(".started", "Started").th(".node", "Node").th(".logs", "Logs")
           .th(".started", "Started").th(".node", "Node").th(".logs", "Logs")

+ 64 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMAppBlock.java

@@ -20,16 +20,25 @@ package org.apache.hadoop.yarn.server.resourcemanager.webapp;
 
 
 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP;
 import static org.apache.hadoop.yarn.webapp.view.JQueryUI._INFO_WRAP;
 
 
+import java.util.Collection;
+
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport;
 import org.apache.hadoop.yarn.api.records.Resource;
 import org.apache.hadoop.yarn.api.records.Resource;
 import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
 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.RMApp;
 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics;
 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppMetrics;
+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.rmapp.attempt.RMAppAttemptMetrics;
+import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppAttemptInfo;
 import org.apache.hadoop.yarn.server.webapp.AppBlock;
 import org.apache.hadoop.yarn.server.webapp.AppBlock;
 import org.apache.hadoop.yarn.util.resource.Resources;
 import org.apache.hadoop.yarn.util.resource.Resources;
 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
 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.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 org.apache.hadoop.yarn.webapp.view.InfoBlock;
 
 
 import com.google.inject.Inject;
 import com.google.inject.Inject;
@@ -37,11 +46,13 @@ import com.google.inject.Inject;
 public class RMAppBlock extends AppBlock{
 public class RMAppBlock extends AppBlock{
 
 
   private final ResourceManager rm;
   private final ResourceManager rm;
+  private final Configuration conf;
 
 
   @Inject
   @Inject
   RMAppBlock(ViewContext ctx, Configuration conf, ResourceManager rm) {
   RMAppBlock(ViewContext ctx, Configuration conf, ResourceManager rm) {
     super(rm.getClientRMService(), ctx, conf);
     super(rm.getClientRMService(), ctx, conf);
     this.rm = rm;
     this.rm = rm;
+    this.conf = conf;
   }
   }
 
 
   @Override
   @Override
@@ -91,4 +102,57 @@ public class RMAppBlock extends AppBlock{
               appMetrics == null ? "N/A" : appMetrics.getVcoreSeconds()));
               appMetrics == null ? "N/A" : appMetrics.getVcoreSeconds()));
     pdiv._();
     pdiv._();
   }
   }
+
+  @Override
+  protected void createApplicationAttemptTable(Block html,
+      Collection<ApplicationAttemptReport> attempts) {
+    TBODY<TABLE<Hamlet>> tbody =
+        html.table("#attempts").thead().tr().th(".id", "Attempt ID")
+          .th(".started", "Started").th(".node", "Node").th(".logs", "Logs")
+          ._()._().tbody();
+    RMApp rmApp = this.rm.getRMContext().getRMApps().get(this.appID);
+    if (rmApp == null) {
+      return;
+    }
+    StringBuilder attemptsTableData = new StringBuilder("[\n");
+    for (final ApplicationAttemptReport appAttemptReport : attempts) {
+      RMAppAttempt rmAppAttempt =
+          rmApp.getRMAppAttempt(appAttemptReport.getApplicationAttemptId());
+      if (rmAppAttempt == null) {
+        continue;
+      }
+      AppAttemptInfo attemptInfo =
+          new AppAttemptInfo(rmAppAttempt, rmApp.getUser());
+      String nodeLink = attemptInfo.getNodeHttpAddress();
+      if (nodeLink != null) {
+        nodeLink = WebAppUtils.getHttpSchemePrefix(conf) + nodeLink;
+      }
+      String logsLink = attemptInfo.getLogsLink();
+      attemptsTableData
+        .append("[\"<a href='")
+        .append(url("appattempt", rmAppAttempt.getAppAttemptId().toString()))
+        .append("'>")
+        .append(String.valueOf(rmAppAttempt.getAppAttemptId()))
+        .append("</a>\",\"")
+        .append(attemptInfo.getStartTime())
+        .append("\",\"<a ")
+        .append(nodeLink == null ? "#" : "href='" + nodeLink)
+        .append("'>")
+        .append(
+          nodeLink == null ? "N/A" : StringEscapeUtils
+            .escapeJavaScript(StringEscapeUtils.escapeHtml(nodeLink)))
+        .append("</a>\",\"<a ")
+        .append(logsLink == null ? "#" : "href='" + logsLink).append("'>")
+        .append(logsLink == null ? "N/A" : "Logs").append("</a>\"],\n");
+    }
+    if (attemptsTableData.charAt(attemptsTableData.length() - 2) == ',') {
+      attemptsTableData.delete(attemptsTableData.length() - 2,
+        attemptsTableData.length() - 1);
+    }
+    attemptsTableData.append("]");
+    html.script().$type("text/javascript")
+      ._("var attemptsTableData=" + attemptsTableData)._();
+
+    tbody._()._();
+  }
 }
 }