/** * 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.mapreduce.v2.hs.webapp; import static org.apache.hadoop.mapreduce.v2.app.webapp.AMParams.TASK_TYPE; import org.apache.hadoop.mapreduce.v2.api.records.TaskType; import org.apache.hadoop.mapreduce.v2.app.job.Task; import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt; import org.apache.hadoop.mapreduce.v2.app.webapp.App; import org.apache.hadoop.mapreduce.v2.app.webapp.dao.ReduceTaskAttemptInfo; import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptInfo; import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskInfo; import org.apache.hadoop.mapreduce.v2.util.MRApps; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.util.Times; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TABLE; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TFOOT; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.THEAD; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TR; import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.InputType; import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import com.google.inject.Inject; /** * Render the a table of tasks for a given type. */ public class HsTasksBlock extends HtmlBlock { final App app; @Inject HsTasksBlock(App app) { this.app = app; } /* * (non-Javadoc) * @see org.apache.hadoop.yarn.webapp.view.HtmlBlock#render(org.apache.hadoop.yarn.webapp.view.HtmlBlock.Block) */ @Override protected void render(Block html) { if (app.getJob() == null) { html. h2($(TITLE)); return; } TaskType type = null; String symbol = $(TASK_TYPE); if (!symbol.isEmpty()) { type = MRApps.taskType(symbol); } THEAD<TABLE<Hamlet>> thead = html.table("#tasks").thead(); //Create the spanning row int attemptColSpan = type == TaskType.REDUCE ? 8 : 3; thead.tr(). th().$colspan(5).$class("ui-state-default")._("Task")._(). th().$colspan(attemptColSpan).$class("ui-state-default"). _("Successful Attempt")._(). _(); TR<THEAD<TABLE<Hamlet>>> theadRow = thead. tr(). th("Name"). th("State"). th("Start Time"). th("Finish Time"). th("Elapsed Time"). th("Start Time"); //Attempt if(type == TaskType.REDUCE) { theadRow.th("Shuffle Finish Time"); //Attempt theadRow.th("Merge Finish Time"); //Attempt } theadRow.th("Finish Time"); //Attempt if(type == TaskType.REDUCE) { theadRow.th("Elapsed Time Shuffle"); //Attempt theadRow.th("Elapsed Time Merge"); //Attempt theadRow.th("Elapsed Time Reduce"); //Attempt } theadRow.th("Elapsed Time"); //Attempt TBODY<TABLE<Hamlet>> tbody = theadRow._()._().tbody(); for (Task task : app.getJob().getTasks().values()) { if (type != null && task.getType() != type) { continue; } TaskInfo info = new TaskInfo(task); String tid = info.getId(); long startTime = info.getStartTime(); long finishTime = info.getFinishTime(); long elapsed = info.getElapsedTime(); long attemptStartTime = -1; long shuffleFinishTime = -1; long sortFinishTime = -1; long attemptFinishTime = -1; long elapsedShuffleTime = -1; long elapsedSortTime = -1;; long elapsedReduceTime = -1; long attemptElapsed = -1; TaskAttempt successful = info.getSuccessful(); if(successful != null) { TaskAttemptInfo ta; if(type == TaskType.REDUCE) { ReduceTaskAttemptInfo rta = new ReduceTaskAttemptInfo(successful, type); shuffleFinishTime = rta.getShuffleFinishTime(); sortFinishTime = rta.getMergeFinishTime(); elapsedShuffleTime = rta.getElapsedShuffleTime(); elapsedSortTime = rta.getElapsedMergeTime(); elapsedReduceTime = rta.getElapsedReduceTime(); ta = rta; } else { ta = new TaskAttemptInfo(successful, type, false); } attemptStartTime = ta.getStartTime(); attemptFinishTime = ta.getFinishTime(); attemptElapsed = ta.getElapsedTime(); } TR<TBODY<TABLE<Hamlet>>> row = tbody.tr(); row. td(). br().$title(String.valueOf(info.getTaskNum()))._(). // sorting a(url("task", tid), tid)._(). td(info.getState()). td(). br().$title(String.valueOf(startTime))._(). _(Times.format(startTime))._(). td(). br().$title(String.valueOf(finishTime))._(). _(Times.format(finishTime))._(). td(). br().$title(String.valueOf(elapsed))._(). _(formatTime(elapsed))._(). td(). br().$title(String.valueOf(attemptStartTime))._(). _(Times.format(attemptStartTime))._(); if(type == TaskType.REDUCE) { row.td(). br().$title(String.valueOf(shuffleFinishTime))._(). _(Times.format(shuffleFinishTime))._(); row.td(). br().$title(String.valueOf(sortFinishTime))._(). _(Times.format(sortFinishTime))._(); } row. td(). br().$title(String.valueOf(attemptFinishTime))._(). _(Times.format(attemptFinishTime))._(); if(type == TaskType.REDUCE) { row.td(). br().$title(String.valueOf(elapsedShuffleTime))._(). _(formatTime(elapsedShuffleTime))._(); row.td(). br().$title(String.valueOf(elapsedSortTime))._(). _(formatTime(elapsedSortTime))._(); row.td(). br().$title(String.valueOf(elapsedReduceTime))._(). _(formatTime(elapsedReduceTime))._(); } row.td(). br().$title(String.valueOf(attemptElapsed))._(). _(formatTime(attemptElapsed))._(); row._(); } TR<TFOOT<TABLE<Hamlet>>> footRow = tbody._().tfoot().tr(); footRow.th().input("search_init").$type(InputType.text).$name("task") .$value("ID")._()._().th().input("search_init").$type(InputType.text) .$name("state").$value("State")._()._().th().input("search_init") .$type(InputType.text).$name("start_time").$value("Start Time")._()._() .th().input("search_init").$type(InputType.text).$name("finish_time") .$value("Finish Time")._()._().th().input("search_init") .$type(InputType.text).$name("elapsed_time").$value("Elapsed Time")._() ._().th().input("search_init").$type(InputType.text) .$name("attempt_start_time").$value("Start Time")._()._(); if(type == TaskType.REDUCE) { footRow.th().input("search_init").$type(InputType.text) .$name("shuffle_time").$value("Shuffle Time")._()._(); footRow.th().input("search_init").$type(InputType.text) .$name("merge_time").$value("Merge Time")._()._(); } footRow.th().input("search_init").$type(InputType.text) .$name("attempt_finish").$value("Finish Time")._()._(); if(type == TaskType.REDUCE) { footRow.th().input("search_init").$type(InputType.text) .$name("elapsed_shuffle_time").$value("Elapsed Shuffle Time")._()._(); footRow.th().input("search_init").$type(InputType.text) .$name("elapsed_merge_time").$value("Elapsed Merge Time")._()._(); footRow.th().input("search_init").$type(InputType.text) .$name("elapsed_reduce_time").$value("Elapsed Reduce Time")._()._(); } footRow.th().input("search_init").$type(InputType.text) .$name("attempt_elapsed").$value("Elapsed Time")._()._(); footRow._()._()._(); } private String formatTime(long elapsed) { return elapsed < 0 ? "N/A" : StringUtils.formatTime(elapsed); } }