YARN-5650. Render Application Timeout value in web UI. Contributed by Akhil PB.
This commit is contained in:
parent
fcbe152342
commit
ef2dd7b78c
|
@ -40,6 +40,7 @@ import org.apache.hadoop.yarn.api.protocolrecords.GetContainerReportRequest;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport;
|
import org.apache.hadoop.yarn.api.records.ApplicationAttemptReport;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
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.ContainerReport;
|
||||||
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
import org.apache.hadoop.yarn.api.records.FinalApplicationStatus;
|
||||||
import org.apache.hadoop.yarn.api.records.LogAggregationStatus;
|
import org.apache.hadoop.yarn.api.records.LogAggregationStatus;
|
||||||
|
@ -207,6 +208,14 @@ public class AppBlock extends HtmlBlock {
|
||||||
overviewTable._("Log Aggregation Status:",
|
overviewTable._("Log Aggregation Status:",
|
||||||
root_url("logaggregationstatus", app.getAppId()), status.name());
|
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:",
|
overviewTable._("Diagnostics:",
|
||||||
app.getDiagnosticsInfo() == null ? "" : app.getDiagnosticsInfo());
|
app.getDiagnosticsInfo() == null ? "" : app.getDiagnosticsInfo());
|
||||||
|
|
|
@ -259,8 +259,12 @@ public class AppInfo {
|
||||||
timeout.setTimeoutType(entry.getKey());
|
timeout.setTimeoutType(entry.getKey());
|
||||||
long timeoutInMillis = entry.getValue().longValue();
|
long timeoutInMillis = entry.getValue().longValue();
|
||||||
timeout.setExpiryTime(Times.formatISO8601(timeoutInMillis));
|
timeout.setExpiryTime(Times.formatISO8601(timeoutInMillis));
|
||||||
timeout.setRemainingTime(Math
|
if (app.isAppInCompletedStates()) {
|
||||||
.max((timeoutInMillis - System.currentTimeMillis()) / 1000, 0));
|
timeout.setRemainingTime(0);
|
||||||
|
} else {
|
||||||
|
timeout.setRemainingTime(Math
|
||||||
|
.max((timeoutInMillis - System.currentTimeMillis()) / 1000, 0));
|
||||||
|
}
|
||||||
timeouts.add(timeout);
|
timeouts.add(timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
});
|
|
@ -50,6 +50,8 @@ export default DS.Model.extend({
|
||||||
clusterUsagePercentage: DS.attr('number'),
|
clusterUsagePercentage: DS.attr('number'),
|
||||||
queueUsagePercentage: DS.attr('number'),
|
queueUsagePercentage: DS.attr('number'),
|
||||||
currentAppAttemptId: DS.attr('string'),
|
currentAppAttemptId: DS.attr('string'),
|
||||||
|
remainingTimeoutInSeconds: DS.attr('number'),
|
||||||
|
applicationExpiryTime: DS.attr('string'),
|
||||||
|
|
||||||
isFailed: function() {
|
isFailed: function() {
|
||||||
return this.get('finalStatus') == "FAILED"
|
return this.get('finalStatus') == "FAILED"
|
||||||
|
|
|
@ -23,9 +23,18 @@ export default DS.JSONAPISerializer.extend({
|
||||||
internalNormalizeSingleResponse(store, primaryModelClass, payload, id,
|
internalNormalizeSingleResponse(store, primaryModelClass, payload, id,
|
||||||
requestType) {
|
requestType) {
|
||||||
if (payload.app) {
|
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 = {
|
var fixedPayload = {
|
||||||
id: id,
|
id: id,
|
||||||
type: primaryModelClass.modelName, // yarn-app
|
type: primaryModelClass.modelName, // yarn-app
|
||||||
|
@ -58,7 +67,9 @@ export default DS.JSONAPISerializer.extend({
|
||||||
numAMContainerPreempted: payload.numAMContainerPreempted,
|
numAMContainerPreempted: payload.numAMContainerPreempted,
|
||||||
clusterUsagePercentage: payload.clusterUsagePercentage,
|
clusterUsagePercentage: payload.clusterUsagePercentage,
|
||||||
queueUsagePercentage: payload.queueUsagePercentage,
|
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,
|
normalizeSingleResponse(store, primaryModelClass, payload, id,
|
||||||
requestType) {
|
requestType) {
|
||||||
var p = this.internalNormalizeSingleResponse(store,
|
var p = this.internalNormalizeSingleResponse(store,
|
||||||
primaryModelClass, payload, id, requestType);
|
primaryModelClass, payload, id, requestType);
|
||||||
return { data: p };
|
return { data: p };
|
||||||
},
|
},
|
||||||
|
@ -90,4 +101,4 @@ export default DS.JSONAPISerializer.extend({
|
||||||
|
|
||||||
return normalizedArrayResponse;
|
return normalizedArrayResponse;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
|
@ -45,6 +45,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-10 container-fluid">
|
<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="row">
|
||||||
<div class="col-md-12 container-fluid">
|
<div class="col-md-12 container-fluid">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
|
@ -116,10 +122,10 @@
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-heading">
|
||||||
Diagnostics
|
Diagnostics
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-footer">{{model.app.diagnostics}}</div>
|
<div class="panel-body">{{model.app.diagnostics}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -91,6 +91,9 @@ export default {
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
isoDateToDate: function(isoDate) {
|
||||||
|
return moment(isoDate).format("YYYY/MM/DD HH:mm:ss");
|
||||||
|
},
|
||||||
splitForContainerLogs: function(id) {
|
splitForContainerLogs: function(id) {
|
||||||
if (id) {
|
if (id) {
|
||||||
var splits = id.split(Constants.PARAM_SEPARATOR);
|
var splits = id.split(Constants.PARAM_SEPARATOR);
|
||||||
|
|
|
@ -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(), '');
|
||||||
|
});
|
Loading…
Reference in New Issue