浏览代码

MAPREDUCE-6297. Task Id of the failed task in diagnostics should link to the task page. (Siqi Li via gera)

(cherry picked from commit 89ded89e86e5d9a634d92a5d8a7c889744d97f94)
Gera Shegalov 10 年之前
父节点
当前提交
6f06e3b7ea

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

@@ -95,6 +95,9 @@ Release 2.8.0 - UNRELEASED
     MAPREDUCE-6293. Set job classloader on uber-job's LocalContainerLauncher
     MAPREDUCE-6293. Set job classloader on uber-job's LocalContainerLauncher
     event thread. (Sangjin Lee via gera)
     event thread. (Sangjin Lee via gera)
 
 
+    MAPREDUCE-6297. Task Id of the failed task in diagnostics should link to
+    the task page. (Siqi Li via gera)
+
 Release 2.7.1 - UNRELEASED
 Release 2.7.1 - UNRELEASED
 
 
   INCOMPATIBLE CHANGES
   INCOMPATIBLE CHANGES

+ 13 - 22
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/TaskID.java

@@ -25,6 +25,8 @@ import java.text.NumberFormat;
 import java.util.EnumMap;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.classification.InterfaceStability;
@@ -58,6 +60,9 @@ import org.apache.hadoop.io.WritableUtils;
 public class TaskID extends org.apache.hadoop.mapred.ID {
 public class TaskID extends org.apache.hadoop.mapred.ID {
   protected static final String TASK = "task";
   protected static final String TASK = "task";
   protected static final NumberFormat idFormat = NumberFormat.getInstance();
   protected static final NumberFormat idFormat = NumberFormat.getInstance();
+  public static final String TASK_ID_REGEX = TASK + "_(\\d+)_(\\d+)_" +
+      CharTaskTypeMaps.allTaskTypes + "_(\\d+)";
+  public static final Pattern taskIdPattern = Pattern.compile(TASK_ID_REGEX);
   static {
   static {
     idFormat.setGroupingUsed(false);
     idFormat.setGroupingUsed(false);
     idFormat.setMinimumIntegerDigits(6);
     idFormat.setMinimumIntegerDigits(6);
@@ -207,29 +212,15 @@ public class TaskID extends org.apache.hadoop.mapred.ID {
     throws IllegalArgumentException {
     throws IllegalArgumentException {
     if(str == null)
     if(str == null)
       return null;
       return null;
-    String exceptionMsg = null;
-    try {
-      String[] parts = str.split("_");
-      if(parts.length == 5) {
-        if(parts[0].equals(TASK)) {
-          String type = parts[3];
-          TaskType t = CharTaskTypeMaps.getTaskType(type.charAt(0));
-          if(t != null) {
-          
-            return new org.apache.hadoop.mapred.TaskID(parts[1], 
-                                                     Integer.parseInt(parts[2]),
-                                                     t, 
-                                                     Integer.parseInt(parts[4]));
-          } else
-            exceptionMsg = "Bad TaskType identifier. TaskId string : " + str
-                + " is not properly formed.";
-        }
-      }
-    }catch (Exception ex) {//fall below
-    }
-    if (exceptionMsg == null) {
-      exceptionMsg = "TaskId string : " + str + " is not properly formed";
+    Matcher m = taskIdPattern.matcher(str);
+    if (m.matches()) {
+      return new org.apache.hadoop.mapred.TaskID(m.group(1),
+          Integer.parseInt(m.group(2)),
+          CharTaskTypeMaps.getTaskType(m.group(3).charAt(0)),
+          Integer.parseInt(m.group(4)));
     }
     }
+    String exceptionMsg = "TaskId string : " + str + " is not properly formed" +
+        "\nReason: " + m.toString();
     throw new IllegalArgumentException(exceptionMsg);
     throw new IllegalArgumentException(exceptionMsg);
   }
   }
   /**
   /**

+ 7 - 1
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/main/java/org/apache/hadoop/mapreduce/v2/hs/webapp/HsJobBlock.java

@@ -27,6 +27,7 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI._TH;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 
 
+import org.apache.hadoop.mapreduce.TaskID;
 import org.apache.hadoop.mapreduce.v2.api.records.AMInfo;
 import org.apache.hadoop.mapreduce.v2.api.records.AMInfo;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
 import org.apache.hadoop.mapreduce.v2.app.AppContext;
@@ -98,7 +99,7 @@ public class HsJobBlock extends HtmlBlock {
     if(diagnostics != null && !diagnostics.isEmpty()) {
     if(diagnostics != null && !diagnostics.isEmpty()) {
       StringBuffer b = new StringBuffer();
       StringBuffer b = new StringBuffer();
       for(String diag: diagnostics) {
       for(String diag: diagnostics) {
-        b.append(diag);
+        b.append(addTaskLinks(diag));
       }
       }
       infoBlock._("Diagnostics:", b.toString());
       infoBlock._("Diagnostics:", b.toString());
     }
     }
@@ -203,4 +204,9 @@ public class HsJobBlock extends HtmlBlock {
        _().
        _().
      _();
      _();
   }
   }
+
+  static String addTaskLinks(String text) {
+    return TaskID.taskIdPattern.matcher(text).replaceAll(
+        "<a href=\"/jobhistory/task/$0\">$0</a>");
+  }
 }
 }

+ 19 - 1
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestBlocks.java

@@ -65,6 +65,7 @@ import org.apache.hadoop.yarn.webapp.log.AggregatedLogsPage;
 import org.apache.hadoop.yarn.webapp.view.BlockForTest;
 import org.apache.hadoop.yarn.webapp.view.BlockForTest;
 import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
 import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
 import org.apache.hadoop.yarn.webapp.view.HtmlBlock.Block;
 import org.apache.hadoop.yarn.webapp.view.HtmlBlock.Block;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.Test;
 
 
 import static org.junit.Assert.*;
 import static org.junit.Assert.*;
@@ -78,6 +79,23 @@ import static org.mockito.Mockito.*;
 public class TestBlocks {
 public class TestBlocks {
   private ByteArrayOutputStream data = new ByteArrayOutputStream();
   private ByteArrayOutputStream data = new ByteArrayOutputStream();
 
 
+  @Test
+  public void testPullTaskLink(){
+    Task task = getTask(0);
+    String taskId = task.getID().toString();
+
+    Assert.assertEquals("pull links doesn't work correctly",
+        "Task failed <a href=\"/jobhistory/task/" + taskId + "\">" +
+        taskId + "</a>"
+        , HsJobBlock.addTaskLinks("Task failed " + taskId));
+
+    Assert.assertEquals("pull links doesn't work correctly",
+        "Task failed <a href=\"/jobhistory/task/" + taskId + "\">" +
+        taskId + "</a>\n Job failed as tasks failed. failedMaps:1 failedReduces:0"
+        , HsJobBlock.addTaskLinks("Task failed " + taskId + "\n " +
+        "Job failed as tasks failed. failedMaps:1 failedReduces:0"));
+  }
+
   /**
   /**
    * test HsTasksBlock's rendering.
    * test HsTasksBlock's rendering.
    */
    */
@@ -241,7 +259,7 @@ public class TestBlocks {
     assertEquals(HsAttemptsPage.class, controller.attemptsPage());
     assertEquals(HsAttemptsPage.class, controller.attemptsPage());
 
 
     controller.set(AMParams.JOB_ID, "job_01_01");
     controller.set(AMParams.JOB_ID, "job_01_01");
-    controller.set(AMParams.TASK_ID, "task_01_01_m01_01");
+    controller.set(AMParams.TASK_ID, "task_01_01_m_01");
     controller.set(AMParams.TASK_TYPE, "m");
     controller.set(AMParams.TASK_TYPE, "m");
     controller.set(AMParams.ATTEMPT_STATE, "State");
     controller.set(AMParams.ATTEMPT_STATE, "State");
 
 

+ 18 - 9
hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-hs/src/test/java/org/apache/hadoop/mapreduce/v2/hs/webapp/TestHsWebServicesTasks.java

@@ -33,6 +33,7 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.DocumentBuilderFactory;
 
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.mapreduce.TaskID;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
 import org.apache.hadoop.mapreduce.v2.api.records.TaskId;
 import org.apache.hadoop.mapreduce.v2.api.records.TaskId;
 import org.apache.hadoop.mapreduce.v2.api.records.TaskReport;
 import org.apache.hadoop.mapreduce.v2.api.records.TaskReport;
@@ -368,9 +369,11 @@ public class TestHsWebServicesTasks extends JerseyTest {
         String message = exception.getString("message");
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         String classname = exception.getString("javaClassName");
-        WebServicesTestUtils.checkStringMatch("exception message",
+        WebServicesTestUtils.checkStringEqual("exception message",
             "java.lang.Exception: TaskId string : "
             "java.lang.Exception: TaskId string : "
-                + "bogustaskid is not properly formed", message);
+                + "bogustaskid is not properly formed"
+                + "\nReason: java.util.regex.Matcher[pattern=" +
+                TaskID.TASK_ID_REGEX + " region=0,11 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -432,9 +435,11 @@ public class TestHsWebServicesTasks extends JerseyTest {
         String message = exception.getString("message");
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         String classname = exception.getString("javaClassName");
-        WebServicesTestUtils.checkStringMatch("exception message",
-            "java.lang.Exception: Bad TaskType identifier. TaskId string : "
-                + "task_0_0000_d_000000 is not properly formed.", message);
+        WebServicesTestUtils.checkStringEqual("exception message",
+            "java.lang.Exception: TaskId string : "
+                + "task_0_0000_d_000000 is not properly formed" +
+                "\nReason: java.util.regex.Matcher[pattern=" +
+                TaskID.TASK_ID_REGEX + " region=0,20 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -464,9 +469,11 @@ public class TestHsWebServicesTasks extends JerseyTest {
         String message = exception.getString("message");
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         String classname = exception.getString("javaClassName");
-        WebServicesTestUtils.checkStringMatch("exception message",
+        WebServicesTestUtils.checkStringEqual("exception message",
             "java.lang.Exception: TaskId string : "
             "java.lang.Exception: TaskId string : "
-                + "task_0000_m_000000 is not properly formed", message);
+                + "task_0000_m_000000 is not properly formed" +
+                "\nReason: java.util.regex.Matcher[pattern=" +
+                TaskID.TASK_ID_REGEX + " region=0,18 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
         WebServicesTestUtils.checkStringMatch("exception classname",
@@ -496,9 +503,11 @@ public class TestHsWebServicesTasks extends JerseyTest {
         String message = exception.getString("message");
         String message = exception.getString("message");
         String type = exception.getString("exception");
         String type = exception.getString("exception");
         String classname = exception.getString("javaClassName");
         String classname = exception.getString("javaClassName");
-        WebServicesTestUtils.checkStringMatch("exception message",
+        WebServicesTestUtils.checkStringEqual("exception message",
             "java.lang.Exception: TaskId string : "
             "java.lang.Exception: TaskId string : "
-                + "task_0_0000_m is not properly formed", message);
+                + "task_0_0000_m is not properly formed" +
+                "\nReason: java.util.regex.Matcher[pattern=" +
+                TaskID.TASK_ID_REGEX + " region=0,13 lastmatch=]", message);
         WebServicesTestUtils.checkStringMatch("exception type",
         WebServicesTestUtils.checkStringMatch("exception type",
             "NotFoundException", type);
             "NotFoundException", type);
         WebServicesTestUtils.checkStringMatch("exception classname",
         WebServicesTestUtils.checkStringMatch("exception classname",