MAPREDUCE-6316. Task Attempt List entries should link to the task overview. (Siqi Li via gera)
This commit is contained in:
parent
bcb3c40bed
commit
63d40d5286
@ -352,6 +352,9 @@ Release 2.8.0 - UNRELEASED
|
||||
MAPREDUCE-6395. Improve the commit failure messages in MRAppMaster recovery.
|
||||
(Brahma Reddy Battula via gera)
|
||||
|
||||
MAPREDUCE-6316. Task Attempt List entries should link to the task overview.
|
||||
(Siqi Li via gera)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
BUG FIXES
|
||||
|
@ -29,9 +29,11 @@
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptId;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptState;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskId;
|
||||
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.dao.TaskAttemptInfo;
|
||||
import org.apache.hadoop.mapreduce.v2.util.MRApps;
|
||||
import org.apache.hadoop.mapreduce.v2.util.MRApps.TaskAttemptStateUI;
|
||||
import org.apache.hadoop.yarn.webapp.SubView;
|
||||
@ -50,6 +52,12 @@ protected boolean isValidRequest() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAttemptId(TaskId taskId, TaskAttemptInfo ta) {
|
||||
return "<a href='" + url("task", taskId.toString()) +
|
||||
"'>" + ta.getId() + "</a>";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<TaskAttempt> getTaskAttempts() {
|
||||
List<TaskAttempt> fewTaskAttemps = new ArrayList<TaskAttempt>();
|
||||
|
@ -32,6 +32,7 @@
|
||||
import org.apache.hadoop.mapreduce.MRConfig;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.JobId;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptState;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskId;
|
||||
import org.apache.hadoop.mapreduce.v2.app.job.TaskAttempt;
|
||||
import org.apache.hadoop.mapreduce.v2.app.webapp.dao.TaskAttemptInfo;
|
||||
import org.apache.hadoop.mapreduce.v2.util.MRWebAppUtil;
|
||||
@ -128,8 +129,9 @@ protected void render(Block html) {
|
||||
|
||||
String nodeHttpAddr = ta.getNode();
|
||||
String diag = ta.getNote() == null ? "" : ta.getNote();
|
||||
TaskId taskId = attempt.getID().getTaskId();
|
||||
attemptsTableData.append("[\"")
|
||||
.append(ta.getId()).append("\",\"")
|
||||
.append(getAttemptId(taskId, ta)).append("\",\"")
|
||||
.append(progress).append("\",\"")
|
||||
.append(ta.getState().toString()).append("\",\"")
|
||||
.append(StringEscapeUtils.escapeJavaScript(
|
||||
@ -182,6 +184,10 @@ protected void render(Block html) {
|
||||
|
||||
}
|
||||
|
||||
protected String getAttemptId(TaskId taskId, TaskAttemptInfo ta) {
|
||||
return ta.getId();
|
||||
}
|
||||
|
||||
protected boolean isValidRequest() {
|
||||
return app.getTask() != null;
|
||||
}
|
||||
@ -215,6 +221,9 @@ private String attemptsTableInit() {
|
||||
.append("\n{'aTargets': [ 5 ]")
|
||||
.append(", 'bSearchable': false }")
|
||||
|
||||
.append("\n, {'sType':'string', 'aTargets': [ 0 ]")
|
||||
.append(", 'mRender': parseHadoopID }")
|
||||
|
||||
.append("\n, {'sType':'numeric', 'aTargets': [ 6, 7")
|
||||
.append(" ], 'mRender': renderHadoopDate }")
|
||||
|
||||
|
@ -24,19 +24,24 @@
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.JobId;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptId;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptReport;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskAttemptState;
|
||||
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.TaskState;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.TaskType;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.impl.pb.JobIdPBImpl;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.impl.pb.TaskAttemptIdPBImpl;
|
||||
import org.apache.hadoop.mapreduce.v2.api.records.impl.pb.TaskIdPBImpl;
|
||||
import org.apache.hadoop.mapreduce.v2.app.AppContext;
|
||||
import org.apache.hadoop.mapreduce.v2.app.job.Job;
|
||||
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.AttemptsPage.FewAttemptsBlock;
|
||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||
import org.apache.hadoop.yarn.api.records.impl.pb.ApplicationIdPBImpl;
|
||||
import org.apache.hadoop.yarn.webapp.view.BlockForTest;
|
||||
@ -137,8 +142,68 @@ public void testTasksBlock() throws Exception {
|
||||
assertTrue(data.toString().contains("100011"));
|
||||
assertFalse(data.toString().contains("Dummy Status \n*"));
|
||||
assertTrue(data.toString().contains("Dummy Status \\n*"));
|
||||
}
|
||||
|
||||
/**
|
||||
* test AttemptsBlock's rendering.
|
||||
*/
|
||||
@Test
|
||||
public void testAttemptsBlock() {
|
||||
AppContext ctx = mock(AppContext.class);
|
||||
AppForTest app = new AppForTest(ctx);
|
||||
|
||||
JobId jobId = new JobIdPBImpl();
|
||||
jobId.setId(0);
|
||||
jobId.setAppId(ApplicationIdPBImpl.newInstance(0,1));
|
||||
|
||||
TaskId taskId = new TaskIdPBImpl();
|
||||
taskId.setId(0);
|
||||
taskId.setTaskType(TaskType.REDUCE);
|
||||
taskId.setJobId(jobId);
|
||||
Task task = mock(Task.class);
|
||||
when(task.getID()).thenReturn(taskId);
|
||||
TaskReport report = mock(TaskReport.class);
|
||||
|
||||
when(task.getReport()).thenReturn(report);
|
||||
when(task.getType()).thenReturn(TaskType.REDUCE);
|
||||
|
||||
Map<TaskId, Task> tasks =
|
||||
new HashMap<TaskId, Task>();
|
||||
Map<TaskAttemptId, TaskAttempt> attempts =
|
||||
new HashMap<TaskAttemptId, TaskAttempt>();
|
||||
TaskAttempt attempt = mock(TaskAttempt.class);
|
||||
TaskAttemptId taId = new TaskAttemptIdPBImpl();
|
||||
taId.setId(0);
|
||||
taId.setTaskId(task.getID());
|
||||
when(attempt.getID()).thenReturn(taId);
|
||||
|
||||
final TaskAttemptState taState = TaskAttemptState.SUCCEEDED;
|
||||
when(attempt.getState()).thenReturn(taState);
|
||||
TaskAttemptReport taReport = mock(TaskAttemptReport.class);
|
||||
when(taReport.getTaskAttemptState()).thenReturn(taState);
|
||||
when(attempt.getReport()).thenReturn(taReport);
|
||||
attempts.put(taId, attempt);
|
||||
tasks.put(taskId, task);
|
||||
when(task.getAttempts()).thenReturn(attempts);
|
||||
|
||||
app.setTask(task);
|
||||
Job job = mock(Job.class);
|
||||
when(job.getTasks(TaskType.REDUCE)).thenReturn(tasks);
|
||||
app.setJob(job);
|
||||
|
||||
AttemptsBlockForTest block = new AttemptsBlockForTest(app,
|
||||
new Configuration());
|
||||
block.addParameter(AMParams.TASK_TYPE, "r");
|
||||
block.addParameter(AMParams.ATTEMPT_STATE, "SUCCESSFUL");
|
||||
|
||||
PrintWriter pWriter = new PrintWriter(data);
|
||||
Block html = new BlockForTest(new HtmlBlockForTest(), pWriter, 0, false);
|
||||
|
||||
block.render(html);
|
||||
pWriter.flush();
|
||||
assertTrue(data.toString().contains(
|
||||
"<a href='" + block.url("task",task.getID().toString()) +"'>"
|
||||
+"attempt_0_0001_r_000000_0</a>"));
|
||||
}
|
||||
|
||||
private class ConfBlockForTest extends ConfBlock {
|
||||
@ -168,4 +233,29 @@ protected void render(Block html) {
|
||||
}
|
||||
}
|
||||
|
||||
private class AttemptsBlockForTest extends FewAttemptsBlock {
|
||||
private final Map<String, String> params = new HashMap<String, String>();
|
||||
|
||||
public void addParameter(String name, String value) {
|
||||
params.put(name, value);
|
||||
}
|
||||
|
||||
public String $(String key, String defaultValue) {
|
||||
String value = params.get(key);
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
public AttemptsBlockForTest(App ctx, Configuration conf) {
|
||||
super(ctx, conf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String url(String... parts) {
|
||||
String result = "url://";
|
||||
for (String string : parts) {
|
||||
result += string + ":";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
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.TaskAttemptInfo;
|
||||
import org.apache.hadoop.mapreduce.v2.util.MRApps;
|
||||
import org.apache.hadoop.mapreduce.v2.util.MRApps.TaskAttemptStateUI;
|
||||
import org.apache.hadoop.yarn.webapp.SubView;
|
||||
@ -59,6 +60,12 @@ protected boolean isValidRequest() {
|
||||
return app.getJob() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAttemptId(TaskId taskId, TaskAttemptInfo ta) {
|
||||
return "<a href='" + url("task", taskId.toString()) +
|
||||
"'>" + ta.getId() + "</a>";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.apache.hadoop.mapreduce.v2.hs.webapp.HsTaskPage.AttemptsBlock#getTaskAttempts()
|
||||
|
@ -143,11 +143,10 @@ protected void render(Block html) {
|
||||
}
|
||||
long attemptElapsed =
|
||||
Times.elapsed(attemptStartTime, attemptFinishTime, false);
|
||||
int sortId = attempt.getID().getId()
|
||||
+ (attempt.getID().getTaskId().getId() * 10000);
|
||||
TaskId taskId = attempt.getID().getTaskId();
|
||||
|
||||
attemptsTableData.append("[\"")
|
||||
.append(sortId + " ").append(taid).append("\",\"")
|
||||
.append(getAttemptId(taskId, ta)).append("\",\"")
|
||||
.append(ta.getState()).append("\",\"")
|
||||
.append(StringEscapeUtils.escapeJavaScript(
|
||||
StringEscapeUtils.escapeHtml(ta.getStatus()))).append("\",\"")
|
||||
@ -234,6 +233,10 @@ protected void render(Block html) {
|
||||
footRow._()._()._();
|
||||
}
|
||||
|
||||
protected String getAttemptId(TaskId taskId, TaskAttemptInfo ta) {
|
||||
return ta.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this is a valid request else false.
|
||||
*/
|
||||
@ -296,7 +299,7 @@ private String attemptsTableInit() {
|
||||
.append(", 'bSearchable': false }")
|
||||
|
||||
.append("\n, {'sType':'numeric', 'aTargets': [ 0 ]")
|
||||
.append(", 'mRender': parseHadoopAttemptID }")
|
||||
.append(", 'mRender': parseHadoopID }")
|
||||
|
||||
.append("\n, {'sType':'numeric', 'aTargets': [ 5, 6")
|
||||
//Column numbers are different for maps and reduces
|
||||
|
@ -200,7 +200,7 @@ public void testAttemptsBlock() {
|
||||
block.render(html);
|
||||
pWriter.flush();
|
||||
// should be printed information about attempts
|
||||
assertTrue(data.toString().contains("0 attempt_0_0001_r_000000_0"));
|
||||
assertTrue(data.toString().contains("attempt_0_0001_r_000000_0"));
|
||||
assertTrue(data.toString().contains("SUCCEEDED"));
|
||||
assertFalse(data.toString().contains("Processed 128/128 records <p> \n"));
|
||||
assertTrue(data.toString().contains("Processed 128\\/128 records <p> \\n"));
|
||||
|
@ -146,17 +146,13 @@ function parseHadoopID(data, type, full) {
|
||||
if (type === 'display') {
|
||||
return data;
|
||||
}
|
||||
//Return the visible string rather than the entire HTML tag
|
||||
return data.split('>')[1].split('<')[0];
|
||||
}
|
||||
|
||||
//JSON array element is "20000 attempt_1360183373897_0001_m_000002_0"
|
||||
function parseHadoopAttemptID(data, type, full) {
|
||||
if (type === 'display' || type === 'filter') {
|
||||
return data.split(' ')[1];
|
||||
}
|
||||
//For sorting use the order as defined in the JSON element
|
||||
return data.split(' ')[0];
|
||||
var splits = data.split('>');
|
||||
// Return original string if there is no HTML tag
|
||||
if (splits.length === 1) return data;
|
||||
|
||||
//Return the visible string rather than the entire HTML tag
|
||||
return splits[1].split('<')[0];
|
||||
}
|
||||
|
||||
function parseHadoopProgress(data, type, full) {
|
||||
|
Loading…
Reference in New Issue
Block a user