YARN-7092. Render application specific log under application tab in new YARN UI. Contributed by Akhil PB.
This commit is contained in:
parent
f9f317b702
commit
99ccca341f
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* 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 AbstractAdapter from './abstract';
|
||||
|
||||
export default AbstractAdapter.extend({
|
||||
address: "timelineWebAddress",
|
||||
// restNameSpace: "timelineV2", // Use ATSv2 when it supports log APIs.
|
||||
restNameSpace: "timeline", //Using ATSv1.5 now, would be supported by ATSv2 very soon.
|
||||
serverName: "ATS",
|
||||
|
||||
urlForQuery(query/*, modelName*/) {
|
||||
var url = this._buildURL();
|
||||
var containerId = query['containerId'];
|
||||
delete query.containerId;
|
||||
return url + '/containers/' + containerId + '/logs';
|
||||
},
|
||||
|
||||
fetchLogFileContent(containerId, logFile) {
|
||||
var url = this._buildURL();
|
||||
url = url + '/containers/' + containerId + '/logs/' + logFile;
|
||||
return Ember.$.ajax({url: url, type: 'GET', dataType: 'text'});
|
||||
}
|
||||
});
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['pull-right'],
|
||||
|
||||
targetId: '',
|
||||
initialClosedState: false,
|
||||
|
||||
didInsertElement() {
|
||||
if (!this.get('targetId')) {
|
||||
this.$('.toggle_switch').hide();
|
||||
}
|
||||
if (this.get('targetId') && this.get('initialClosedState')) {
|
||||
this.$('.toggle_switch').show();
|
||||
this.toggleToggleSwitchArrow();
|
||||
Ember.$('#' + this.get('targetId')).removeClass('panel-collapsed').show();
|
||||
}
|
||||
},
|
||||
|
||||
toggleToggleSwitchArrow() {
|
||||
let $toggleArrow = this.$('.toggle_switch').find('span');
|
||||
if ($toggleArrow.hasClass('glyphicon-chevron-up')) {
|
||||
$toggleArrow.removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');
|
||||
} else {
|
||||
$toggleArrow.removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');
|
||||
}
|
||||
},
|
||||
|
||||
toggleCollapsiblePanel() {
|
||||
let $collapsiblePanel = Ember.$('#' + this.get('targetId'));
|
||||
if ($collapsiblePanel.hasClass('panel-collapsed')) {
|
||||
$collapsiblePanel.removeClass('panel-collapsed');
|
||||
$collapsiblePanel.slideDown();
|
||||
} else {
|
||||
$collapsiblePanel.addClass('panel-collapsed');
|
||||
$collapsiblePanel.slideUp();
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
togglePanelCollapse() {
|
||||
this.toggleToggleSwitchArrow();
|
||||
this.toggleCollapsiblePanel();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -472,9 +472,5 @@ export default Ember.Component.extend({
|
|||
prop = 'http://' + prop;
|
||||
}
|
||||
return prop;
|
||||
},
|
||||
|
||||
isDataEmpty: Ember.computed(function() {
|
||||
return this.modelArr.length === 0;
|
||||
})
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,7 +22,7 @@ export default Ember.Controller.extend({
|
|||
queryParams: ["service"],
|
||||
service: undefined,
|
||||
|
||||
breadcrumbs: Ember.computed("model.attempt.appId", function () {
|
||||
breadcrumbs: Ember.computed("model.attempt.appId", "model.attempt.id", function () {
|
||||
var appId = this.get("model.attempt.appId");
|
||||
var attemptId = this.get("model.attempt.id");
|
||||
var serviceName = this.get('service');
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
queryParams: ["service"],
|
||||
service: undefined,
|
||||
|
||||
selectedAttemptId: '',
|
||||
attemptContainerList: null,
|
||||
selectedContainerId: '',
|
||||
selectedLogFileName: '',
|
||||
containerLogFiles: null,
|
||||
selectedLogFileContent: '',
|
||||
|
||||
_isLoadingTopPanel: false,
|
||||
_isLoadingBottomPanel: false,
|
||||
|
||||
actions: {
|
||||
showContainersForAttemptId(attemptId) {
|
||||
this.set('selectedAttemptId', '');
|
||||
if (attemptId) {
|
||||
this.set('_isLoadingTopPanel', true);
|
||||
this.set('selectedAttemptId', attemptId);
|
||||
this.fetchContainersForAttemptId(attemptId).then((hash) => {
|
||||
let containers = null;
|
||||
if (hash.rmContainers.get('length') > 0 && hash.rmContainers.get('content')) {
|
||||
containers = (containers || []).concat(hash.rmContainers.get('content'));
|
||||
}
|
||||
if (hash.tsContainers.get('length') > 0 && hash.tsContainers.get('content')) {
|
||||
containers = (containers || []).concat(hash.tsContainers.get('content'));
|
||||
}
|
||||
this.set('attemptContainerList', containers);
|
||||
}).finally(() => {
|
||||
this.set('_isLoadingTopPanel', false);
|
||||
});
|
||||
} else {
|
||||
this.set('attemptContainerList', null);
|
||||
this.set('selectedContainerId', '');
|
||||
this.set('containerLogFiles', null);
|
||||
this.set('selectedLogFileName', '');
|
||||
this.set('selectedLogFileContent', '');
|
||||
}
|
||||
},
|
||||
|
||||
showLogFilesForContainerId(containerId) {
|
||||
this.set('selectedContainerId', '');
|
||||
this.set('containerLogFiles', null);
|
||||
this.set('selectedLogFileName', '');
|
||||
this.set('selectedLogFileContent', '');
|
||||
if (containerId) {
|
||||
this.set('_isLoadingBottomPanel', true);
|
||||
this.set('selectedContainerId', containerId);
|
||||
this.fetchLogFilesForContainerId(containerId).then((hash) => {
|
||||
if (hash.logs.get('length') > 0) {
|
||||
this.set('containerLogFiles', hash.logs);
|
||||
} else {
|
||||
this.set('containerLogFiles', null);
|
||||
}
|
||||
}).finally(() => {
|
||||
this.set('_isLoadingBottomPanel', false);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
showContentForLogFile(logFile) {
|
||||
this.set('selectedLogFileName', '');
|
||||
Ember.$("#logContentTextArea1234554321").val('');
|
||||
this.set('showFullLog', false);
|
||||
if (logFile) {
|
||||
this.set('_isLoadingBottomPanel', true);
|
||||
this.set('selectedLogFileName', logFile);
|
||||
this.fetchContentForLogFile(this.get('selectedContainerId'), logFile).then((content) => {
|
||||
this.set('selectedLogFileContent', content.trim());
|
||||
}, () => {
|
||||
this.set('selectedLogFileContent', '');
|
||||
}).always(() => {
|
||||
this.set('_isLoadingBottomPanel', false);
|
||||
});
|
||||
} else {
|
||||
this.set('selectedLogFileContent', '');
|
||||
}
|
||||
},
|
||||
|
||||
findNextTextInLogContent() {
|
||||
let searchInputElem = document.getElementById('logSeachInput98765');
|
||||
this.send('searchTextInLogContent', searchInputElem.value);
|
||||
},
|
||||
|
||||
searchTextInLogContent(searchText) {
|
||||
Ember.$('body').scrollTop(278);
|
||||
let textAreaElem = document.getElementById('logContentTextArea1234554321');
|
||||
let logContent = textAreaElem.innerText;
|
||||
let startIndex = this.searchTextStartIndex || 0;
|
||||
if (startIndex === -1) {
|
||||
startIndex = this.searchTextStartIndex = 0;
|
||||
}
|
||||
if (this.prevSearchText !== searchText) {
|
||||
startIndex = this.searchTextStartIndex = 0;
|
||||
}
|
||||
if (searchText && searchText.trim()) {
|
||||
searchText = searchText.trim();
|
||||
this.prevSearchText = searchText;
|
||||
if (startIndex === 0) {
|
||||
startIndex = logContent.indexOf(searchText, 0);
|
||||
}
|
||||
let endIndex = startIndex + searchText.length;
|
||||
if (document.createRange && window.getSelection) {
|
||||
let range = document.createRange();
|
||||
range.selectNodeContents(textAreaElem);
|
||||
range.setStart(textAreaElem.childNodes.item(0), startIndex);
|
||||
range.setEnd(textAreaElem.childNodes.item(0), endIndex);
|
||||
let selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
this.searchTextStartIndex = logContent.indexOf(searchText, endIndex + 1);
|
||||
} else {
|
||||
this.searchTextStartIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
showFullLogFileContent() {
|
||||
this.set('showFullLog', true);
|
||||
this.notifyPropertyChange('selectedLogFileContent');
|
||||
}
|
||||
},
|
||||
|
||||
attemptList: Ember.computed('model.attempts', function() {
|
||||
let attempts = this.get('model.attempts');
|
||||
let list = null;
|
||||
if (attempts && attempts.get('length') && attempts.get('content')) {
|
||||
list = [].concat(attempts.get('content'));
|
||||
}
|
||||
return list;
|
||||
}),
|
||||
|
||||
fetchContainersForAttemptId(attemptId) {
|
||||
return Ember.RSVP.hash({
|
||||
rmContainers: this.store.query('yarn-container', {
|
||||
app_attempt_id: attemptId
|
||||
}).catch(function() {
|
||||
return Ember.A();
|
||||
}),
|
||||
tsContainers: this.store.query('yarn-timeline-container', {
|
||||
app_attempt_id: attemptId
|
||||
}).catch(function() {
|
||||
return Ember.A();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
fetchLogFilesForContainerId(containerId) {
|
||||
return Ember.RSVP.hash({
|
||||
logs: this.store.query('yarn-log', {
|
||||
containerId: containerId
|
||||
}).catch(function() {
|
||||
return Ember.A();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
fetchContentForLogFile(containerId, logFile) {
|
||||
let logAdapter = this.store.adapterFor('yarn-log');
|
||||
return logAdapter.fetchLogFileContent(containerId, logFile);
|
||||
},
|
||||
|
||||
resetAfterRefresh() {
|
||||
this.set('selectedAttemptId', '');
|
||||
this.set('attemptContainerList', null);
|
||||
this.set('selectedContainerId', '');
|
||||
this.set('selectedLogFileName', '');
|
||||
this.set('containerLogFiles', null);
|
||||
this.set('selectedLogFileContent', '');
|
||||
},
|
||||
|
||||
showFullLog: false,
|
||||
|
||||
showLastFewLinesOfLogContent: Ember.computed('selectedLogFileContent', function() {
|
||||
let content = this.get('selectedLogFileContent');
|
||||
let lines = content.split('\n');
|
||||
if (this.get('showFullLog') || lines.length < 10) {
|
||||
return content;
|
||||
}
|
||||
return lines.slice(lines.length - 10).join('\n');
|
||||
})
|
||||
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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 DS from 'ember-data';
|
||||
|
||||
export default DS.Model.extend({
|
||||
fileName: DS.attr('string'),
|
||||
fileSize: DS.attr('string'),
|
||||
lastModifiedTime: DS.attr('string'),
|
||||
containerId: DS.attr('string'),
|
||||
nodeId: DS.attr('string')
|
||||
});
|
|
@ -60,6 +60,7 @@ Router.map(function() {
|
|||
this.route('components');
|
||||
this.route('charts');
|
||||
this.route('configs');
|
||||
this.route('logs');
|
||||
});
|
||||
this.route('yarn-component-instances', function() {
|
||||
this.route('info', {path: '/:component_name/info'});
|
||||
|
|
|
@ -26,11 +26,13 @@ export default AbstractRoute.extend(AppAttemptMixin, {
|
|||
attempt: this.fetchAttemptInfoFromRMorATS(param.app_attempt_id, this.store),
|
||||
rmContainers: this.store.query('yarn-container', {
|
||||
app_attempt_id: param.app_attempt_id
|
||||
}).catch(function() {
|
||||
return Ember.A();
|
||||
}),
|
||||
tsContainers: this.store.query('yarn-timeline-container', {
|
||||
app_attempt_id: param.app_attempt_id
|
||||
}).catch(function() {
|
||||
return [];
|
||||
return Ember.A();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
|
|
@ -29,7 +29,9 @@ export default AbstractRoute.extend(AppAttemptMixin, {
|
|||
return Ember.RSVP.hash({
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
attempts: this.fetchAttemptListFromRMorATS(app_id, this.store)
|
||||
attempts: this.fetchAttemptListFromRMorATS(app_id, this.store).catch(function() {
|
||||
return Ember.A();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* 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 AbstractRoute from '../abstract';
|
||||
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
|
||||
|
||||
export default AbstractRoute.extend(AppAttemptMixin, {
|
||||
model(param, transition) {
|
||||
const { app_id } = this.paramsFor('yarn-app');
|
||||
const { service } = param;
|
||||
transition.send('updateBreadcrumbs', app_id, service, [{text: 'Logs'}]);
|
||||
return Ember.RSVP.hash({
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
attempts: this.fetchAttemptListFromRMorATS(app_id, this.store).catch(function() {
|
||||
return [];
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-app-attempt');
|
||||
this.store.unloadAll('yarn-timeline-appattempt');
|
||||
this.store.unloadAll('yarn-container');
|
||||
this.store.unloadAll('yarn-timeline-container');
|
||||
this.store.unloadAll('yarn-log');
|
||||
if (this.controller) {
|
||||
this.controller.resetAfterRefresh();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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 DS from 'ember-data';
|
||||
|
||||
export default DS.JSONAPISerializer.extend({
|
||||
internalNormalizeSingleResponse(store, primaryModelClass, payload, containerId, nodeId) {
|
||||
var fixedPayload = {
|
||||
id: "yarn_log_" + payload.fileName + "_" + Date.now(),
|
||||
type: primaryModelClass.modelName,
|
||||
attributes: {
|
||||
fileName: payload.fileName,
|
||||
fileSize: payload.fileSize,
|
||||
lastModifiedTime: payload.lastModifiedTime,
|
||||
containerId: containerId,
|
||||
nodeId: nodeId
|
||||
}
|
||||
};
|
||||
return fixedPayload;
|
||||
},
|
||||
|
||||
normalizeArrayResponse(store, primaryModelClass, payload/*, id, requestType*/) {
|
||||
var normalizedArrayResponse = {
|
||||
data: []
|
||||
};
|
||||
if (payload && payload.containerLogsInfo && payload.containerLogsInfo.containerLogInfo) {
|
||||
normalizedArrayResponse.data = payload.containerLogsInfo.containerLogInfo.map((paylog) => {
|
||||
return this.internalNormalizeSingleResponse(store, primaryModelClass, paylog,
|
||||
payload.containerLogsInfo.containerId, payload.containerLogsInfo.nodeId);
|
||||
});
|
||||
}
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
{{!
|
||||
* 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.
|
||||
}}
|
||||
|
||||
<a class="pull-right toggle_switch" href="#" {{action "togglePanelCollapse"}}>
|
||||
<span class="glyphicon glyphicon-chevron-up"></span>
|
||||
</a>
|
|
@ -25,49 +25,41 @@
|
|||
Containers
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if isDataEmpty}}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="active">
|
||||
<a href="#graphViewTab" role="tab" data-toggle="tab">Graph View</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a href="#gridViewTab" role="tab" data-toggle="tab">Grid View</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="graphViewTab">
|
||||
<br/><br/>
|
||||
<div class="col-md-7 container-fluid" id={{parent-id}}></div>
|
||||
<!-- diag info -->
|
||||
<div class="col-md-5 container-fluid">
|
||||
<div class="panel panel-default add-ellipsis attempt-info-panel">
|
||||
<div class="panel-heading">
|
||||
{{#if selected.link}}
|
||||
{{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}}
|
||||
{{else}}
|
||||
{{selected.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if attemptModel}}
|
||||
{{app-attempt-table attempt=selected}}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="active">
|
||||
<a href="#graphViewTab" role="tab" data-toggle="tab">Graph View</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a href="#gridViewTab" role="tab" data-toggle="tab">Grid View</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="graphViewTab">
|
||||
<br/><br/>
|
||||
<div class="col-md-7 container-fluid" id={{parent-id}}></div>
|
||||
<!-- diag info -->
|
||||
<div class="col-md-5 container-fluid">
|
||||
<div class="panel panel-default add-ellipsis attempt-info-panel">
|
||||
<div class="panel-heading">
|
||||
{{#if selected.link}}
|
||||
{{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}}
|
||||
{{else}}
|
||||
{{container-table container=selected}}
|
||||
{{selected.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if attemptModel}}
|
||||
{{app-attempt-table attempt=selected}}
|
||||
{{else}}
|
||||
{{container-table container=selected}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="gridViewTab">
|
||||
{{em-table columns=gridColumns rows=gridRows}}
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="gridViewTab">
|
||||
{{em-table columns=gridColumns rows=gridRows}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel-body">
|
||||
<h4 class="text-center">No data available!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{outlet}}
|
||||
|
|
|
@ -48,7 +48,26 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
{{#if (or model.rmContainers model.tsContainers)}}
|
||||
{{timeline-view parent-id="containers-timeline-div" my-id="timeline-view" height="400" rmModel=model.rmContainers tsModel=model.tsContainers label="shortAppAttemptId" attemptModel=false}}
|
||||
{{timeline-view
|
||||
parent-id="containers-timeline-div"
|
||||
my-id="timeline-view"
|
||||
height="400"
|
||||
rmModel=model.rmContainers
|
||||
tsModel=model.tsContainers
|
||||
label="shortAppAttemptId"
|
||||
attemptModel=false
|
||||
}}
|
||||
{{else}}
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Containers
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<h4 class="text-center">No data available!</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -125,6 +125,9 @@
|
|||
{{#link-to 'yarn-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
|
||||
{{#link-to 'yarn-app.info' appId (query-params service=model.serviceName)}}Diagnostics{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.logs' tagName="li" class=(if (eq target.currentPath 'yarn-app.logs') "active")}}
|
||||
{{#link-to 'yarn-app.logs' appId (query-params service=serviceName)}}Logs{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
}}
|
||||
|
||||
<div>
|
||||
{{#if model.attempts}}
|
||||
{{timeline-view
|
||||
parent-id="attempt-timeline-div"
|
||||
my-id="timeline-view"
|
||||
|
@ -26,4 +27,16 @@
|
|||
attemptModel=true
|
||||
serviceName=model.serviceName
|
||||
}}
|
||||
{{else}}
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Application Attempts
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<h4 class="text-center">No data available!</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
{{!
|
||||
* 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="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Logs {{collapsible-panel targetId="logFilesCollapsablePanel"}}
|
||||
</div>
|
||||
<div class="panel-body" id="logFilesCollapsablePanel">
|
||||
{{#if _isLoadingTopPanel}}
|
||||
<div class="text-center" style="z-index: 100; position: absolute; left: 46%;">
|
||||
<img src="assets/images/spinner.gif" alt="Loading...">
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if attemptList}}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label>Choose attempt to fetch containers</label>
|
||||
<select class="form-control" onchange={{action "showContainersForAttemptId" value="target.value"}} style="max-width:350px;">
|
||||
<option value="" selected={{eq selectedAttemptId ''}}>None</option>
|
||||
{{#each attemptList as |attempt|}}
|
||||
<option value="{{attempt.id}}" selected={{eq selectedAttemptId attempt.id}}>{{attempt.id}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
{{#if attemptContainerList}}
|
||||
<div class="col-md-6">
|
||||
<label>Choose container to fetch logs</label>
|
||||
<select class="form-control" onchange={{action "showLogFilesForContainerId" value="target.value"}} style="max-width:350px">
|
||||
<option value="" selected={{eq selectedContainerId ''}}>None</option>
|
||||
{{#each attemptContainerList as |container|}}
|
||||
<option value="{{container.id}}" selected={{eq selectedContainerId container.id}}>{{container.id}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#if (and selectedAttemptId (not _isLoadingTopPanel))}}
|
||||
<div class="col-md-4">
|
||||
<h4 class="text-center" style="margin-top:25px;">No container data available!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="col-md-12">
|
||||
<h4 class="text-center">No data available!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if selectedContainerId}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default" style="min-height:150px;">
|
||||
<div class="panel-heading">
|
||||
Log: {{selectedLogFileName}} [ {{selectedContainerId}} & {{selectedAttemptId}} ]
|
||||
{{collapsible-panel targetId="logContentCollapsablePanel"}}
|
||||
</div>
|
||||
<div class="panel-body" id="logContentCollapsablePanel">
|
||||
{{#if _isLoadingBottomPanel}}
|
||||
<div class="text-center" style="z-index: 100; position: absolute; left: 46%;">
|
||||
<img src="assets/images/spinner.gif" alt="Loading...">
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if containerLogFiles}}
|
||||
<div class="row">
|
||||
<div class="col-md-6" style="margin-bottom:20px;">
|
||||
<label>Choose log for {{selectedContainerId}}</label>
|
||||
<select class="form-control" onchange={{action "showContentForLogFile" value="target.value"}} style="max-width:350px">
|
||||
<option value="" selected={{eq selectedLogFileName ''}}>None</option>
|
||||
{{#each containerLogFiles as |file|}}
|
||||
<option value="{{file.fileName}}" selected={{eq selectedLogFileName file.fileName}}>{{file.fileName}} - {{file.fileSize}} bytes</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
{{#if selectedLogFileName}}
|
||||
<div class="col-md-6">
|
||||
<label>Find in log</label>
|
||||
<div class="input-group" style="max-width:350px;">
|
||||
{{input
|
||||
class="form-control"
|
||||
value=""
|
||||
enter="searchTextInLogContent"
|
||||
id="logSeachInput98765"
|
||||
}}
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" {{action "findNextTextInLogContent"}}>Find</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{#if selectedLogFileContent}}
|
||||
{{#unless showFullLog}}
|
||||
<div class="col-md-12">
|
||||
<strong>Showing last 10 lines of log. Click <a href="#" {{action "showFullLogFileContent"}}>here</a> for full log.</strong>
|
||||
</div>
|
||||
{{/unless}}
|
||||
<pre id="logContentTextArea1234554321" class="log-content-area">{{showLastFewLinesOfLogContent}}</pre>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{#unless _isLoadingBottomPanel}}
|
||||
<div class="col-md-12" style="margin-top:20px;">
|
||||
<h4 class="text-center">No log data available!</h4>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"https://github.com/DataTables/DataTables.git": {
|
||||
"1.10.15": "1.10.15"
|
||||
"1.10.15": "84d24d41477bac7657c9ddfa1d86245f9affc879"
|
||||
},
|
||||
"https://github.com/components/ember-data.git": {
|
||||
"2.1.0": "d8b4d3092f67afe22d9d374c40d719d557915fa3"
|
||||
|
@ -27,10 +27,10 @@
|
|||
"0.1.7": "7bb21488563bd1bba23e903a812bf5815beddd1a"
|
||||
},
|
||||
"https://github.com/fgnass/spin.js.git": {
|
||||
"2.3.2": "2.3.2"
|
||||
"2.3.2": "5a9ea41651105302fe76d15cb294070c5863e759"
|
||||
},
|
||||
"https://github.com/ivaynberg/select2.git": {
|
||||
"4.0.0": "4.0.0"
|
||||
"4.0.0": "80eb44bec78568b152dc5547269c164cb7b5363c"
|
||||
},
|
||||
"https://github.com/jquery/jquery-dist.git": {
|
||||
"2.1.4": "7751e69b615c6eca6f783a81e292a55725af6b85"
|
||||
|
@ -39,20 +39,20 @@
|
|||
"1.19.0": "467e7e34652ad7d5883ce9c568461cf8c5e172a8"
|
||||
},
|
||||
"https://github.com/mbostock-bower/d3-bower.git": {
|
||||
"3.5.17": "3.5.17"
|
||||
"3.5.17": "abe0262a205c9f3755c3a757de4dfd1d49f34b24"
|
||||
},
|
||||
"https://github.com/moment/moment-timezone.git": {
|
||||
"0.5.0": "74a2e9378ecf4a31a168f3049f086565c8d66814"
|
||||
},
|
||||
"https://github.com/moment/moment.git": {
|
||||
"2.10.6": "2.10.6",
|
||||
"2.10.6": "446ce77eb08c5c862d7b0b11ef1d2e884d12e3d7",
|
||||
"2.12.0": "d3d7488b4d60632854181cb0a9af325d57fb3d51"
|
||||
},
|
||||
"https://github.com/rwjblue/ember-qunit-builds.git": {
|
||||
"0.4.16": "142c4066a5458bef9dfcb92b70152b9c01d79188"
|
||||
},
|
||||
"https://github.com/sreenaths/more-js.git": {
|
||||
"0.8.2": "0.8.2"
|
||||
"0.8.2": "015ab7c7dad2dc9edc0049b8b65aeb020fd20c51"
|
||||
},
|
||||
"https://github.com/sreenaths/snippet-ss.git": {
|
||||
"1.11.0": "c1abc566f4e001b7f1939b6dbdd911eadc969cf9"
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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('collapsible-panel', 'Integration | Component | collapsible panel', {
|
||||
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`{{collapsible-panel}}`);
|
||||
|
||||
assert.equal(this.$().text().trim(), '');
|
||||
|
||||
// Template block usage:" + EOL +
|
||||
this.render(hbs`
|
||||
{{#collapsible-panel}}
|
||||
template block text
|
||||
{{/collapsible-panel}}
|
||||
`);
|
||||
|
||||
assert.equal(this.$().text().trim(), 'template block text');
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('adapter:yarn-log', 'Unit | Adapter | yarn log', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['serializer:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let adapter = this.subject();
|
||||
assert.ok(adapter);
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('controller:yarn-app/logs', 'Unit | Controller | yarn app/logs', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let controller = this.subject();
|
||||
assert.ok(controller);
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 { moduleForModel, test } from 'ember-qunit';
|
||||
|
||||
moduleForModel('yarn-log', 'Unit | Model | yarn log', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: []
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let model = this.subject();
|
||||
// let store = this.store();
|
||||
assert.ok(!!model);
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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 { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('route:yarn-app/logs', 'Unit | Route | yarn app/logs', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['controller:foo']
|
||||
});
|
||||
|
||||
test('it exists', function(assert) {
|
||||
let route = this.subject();
|
||||
assert.ok(route);
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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 { moduleForModel, test } from 'ember-qunit';
|
||||
|
||||
moduleForModel('yarn-log', 'Unit | Serializer | yarn log', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: ['serializer:yarn-log']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it serializes records', function(assert) {
|
||||
let record = this.subject();
|
||||
|
||||
let serializedRecord = record.serialize();
|
||||
|
||||
assert.ok(serializedRecord);
|
||||
});
|
Loading…
Reference in New Issue