Browse Source

YARN-10792. Set Completed AppAttempt LogsLink to Log Server URL. Contributed by Abhinaba Sarkar

Prabhu Josephraj 3 years ago
parent
commit
9445abb500

+ 21 - 5
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/AppAttemptInfo.java

@@ -23,7 +23,9 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import com.google.gson.Gson;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.yarn.api.records.Container;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttempt;
 import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.RMAppAttemptState;
@@ -31,6 +33,8 @@ import org.apache.hadoop.yarn.server.resourcemanager.scheduler.AbstractYarnSched
 import org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerApplicationAttempt;
 import org.apache.hadoop.yarn.webapp.util.WebAppUtils;
 
+import static org.apache.hadoop.yarn.util.StringHelper.PATH_JOINER;
+
 @XmlRootElement(name = "appAttempt")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class AppAttemptInfo {
@@ -64,15 +68,29 @@ public class AppAttemptInfo {
       this.id = attempt.getAppAttemptId().getAttemptId();
       this.startTime = attempt.getStartTime();
       this.finishedTime = attempt.getFinishTime();
+      this.appAttemptState = attempt.getAppAttemptState();
+      this.appAttemptId = attempt.getAppAttemptId().toString();
       Container masterContainer = attempt.getMasterContainer();
       if (masterContainer != null && hasAccess) {
         this.containerId = masterContainer.getId().toString();
         this.nodeHttpAddress = masterContainer.getNodeHttpAddress();
         this.nodeId = masterContainer.getNodeId().toString();
-        this.logsLink = WebAppUtils.getRunningLogURL(schemePrefix
-            + masterContainer.getNodeHttpAddress(),
-            masterContainer.getId().toString(), user);
 
+        Configuration conf = rm.getRMContext().getYarnConfiguration();
+        String logServerUrl = conf.get(YarnConfiguration.YARN_LOG_SERVER_URL);
+        if ((this.appAttemptState == RMAppAttemptState.FAILED ||
+            this.appAttemptState == RMAppAttemptState.FINISHED ||
+            this.appAttemptState == RMAppAttemptState.KILLED) &&
+            logServerUrl != null) {
+          this.logsLink = PATH_JOINER.join(logServerUrl,
+               masterContainer.getNodeId().toString(),
+               masterContainer.getId().toString(),
+               masterContainer.getId().toString(), user);
+        } else {
+          this.logsLink = WebAppUtils.getRunningLogURL(schemePrefix
+               + masterContainer.getNodeHttpAddress(),
+               masterContainer.getId().toString(), user);
+        }
         Gson gson = new Gson();
         this.exportPorts = gson.toJson(masterContainer.getExposedPorts());
 
@@ -90,8 +108,6 @@ public class AppAttemptInfo {
           }
         }
       }
-      this.appAttemptId = attempt.getAppAttemptId().toString();
-      this.appAttemptState = attempt.getAppAttemptState();
     }
   }
 

+ 40 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesAppAttempts.java

@@ -60,6 +60,7 @@ import java.util.Collection;
 
 import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.assertResponseStatusCode;
 import static org.apache.hadoop.yarn.webapp.WebServicesTestUtils.checkStringMatch;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -124,6 +125,45 @@ public class TestRMWebServicesAppAttempts extends JerseyTestBase {
     rm.stop();
   }
 
+  @Test (timeout = 20000)
+  public void testCompletedAppAttempt() throws Exception {
+    Configuration conf = rm.getConfig();
+    String logServerUrl = "http://localhost:19888/jobhistory/logs";
+    conf.set(YarnConfiguration.YARN_LOG_SERVER_URL, logServerUrl);
+    conf.setInt(YarnConfiguration.RM_AM_MAX_ATTEMPTS, 1);
+    rm.start();
+    MockNM amNodeManager = rm.registerNode("127.0.0.1:1234", 8192);
+    MockRMAppSubmissionData data =
+        MockRMAppSubmissionData.Builder.createWithMemory(CONTAINER_MB, rm)
+        .withAppName("testwordcount")
+        .withUser("user1")
+        .build();
+    RMApp app1 = MockRMAppSubmitter.submit(rm, data);
+    MockAM am = MockRM.launchAndRegisterAM(app1, rm, amNodeManager);
+    // fail the AM by sending CONTAINER_FINISHED event without registering.
+    amNodeManager.nodeHeartbeat(am.getApplicationAttemptId(), 1,
+        ContainerState.COMPLETE);
+    rm.waitForState(am.getApplicationAttemptId(), RMAppAttemptState.FAILED);
+    rm.waitForState(app1.getApplicationId(), RMAppState.FAILED);
+
+    WebResource r = resource();
+    ClientResponse response = r.path("ws").path("v1").path("cluster")
+        .path("apps").path(app1.getApplicationId().toString())
+        .path("appattempts").accept(MediaType.APPLICATION_JSON)
+        .get(ClientResponse.class);
+    JSONObject json = response.getEntity(JSONObject.class);
+    JSONObject jsonAppAttempts = json.getJSONObject("appAttempts");
+    JSONArray jsonArray = jsonAppAttempts.getJSONArray("appAttempt");
+    JSONObject info = jsonArray.getJSONObject(0);
+    String logsLink = info.getString("logsLink");
+    String containerId = app1.getCurrentAppAttempt().getMasterContainer()
+        .getId().toString();
+    assertThat(logsLink).isEqualTo(logServerUrl
+        + "/127.0.0.1:1234/" + containerId + "/" + containerId + "/"
+        + "user1");
+    rm.stop();
+  }
+
   @Test (timeout = 20000)
   public void testMultipleAppAttempts() throws Exception {
     rm.start();