YARN-258. RM web page UI shows Invalid Date for start and finish times. Contributed by Ravi Prakash

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1417948 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jason Darrell Lowe 2012-12-06 15:39:30 +00:00
parent 8bb0dc34e4
commit 2d1237cbb0
8 changed files with 19 additions and 224 deletions

View File

@ -203,6 +203,9 @@ Release 0.23.6 - UNRELEASED
YARN-251. Proxy URI generation fails for blank tracking URIs (Tom White YARN-251. Proxy URI generation fails for blank tracking URIs (Tom White
via jlowe) via jlowe)
YARN-258. RM web page UI shows Invalid Date for start and finish times
(Ravi Prakash via jlowe)
Release 0.23.5 - UNRELEASED Release 0.23.5 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -28,17 +28,6 @@ import static org.apache.hadoop.yarn.util.StringHelper.*;
import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.HTML; import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.HTML;
public class JQueryUI extends HtmlBlock { public class JQueryUI extends HtmlBlock {
// Render choices (mostly for dataTables)
public enum Render {
/** small (<~100 rows) table as html, most gracefully degradable */
HTML,
/** medium (<~2000 rows) table as js array */
JS_ARRAY,
/** large (<~10000 rows) table loading from server */
JS_LOAD,
/** huge (>~10000 rows) table processing from server */
JS_SERVER
};
// UI params // UI params
public static final String ACCORDION = "ui.accordion"; public static final String ACCORDION = "ui.accordion";
@ -197,12 +186,4 @@ public class JQueryUI extends HtmlBlock {
append("sPaginationType: 'full_numbers', iDisplayLength:20, "). append("sPaginationType: 'full_numbers', iDisplayLength:20, ").
append("aLengthMenu:[20, 40, 60, 80, 100]"); append("aLengthMenu:[20, 40, 60, 80, 100]");
} }
public static StringBuilder tableInitProgress(StringBuilder init,
long numCells) {
return init.append(", bProcessing:true, ").
append("oLanguage:{sProcessing:'Processing ").
append(numCells).append(" cells...").
append("<p><img src=\"/static/busy.gif\">'}");
}
} }

View File

@ -1,56 +0,0 @@
/**
* 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.yarn.webapp.view;
import java.io.PrintWriter;
import static org.apache.hadoop.yarn.util.StringHelper.*;
import static org.apache.hadoop.yarn.webapp.view.JQueryUI.*;
/**
* JSON helpers
*/
public class Jsons {
public static final String _SEP = "\",\"";
public static PrintWriter appendProgressBar(PrintWriter out, String pct) {
return out.append("<br title='").append(pct).append("'>").
append("<div class='").append(C_PROGRESSBAR).
append("' title='").append(pct).append('%').
append("'><div class='").append(C_PROGRESSBAR_VALUE).
append("' style='width: ").append(pct).
append("%'>").append("<\\/div><\\/div>");
}
public static PrintWriter appendProgressBar(PrintWriter out,
float progress) {
return appendProgressBar(out, String.format("%.1f", progress));
}
public static PrintWriter appendSortable(PrintWriter out, Object value) {
return out.append("<br title='").append(String.valueOf(value)).append("'>");
}
public static PrintWriter appendLink(PrintWriter out, Object anchor,
String prefix, String... parts) {
String anchorText = String.valueOf(anchor);
return out.append("<a href='").append(anchor == null ? "#" :
ujoin(prefix, parts)).append("'>").append(anchorText).append("<\\/a>");
}
}

View File

@ -25,26 +25,27 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI.C_PROGRESSBAR_VALUE;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringEscapeUtils;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo; import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo;
import org.apache.hadoop.yarn.util.Times;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet; 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.TABLE;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY;
import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
import org.apache.hadoop.yarn.webapp.view.JQueryUI.Render;
import com.google.inject.Inject; import com.google.inject.Inject;
class AppsBlock extends HtmlBlock { class AppsBlock extends HtmlBlock {
final AppsList list; final ConcurrentMap<ApplicationId, RMApp> apps;
@Inject AppsBlock(AppsList list, ViewContext ctx) { @Inject AppsBlock(RMContext rmContext, ViewContext ctx) {
super(ctx); super(ctx);
this.list = list; apps = rmContext.getRMApps();
} }
@Override public void render(Block html) { @Override public void render(Block html) {
@ -63,7 +64,6 @@ class AppsBlock extends HtmlBlock {
th(".progress", "Progress"). th(".progress", "Progress").
th(".ui", "Tracking UI")._()._(). th(".ui", "Tracking UI")._()._().
tbody(); tbody();
int i = 0;
Collection<RMAppState> reqAppStates = null; Collection<RMAppState> reqAppStates = null;
String reqStateString = $(APP_STATE); String reqStateString = $(APP_STATE);
if (reqStateString != null && !reqStateString.isEmpty()) { if (reqStateString != null && !reqStateString.isEmpty()) {
@ -74,7 +74,7 @@ class AppsBlock extends HtmlBlock {
} }
} }
StringBuilder appsTableData = new StringBuilder("[\n"); StringBuilder appsTableData = new StringBuilder("[\n");
for (RMApp app : list.apps.values()) { for (RMApp app : apps.values()) {
if (reqAppStates != null && !reqAppStates.contains(app.getState())) { if (reqAppStates != null && !reqAppStates.contains(app.getState())) {
continue; continue;
} }
@ -108,7 +108,6 @@ class AppsBlock extends HtmlBlock {
appsTableData.append(trackingURL).append("'>") appsTableData.append(trackingURL).append("'>")
.append(appInfo.getTrackingUI()).append("</a>\"],\n"); .append(appInfo.getTrackingUI()).append("</a>\"],\n");
if (list.rendering != Render.HTML && ++i >= 20) break;
} }
if(appsTableData.charAt(appsTableData.length() - 2) == ',') { if(appsTableData.charAt(appsTableData.length() - 2) == ',') {
appsTableData.delete(appsTableData.length()-2, appsTableData.length()-1); appsTableData.delete(appsTableData.length()-2, appsTableData.length()-1);
@ -118,12 +117,5 @@ class AppsBlock extends HtmlBlock {
_("var appsTableData=" + appsTableData)._(); _("var appsTableData=" + appsTableData)._();
tbody._()._(); tbody._()._();
if (list.rendering == Render.JS_ARRAY) {
echo("<script type='text/javascript'>\n",
"var appsData=");
list.toDataTableArrays(reqAppStates, writer());
echo("\n</script>\n");
}
} }
} }

View File

@ -1,101 +0,0 @@
/**
* 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.yarn.server.resourcemanager.webapp;
import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
import static org.apache.commons.lang.StringEscapeUtils.escapeJavaScript;
import static org.apache.hadoop.yarn.webapp.view.Jsons._SEP;
import static org.apache.hadoop.yarn.webapp.view.Jsons.appendLink;
import static org.apache.hadoop.yarn.webapp.view.Jsons.appendProgressBar;
import static org.apache.hadoop.yarn.webapp.view.Jsons.appendSortable;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.concurrent.ConcurrentMap;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.AppInfo;
import org.apache.hadoop.yarn.util.Times;
import org.apache.hadoop.yarn.webapp.Controller.RequestContext;
import org.apache.hadoop.yarn.webapp.ToJSON;
import org.apache.hadoop.yarn.webapp.view.JQueryUI.Render;
import com.google.inject.Inject;
import com.google.inject.servlet.RequestScoped;
// So we only need to do asm.getApplications once in a request
@RequestScoped
class AppsList implements ToJSON {
final RequestContext rc;
final ConcurrentMap<ApplicationId, RMApp> apps;
Render rendering;
@Inject AppsList(RequestContext ctx, RMContext rmContext) {
rc = ctx;
apps = rmContext.getRMApps();
}
void toDataTableArrays(Collection<RMAppState> requiredAppStates, PrintWriter out) {
out.append('[');
boolean first = true;
for (RMApp app : apps.values()) {
if (requiredAppStates != null &&
!requiredAppStates.contains(app.getState())) {
continue;
}
AppInfo appInfo = new AppInfo(app, true);
String startTime = Times.format(appInfo.getStartTime());
String finishTime = Times.format(appInfo.getFinishTime());
if (first) {
first = false;
} else {
out.append(",\n");
}
out.append("[\"");
appendSortable(out, appInfo.getAppIdNum());
appendLink(out, appInfo.getAppId(), rc.prefix(), "app",
appInfo.getAppId()).append(_SEP).
append(escapeHtml(appInfo.getUser())).append(_SEP).
append(escapeJavaScript(escapeHtml(appInfo.getName()))).append(_SEP).
append(escapeHtml(appInfo.getQueue())).append(_SEP);
appendSortable(out, appInfo.getStartTime()).
append(startTime).append(_SEP);
appendSortable(out, appInfo.getFinishTime()).
append(finishTime).append(_SEP).
append(appInfo.getState()).append(_SEP).
append(appInfo.getFinalStatus()).append(_SEP);
appendProgressBar(out, appInfo.getProgress()).append(_SEP);
appendLink(out, appInfo.getTrackingUI(), rc.prefix(),
!appInfo.isTrackingUrlReady() ?
"#" : appInfo.getTrackingUrlPretty()).
append("\"]");
}
out.append(']');
}
@Override
public void toJSON(PrintWriter out) {
out.print("{\"aaData\":");
toDataTableArrays(null, out);
out.print("}\n");
}
}

View File

@ -25,8 +25,11 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI._PROGRESSBAR_VALUE;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.ConcurrentMap;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager; import org.apache.hadoop.yarn.server.resourcemanager.ResourceManager;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
@ -38,7 +41,6 @@ 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.TABLE;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY; import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY;
import org.apache.hadoop.yarn.webapp.view.HtmlBlock; import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
import org.apache.hadoop.yarn.webapp.view.JQueryUI.Render;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -47,15 +49,15 @@ import com.google.inject.Inject;
* scheduler as part of the fair scheduler page. * scheduler as part of the fair scheduler page.
*/ */
public class FairSchedulerAppsBlock extends HtmlBlock { public class FairSchedulerAppsBlock extends HtmlBlock {
final AppsList list; final ConcurrentMap<ApplicationId, RMApp> apps;
final FairSchedulerInfo fsinfo; final FairSchedulerInfo fsinfo;
@Inject public FairSchedulerAppsBlock(AppsList list, @Inject public FairSchedulerAppsBlock(RMContext rmContext,
ResourceManager rm, ViewContext ctx) { ResourceManager rm, ViewContext ctx) {
super(ctx); super(ctx);
this.list = list;
FairScheduler scheduler = (FairScheduler) rm.getResourceScheduler(); FairScheduler scheduler = (FairScheduler) rm.getResourceScheduler();
fsinfo = new FairSchedulerInfo(scheduler); fsinfo = new FairSchedulerInfo(scheduler);
apps = rmContext.getRMApps();
} }
@Override public void render(Block html) { @Override public void render(Block html) {
@ -75,7 +77,6 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
th(".progress", "Progress"). th(".progress", "Progress").
th(".ui", "Tracking UI")._()._(). th(".ui", "Tracking UI")._()._().
tbody(); tbody();
int i = 0;
Collection<RMAppState> reqAppStates = null; Collection<RMAppState> reqAppStates = null;
String reqStateString = $(APP_STATE); String reqStateString = $(APP_STATE);
if (reqStateString != null && !reqStateString.isEmpty()) { if (reqStateString != null && !reqStateString.isEmpty()) {
@ -85,7 +86,7 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
reqAppStates.add(RMAppState.valueOf(stateString)); reqAppStates.add(RMAppState.valueOf(stateString));
} }
} }
for (RMApp app : list.apps.values()) { for (RMApp app : apps.values()) {
if (reqAppStates != null && !reqAppStates.contains(app.getState())) { if (reqAppStates != null && !reqAppStates.contains(app.getState())) {
continue; continue;
} }
@ -122,15 +123,7 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
td(). td().
a(!appInfo.isTrackingUrlReady()? a(!appInfo.isTrackingUrlReady()?
"#" : appInfo.getTrackingUrlPretty(), appInfo.getTrackingUI())._()._(); "#" : appInfo.getTrackingUrlPretty(), appInfo.getTrackingUI())._()._();
if (list.rendering != Render.HTML && ++i >= 20) break;
} }
tbody._()._(); tbody._()._();
if (list.rendering == Render.JS_ARRAY) {
echo("<script type='text/javascript'>\n",
"var appsData=");
list.toDataTableArrays(reqAppStates, writer());
echo("\n</script>\n");
}
} }
} }

View File

@ -93,8 +93,4 @@ public class RmController extends Controller {
public void submit() { public void submit() {
setTitle("Application Submission Not Allowed"); setTitle("Application Submission Not Allowed");
} }
public void json() {
renderJSON(AppsList.class);
}
} }

View File

@ -60,9 +60,8 @@ public class RmView extends TwoColumnLayout {
} }
private String appsTableInit() { private String appsTableInit() {
AppsList list = getInstance(AppsList.class);
// id, user, name, queue, starttime, finishtime, state, status, progress, ui // id, user, name, queue, starttime, finishtime, state, status, progress, ui
StringBuilder init = tableInit() return tableInit()
.append(", 'aaData': appsTableData") .append(", 'aaData': appsTableData")
.append(", bDeferRender: true") .append(", bDeferRender: true")
.append(", bProcessing: true") .append(", bProcessing: true")
@ -78,18 +77,6 @@ public class RmView extends TwoColumnLayout {
.append(", 'mRender': parseHadoopProgress }]") .append(", 'mRender': parseHadoopProgress }]")
// Sort by id upon page load // Sort by id upon page load
.append(", aaSorting: [[0, 'desc']]"); .append(", aaSorting: [[0, 'desc']]}").toString();
String rows = $("rowlimit");
int rowLimit = rows.isEmpty() ? MAX_DISPLAY_ROWS : Integer.parseInt(rows);
if (list.apps.size() < rowLimit) {
list.rendering = Render.HTML;
return init.append('}').toString();
}
if (list.apps.size() > MAX_FAST_ROWS) {
tableInitProgress(init, list.apps.size() * 6);
}
list.rendering = Render.JS_ARRAY;
return init.append(", aaData:appsData}").toString();
} }
} }