1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.mapreduce.v2.hs.webapp; 20 21 import static org.apache.hadoop.mapreduce.v2.app.webapp.AMParams.TASK_TYPE; 22 23 import org.apache.hadoop.mapreduce.v2.api.records.TaskType; 24 import org.apache.hadoop.mapreduce.v2.app.job.Task; 25 import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt; 26 import org.apache.hadoop.mapreduce.v2.app.webapp.App; 27 import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ReduceTaskAttemptInfo; 28 import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptInfo; 29 import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskInfo; 30 import org.apache.hadoop.mapreduce.v2.util.MRApps; 31 import org.apache.hadoop.util.StringUtils; 32 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; 33 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; 34 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; 35 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TFOOT; 36 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.THEAD; 37 import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TR; 38 import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.InputType; 39 import org.apache.hadoop.yarn.webapp.view.HtmlBlock; 40 41 import com.google.inject.Inject; 42 43 /** 44 * Render the a table of tasks for a given type. 45 */ 46 public class HsTasksBlock extends HtmlBlock { 47 final App app; 48 HsTasksBlock(App app)49 @Inject HsTasksBlock(App app) { 50 this.app = app; 51 } 52 53 /* 54 * (non-Javadoc) 55 * @see org.apache.hadoop.yarn.webapp.view.HtmlBlock#render(org.apache.hadoop.yarn.webapp.view.HtmlBlock.Block) 56 */ render(Block html)57 @Override protected void render(Block html) { 58 if (app.getJob() == null) { 59 html. 60 h2($(TITLE)); 61 return; 62 } 63 TaskType type = null; 64 String symbol = $(TASK_TYPE); 65 if (!symbol.isEmpty()) { 66 type = MRApps.taskType(symbol); 67 } 68 THEAD<TABLE<Hamlet>> thead; 69 if(type != null) 70 thead = html.table("#"+app.getJob().getID() 71 + type).$class("dt-tasks").thead(); 72 else 73 thead = html.table("#tasks").thead(); 74 //Create the spanning row 75 int attemptColSpan = type == TaskType.REDUCE ? 8 : 3; 76 thead.tr(). 77 th().$colspan(5).$class("ui-state-default")._("Task")._(). 78 th().$colspan(attemptColSpan).$class("ui-state-default"). 79 _("Successful Attempt")._(). 80 _(); 81 82 TR<THEAD<TABLE<Hamlet>>> theadRow = thead. 83 tr(). 84 th("Name"). 85 th("State"). 86 th("Start Time"). 87 th("Finish Time"). 88 th("Elapsed Time"). 89 th("Start Time"); //Attempt 90 91 if(type == TaskType.REDUCE) { 92 theadRow.th("Shuffle Finish Time"); //Attempt 93 theadRow.th("Merge Finish Time"); //Attempt 94 } 95 96 theadRow.th("Finish Time"); //Attempt 97 98 if(type == TaskType.REDUCE) { 99 theadRow.th("Elapsed Time Shuffle"); //Attempt 100 theadRow.th("Elapsed Time Merge"); //Attempt 101 theadRow.th("Elapsed Time Reduce"); //Attempt 102 } 103 theadRow.th("Elapsed Time"); //Attempt 104 105 TBODY<TABLE<Hamlet>> tbody = theadRow._()._().tbody(); 106 107 // Write all the data into a JavaScript array of arrays for JQuery 108 // DataTables to display 109 StringBuilder tasksTableData = new StringBuilder("[\n"); 110 for (Task task : app.getJob().getTasks().values()) { 111 if (type != null && task.getType() != type) { 112 continue; 113 } 114 TaskInfo info = new TaskInfo(task); 115 String tid = info.getId(); 116 117 long startTime = info.getStartTime(); 118 long finishTime = info.getFinishTime(); 119 long elapsed = info.getElapsedTime(); 120 121 long attemptStartTime = -1; 122 long shuffleFinishTime = -1; 123 long sortFinishTime = -1; 124 long attemptFinishTime = -1; 125 long elapsedShuffleTime = -1; 126 long elapsedSortTime = -1;; 127 long elapsedReduceTime = -1; 128 long attemptElapsed = -1; 129 TaskAttempt successful = info.getSuccessful(); 130 if(successful != null) { 131 TaskAttemptInfo ta; 132 if(type == TaskType.REDUCE) { 133 ReduceTaskAttemptInfo rta = new ReduceTaskAttemptInfo(successful, type); 134 shuffleFinishTime = rta.getShuffleFinishTime(); 135 sortFinishTime = rta.getMergeFinishTime(); 136 elapsedShuffleTime = rta.getElapsedShuffleTime(); 137 elapsedSortTime = rta.getElapsedMergeTime(); 138 elapsedReduceTime = rta.getElapsedReduceTime(); 139 ta = rta; 140 } else { 141 ta = new TaskAttemptInfo(successful, type, false); 142 } 143 attemptStartTime = ta.getStartTime(); 144 attemptFinishTime = ta.getFinishTime(); 145 attemptElapsed = ta.getElapsedTime(); 146 } 147 148 tasksTableData.append("[\"") 149 .append("<a href='" + url("task", tid)).append("'>") 150 .append(tid).append("</a>\",\"") 151 .append(info.getState()).append("\",\"") 152 .append(startTime).append("\",\"") 153 .append(finishTime).append("\",\"") 154 .append(elapsed).append("\",\"") 155 .append(attemptStartTime).append("\",\""); 156 157 if(type == TaskType.REDUCE) { 158 tasksTableData.append(shuffleFinishTime).append("\",\"") 159 .append(sortFinishTime).append("\",\""); 160 } 161 tasksTableData.append(attemptFinishTime).append("\",\""); 162 if(type == TaskType.REDUCE) { 163 tasksTableData.append(elapsedShuffleTime).append("\",\"") 164 .append(elapsedSortTime).append("\",\"") 165 .append(elapsedReduceTime).append("\",\""); 166 } 167 tasksTableData.append(attemptElapsed).append("\"],\n"); 168 } 169 //Remove the last comma and close off the array of arrays 170 if(tasksTableData.charAt(tasksTableData.length() - 2) == ',') { 171 tasksTableData.delete( 172 tasksTableData.length()-2, tasksTableData.length()-1); 173 } 174 tasksTableData.append("]"); 175 html.script().$type("text/javascript"). 176 _("var tasksTableData=" + tasksTableData)._(); 177 178 TR<TFOOT<TABLE<Hamlet>>> footRow = tbody._().tfoot().tr(); 179 footRow.th().input("search_init").$type(InputType.text).$name("task") 180 .$value("ID")._()._().th().input("search_init").$type(InputType.text) 181 .$name("state").$value("State")._()._().th().input("search_init") 182 .$type(InputType.text).$name("start_time").$value("Start Time")._()._() 183 .th().input("search_init").$type(InputType.text).$name("finish_time") 184 .$value("Finish Time")._()._().th().input("search_init") 185 .$type(InputType.text).$name("elapsed_time").$value("Elapsed Time")._() 186 ._().th().input("search_init").$type(InputType.text) 187 .$name("attempt_start_time").$value("Start Time")._()._(); 188 189 if(type == TaskType.REDUCE) { 190 footRow.th().input("search_init").$type(InputType.text) 191 .$name("shuffle_time").$value("Shuffle Time")._()._(); 192 footRow.th().input("search_init").$type(InputType.text) 193 .$name("merge_time").$value("Merge Time")._()._(); 194 } 195 196 footRow.th().input("search_init").$type(InputType.text) 197 .$name("attempt_finish").$value("Finish Time")._()._(); 198 199 if(type == TaskType.REDUCE) { 200 footRow.th().input("search_init").$type(InputType.text) 201 .$name("elapsed_shuffle_time").$value("Elapsed Shuffle Time")._()._(); 202 footRow.th().input("search_init").$type(InputType.text) 203 .$name("elapsed_merge_time").$value("Elapsed Merge Time")._()._(); 204 footRow.th().input("search_init").$type(InputType.text) 205 .$name("elapsed_reduce_time").$value("Elapsed Reduce Time")._()._(); 206 } 207 208 footRow.th().input("search_init").$type(InputType.text) 209 .$name("attempt_elapsed").$value("Elapsed Time")._()._(); 210 211 footRow._()._()._(); 212 } 213 } 214