YARN-5650. Render Application Timeout value in web UI. Contributed by Akhil PB.

This commit is contained in:
Sunil G 2016-12-19 11:44:03 +05:30
parent fcbe152342
commit ef2dd7b78c
9 changed files with 172 additions and 9 deletions

View File

@ -40,6 +40,7 @@
import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
import org.apache.hadoop.yarn.api.records.ApplicationTimeoutType;
import org.apache.hadoop.yarn.api.records.ContainerReport;
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
import org.apache.hadoop.yarn.api.records.LogAggregationStatus;
@ -207,6 +208,14 @@ public ApplicationReport run() throws Exception {
overviewTable._("Log Aggregation Status:",
root_url("logaggregationstatus", app.getAppId()), status.name());
}
long timeout = appReport.getApplicationTimeouts()
.get(ApplicationTimeoutType.LIFETIME).getRemainingTime();
if (timeout < 0) {
overviewTable._("Application Timeout (Remaining Time):", "Unlimited");
} else {
overviewTable._("Application Timeout (Remaining Time):",
String.format("%d seconds", timeout));
}
}
overviewTable._("Diagnostics:",
app.getDiagnosticsInfo() == null ? "" : app.getDiagnosticsInfo());

View File

@ -259,8 +259,12 @@ public AppInfo(ResourceManager rm, RMApp app, Boolean hasAccess,
timeout.setTimeoutType(entry.getKey());
long timeoutInMillis = entry.getValue().longValue();
timeout.setExpiryTime(Times.formatISO8601(timeoutInMillis));
timeout.setRemainingTime(Math
.max((timeoutInMillis - System.currentTimeMillis()) / 1000, 0));
if (app.isAppInCompletedStates()) {
timeout.setRemainingTime(0);
} else {
timeout.setRemainingTime(Math
.max((timeoutInMillis - System.currentTimeMillis()) / 1000, 0));
}
timeouts.add(timeout);
}
}

View File

@ -0,0 +1,60 @@
/**
* 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.
*/
import Ember from 'ember';
import Converter from 'yarn-ui/utils/converter';
export default Ember.Component.extend({
app: null,
appTimeoutValue: function() {
var timeoutValueInSecs = this.get("app.remainingTimeoutInSeconds");
if (timeoutValueInSecs > -1) {
return Converter.msToElapsedTime(timeoutValueInSecs * 1000);
} else {
return timeoutValueInSecs;
}
}.property("app.remainingTimeoutInSeconds"),
isAppTimedOut: function() {
if (this.get("app.remainingTimeoutInSeconds") > 0) {
return false;
} else {
return true;
}
}.property("app.remainingTimeoutInSeconds"),
appTimeoutBarStyle: function() {
var remainingInSecs = this.get("app.remainingTimeoutInSeconds"),
expiryTimestamp = Converter.dateToTimeStamp(this.get("app.applicationExpiryTime")),
expiryInSecs = expiryTimestamp / 1000,
startTimestamp = Converter.dateToTimeStamp(this.get("app.startTime")),
startInSecs = startTimestamp / 1000,
totalRunInSecs = 0,
appRunDurationInSecs = 0,
width = 0;
if (remainingInSecs > 0) {
totalRunInSecs = expiryInSecs - startInSecs;
appRunDurationInSecs = totalRunInSecs - remainingInSecs;
width = appRunDurationInSecs / totalRunInSecs * 100;
}
return "width: " + width + "%";
}.property("app.remainingTimeoutInSeconds", "app.applicationExpiryTime", "app.startTime")
});

View File

@ -50,6 +50,8 @@ export default DS.Model.extend({
clusterUsagePercentage: DS.attr('number'),
queueUsagePercentage: DS.attr('number'),
currentAppAttemptId: DS.attr('string'),
remainingTimeoutInSeconds: DS.attr('number'),
applicationExpiryTime: DS.attr('string'),
isFailed: function() {
return this.get('finalStatus') == "FAILED"

View File

@ -23,9 +23,18 @@ export default DS.JSONAPISerializer.extend({
internalNormalizeSingleResponse(store, primaryModelClass, payload, id,
requestType) {
if (payload.app) {
payload = payload.app;
payload = payload.app;
}
var timeoutInSecs = -1;
var appExpiryTime = Converter.timeStampToDate(payload.finishedTime);
if (payload.timeouts && payload.timeouts.timeout && payload.timeouts.timeout[0]) {
timeoutInSecs = payload.timeouts.timeout[0].remainingTimeInSeconds;
if (timeoutInSecs > -1) {
appExpiryTime = Converter.isoDateToDate(payload.timeouts.timeout[0].expiryTime);
}
}
var fixedPayload = {
id: id,
type: primaryModelClass.modelName, // yarn-app
@ -58,7 +67,9 @@ export default DS.JSONAPISerializer.extend({
numAMContainerPreempted: payload.numAMContainerPreempted,
clusterUsagePercentage: payload.clusterUsagePercentage,
queueUsagePercentage: payload.queueUsagePercentage,
currentAppAttemptId: payload.currentAppAttemptId
currentAppAttemptId: payload.currentAppAttemptId,
remainingTimeoutInSeconds: timeoutInSecs,
applicationExpiryTime: appExpiryTime
}
};
@ -67,7 +78,7 @@ export default DS.JSONAPISerializer.extend({
normalizeSingleResponse(store, primaryModelClass, payload, id,
requestType) {
var p = this.internalNormalizeSingleResponse(store,
var p = this.internalNormalizeSingleResponse(store,
primaryModelClass, payload, id, requestType);
return { data: p };
},
@ -90,4 +101,4 @@ export default DS.JSONAPISerializer.extend({
return normalizedArrayResponse;
}
});
});

View File

@ -0,0 +1,34 @@
{{!
* 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.
}}
<div class="app-timeout-wrapper">
{{#unless isAppTimedOut}}
<div class="panel panel-default">
<div class="panel-body">
<label>Application will be timed out after <span class="text-danger">{{appTimeoutValue}}</span></label>
<div class="progress">
<div class="progress-bar progress-bar-danger progress-bar-striped active" style="{{appTimeoutBarStyle}}"></div>
</div>
<div>
<label class="pull-left">{{app.startTime}}</label>
<label class="pull-right">{{app.applicationExpiryTime}}</label>
</div>
</div>
</div>
{{/unless}}
</div>

View File

@ -45,6 +45,12 @@
</div>
<div class="col-md-10 container-fluid">
<div class="row">
<div class="col-md-12">
{{app-timeout-bar app=model.app}}
</div>
</div>
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
@ -116,10 +122,10 @@
</div>
{{else}}
<div class="panel panel-default">
<div class="panel-body">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-footer">{{model.app.diagnostics}}</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{/if}}
</div>

View File

@ -91,6 +91,9 @@ export default {
return ts;
}
},
isoDateToDate: function(isoDate) {
return moment(isoDate).format("YYYY/MM/DD HH:mm:ss");
},
splitForContainerLogs: function(id) {
if (id) {
var splits = id.split(Constants.PARAM_SEPARATOR);

View File

@ -0,0 +1,34 @@
/**
* 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.
*/
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('app-timeout-bar', 'Integration | Component | app timeout bar', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
this.render(hbs`{{app-timeout-bar}}`);
assert.equal(this.$().text().trim(), '');
});