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:
parent
8bb0dc34e4
commit
2d1237cbb0
|
@ -203,6 +203,9 @@ Release 0.23.6 - UNRELEASED
|
|||
YARN-251. Proxy URI generation fails for blank tracking URIs (Tom White
|
||||
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
|
||||
|
||||
INCOMPATIBLE CHANGES
|
||||
|
|
|
@ -28,17 +28,6 @@ import static org.apache.hadoop.yarn.util.StringHelper.*;
|
|||
import org.apache.hadoop.yarn.webapp.hamlet.HamletSpec.HTML;
|
||||
|
||||
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
|
||||
public static final String ACCORDION = "ui.accordion";
|
||||
|
@ -197,12 +186,4 @@ public class JQueryUI extends HtmlBlock {
|
|||
append("sPaginationType: 'full_numbers', iDisplayLength:20, ").
|
||||
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\">'}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>");
|
||||
}
|
||||
}
|
|
@ -25,26 +25,27 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI.C_PROGRESSBAR_VALUE;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
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.RMAppState;
|
||||
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.TABLE;
|
||||
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet.TBODY;
|
||||
import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
|
||||
import org.apache.hadoop.yarn.webapp.view.JQueryUI.Render;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
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);
|
||||
this.list = list;
|
||||
apps = rmContext.getRMApps();
|
||||
}
|
||||
|
||||
@Override public void render(Block html) {
|
||||
|
@ -63,7 +64,6 @@ class AppsBlock extends HtmlBlock {
|
|||
th(".progress", "Progress").
|
||||
th(".ui", "Tracking UI")._()._().
|
||||
tbody();
|
||||
int i = 0;
|
||||
Collection<RMAppState> reqAppStates = null;
|
||||
String reqStateString = $(APP_STATE);
|
||||
if (reqStateString != null && !reqStateString.isEmpty()) {
|
||||
|
@ -74,7 +74,7 @@ class AppsBlock extends HtmlBlock {
|
|||
}
|
||||
}
|
||||
StringBuilder appsTableData = new StringBuilder("[\n");
|
||||
for (RMApp app : list.apps.values()) {
|
||||
for (RMApp app : apps.values()) {
|
||||
if (reqAppStates != null && !reqAppStates.contains(app.getState())) {
|
||||
continue;
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ class AppsBlock extends HtmlBlock {
|
|||
appsTableData.append(trackingURL).append("'>")
|
||||
.append(appInfo.getTrackingUI()).append("</a>\"],\n");
|
||||
|
||||
if (list.rendering != Render.HTML && ++i >= 20) break;
|
||||
}
|
||||
if(appsTableData.charAt(appsTableData.length() - 2) == ',') {
|
||||
appsTableData.delete(appsTableData.length()-2, appsTableData.length()-1);
|
||||
|
@ -118,12 +117,5 @@ class AppsBlock extends HtmlBlock {
|
|||
_("var appsTableData=" + appsTableData)._();
|
||||
|
||||
tbody._()._();
|
||||
|
||||
if (list.rendering == Render.JS_ARRAY) {
|
||||
echo("<script type='text/javascript'>\n",
|
||||
"var appsData=");
|
||||
list.toDataTableArrays(reqAppStates, writer());
|
||||
echo("\n</script>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -25,8 +25,11 @@ import static org.apache.hadoop.yarn.webapp.view.JQueryUI._PROGRESSBAR_VALUE;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
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.rmapp.RMApp;
|
||||
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.TBODY;
|
||||
import org.apache.hadoop.yarn.webapp.view.HtmlBlock;
|
||||
import org.apache.hadoop.yarn.webapp.view.JQueryUI.Render;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
|
@ -47,15 +49,15 @@ import com.google.inject.Inject;
|
|||
* scheduler as part of the fair scheduler page.
|
||||
*/
|
||||
public class FairSchedulerAppsBlock extends HtmlBlock {
|
||||
final AppsList list;
|
||||
final ConcurrentMap<ApplicationId, RMApp> apps;
|
||||
final FairSchedulerInfo fsinfo;
|
||||
|
||||
@Inject public FairSchedulerAppsBlock(AppsList list,
|
||||
@Inject public FairSchedulerAppsBlock(RMContext rmContext,
|
||||
ResourceManager rm, ViewContext ctx) {
|
||||
super(ctx);
|
||||
this.list = list;
|
||||
FairScheduler scheduler = (FairScheduler) rm.getResourceScheduler();
|
||||
fsinfo = new FairSchedulerInfo(scheduler);
|
||||
apps = rmContext.getRMApps();
|
||||
}
|
||||
|
||||
@Override public void render(Block html) {
|
||||
|
@ -75,7 +77,6 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
|
|||
th(".progress", "Progress").
|
||||
th(".ui", "Tracking UI")._()._().
|
||||
tbody();
|
||||
int i = 0;
|
||||
Collection<RMAppState> reqAppStates = null;
|
||||
String reqStateString = $(APP_STATE);
|
||||
if (reqStateString != null && !reqStateString.isEmpty()) {
|
||||
|
@ -85,7 +86,7 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
|
|||
reqAppStates.add(RMAppState.valueOf(stateString));
|
||||
}
|
||||
}
|
||||
for (RMApp app : list.apps.values()) {
|
||||
for (RMApp app : apps.values()) {
|
||||
if (reqAppStates != null && !reqAppStates.contains(app.getState())) {
|
||||
continue;
|
||||
}
|
||||
|
@ -122,15 +123,7 @@ public class FairSchedulerAppsBlock extends HtmlBlock {
|
|||
td().
|
||||
a(!appInfo.isTrackingUrlReady()?
|
||||
"#" : appInfo.getTrackingUrlPretty(), appInfo.getTrackingUI())._()._();
|
||||
if (list.rendering != Render.HTML && ++i >= 20) break;
|
||||
}
|
||||
tbody._()._();
|
||||
|
||||
if (list.rendering == Render.JS_ARRAY) {
|
||||
echo("<script type='text/javascript'>\n",
|
||||
"var appsData=");
|
||||
list.toDataTableArrays(reqAppStates, writer());
|
||||
echo("\n</script>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,8 +93,4 @@ public class RmController extends Controller {
|
|||
public void submit() {
|
||||
setTitle("Application Submission Not Allowed");
|
||||
}
|
||||
|
||||
public void json() {
|
||||
renderJSON(AppsList.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,9 +60,8 @@ public class RmView extends TwoColumnLayout {
|
|||
}
|
||||
|
||||
private String appsTableInit() {
|
||||
AppsList list = getInstance(AppsList.class);
|
||||
// id, user, name, queue, starttime, finishtime, state, status, progress, ui
|
||||
StringBuilder init = tableInit()
|
||||
return tableInit()
|
||||
.append(", 'aaData': appsTableData")
|
||||
.append(", bDeferRender: true")
|
||||
.append(", bProcessing: true")
|
||||
|
@ -78,18 +77,6 @@ public class RmView extends TwoColumnLayout {
|
|||
.append(", 'mRender': parseHadoopProgress }]")
|
||||
|
||||
// Sort by id upon page load
|
||||
.append(", aaSorting: [[0, 'desc']]");
|
||||
|
||||
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();
|
||||
.append(", aaSorting: [[0, 'desc']]}").toString();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue