diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js index afd93f44ac1..67a2847be4e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js @@ -23,6 +23,20 @@ export default AbstractAdapter.extend({ restNameSpace: "cluster", serverName: "RM", + urlForQuery(query, modelName) { + var url = this._buildURL(); + if (query.state) { + url = url + '/apps/?state=' + query.state; + } + return url; + }, + + urlForFindRecord(id, modelName, snapshot) { + var url = this._buildURL(); + url = url + '/apps/' + id; + return url; + }, + pathForType(modelName) { return 'apps'; // move to some common place, return path by modelname. }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/app-usage-donut-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/app-usage-donut-chart.js new file mode 100644 index 00000000000..0baf63002c3 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/app-usage-donut-chart.js @@ -0,0 +1,67 @@ +/** + * 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 DonutChart from 'yarn-ui/components/donut-chart'; +import BaseUsageDonutChart from 'yarn-ui/components/base-usage-donut-chart'; +import ColorUtils from 'yarn-ui/utils/color-utils'; +import HrefAddressUtils from 'yarn-ui/utils/href-address-utils'; + +export default BaseUsageDonutChart.extend({ + colors: d3.scale.category20().range(), + + draw: function() { + this.initChart(); + var usageByApps = []; + var avail = 100; + + this.get("data").forEach(function (app) { + var v = app.get("clusterUsagePercentage"); + if (v > 1e-2) { + usageByApps.push({ + label: app.get("id"), + link: HrefAddressUtils.getApplicationLink(app.get("id")), + value: v.toFixed(2) + }); + + console.log(v); + avail = avail - v; + } + }.bind(this)); + + usageByApps.sort(function(a,b) { + return b.value - a.value; + }); + + usageByApps = this.mergeLongTails(usageByApps, 8); + + usageByApps.push({ + label: "Available", + value: avail.toFixed(4) + }) + + this.colors = ColorUtils.getColors(usageByApps.length, ["others", "good"], true); + + this.renderDonutChart(usageByApps, this.get("title"), this.get("showLabels"), + this.get("middleLabel"), "100%", "%"); + }, + + didInsertElement: function() { + this.draw(); + }, +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/bar-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/bar-chart.js index 8e48279f645..7bb292f6ede 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/bar-chart.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/bar-chart.js @@ -116,6 +116,11 @@ export default BaseChartComponent.extend({ this.renderBarChart(this.get("data"), this.get("title"), this.get("textWidth")); }, + _dataChange: Ember.observer("data", function() { + this.chart.g.selectAll("*").remove(); + this.renderBarChart(this.get("data"), this.get("title"), this.get("textWidth")); + }), + didInsertElement: function() { this.draw(); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-chart-component.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-chart-component.js index b85b6ab4d05..d221488c96b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-chart-component.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-chart-component.js @@ -17,23 +17,26 @@ */ import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; export default Ember.Component.extend({ - chart: undefined, tooltip : undefined, colors: d3.scale.category10().range(), - initChart: function() { - this.chart = { + init: function () { + this._super(); + this.set("chart", { svg: undefined, g: undefined, h: 0, w: 0, tooltip: undefined - }; + }); + }, + initChart: function(removeLast = false) { // Init tooltip if it is not initialized - this.tooltip = d3.select("#chart-tooltip"); + // this.tooltip = d3.select("#chart-tooltip"); if (!this.tooltip) { this.tooltip = d3.select("body") .append("div") @@ -42,13 +45,16 @@ export default Ember.Component.extend({ .style("opacity", 0); } - // Init svg - var svg = this.chart.svg; - if (svg) { - svg.remove(); + var parentId = this.get("parentId"); + + if (removeLast) { + // Init svg + var svg = d3.select("#" + parentId + "-svg"); + if (svg) { + svg.remove(); + } } - var parentId = this.get("parentId"); var parent = d3.select("#" + parentId); var bbox = parent.node().getBoundingClientRect(); this.chart.w = bbox.width - 30; @@ -65,12 +71,13 @@ export default Ember.Component.extend({ this.chart.svg = parent.append("svg") .attr("width", this.chart.w) - .attr("height", this.chart.h); + .attr("height", this.chart.h) + .attr("id", parentId + "-svg"); this.chart.g = this.chart.svg.append("g"); }, - renderTitleAndBG: function(g, title, layout) { + renderTitleAndBG: function(g, title, layout, background=true) { var bg = g.append("g"); bg.append("text") .text(title) @@ -78,12 +85,14 @@ export default Ember.Component.extend({ .attr("y", layout.y1 + layout.margin + 20) .attr("class", "chart-title"); - bg.append("rect") - .attr("x", layout.x1) - .attr("y", layout.y1) - .attr("width", layout.x2 - layout.x1) - .attr("height", layout.y2 - layout.y1) - .attr("class", "chart-frame"); + if (background) { + bg.append("rect") + .attr("x", layout.x1) + .attr("y", layout.y1) + .attr("width", layout.x2 - layout.x1) + .attr("height", layout.y2 - layout.y1) + .attr("class", "chart-frame"); + } }, bindTooltip: function(d) { @@ -100,7 +109,11 @@ export default Ember.Component.extend({ } this.tooltip.style("opacity", .9); - this.tooltip.html(data.label + " = " + data.value) + var value = data.value; + if (this.get("type") == "memory") { + value = Converter.memoryToSimpliedUnit(value); + } + this.tooltip.html(data.label + " = " + value) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }.bind(this)) @@ -109,6 +122,10 @@ export default Ember.Component.extend({ }.bind(this)); }, + adjustMaxHeight: function(h) { + this.chart.svg.attr("height", h); + }, + getLayout: function() { var x1 = 0; var y1 = 0; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-usage-donut-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-usage-donut-chart.js new file mode 100644 index 00000000000..bec06c9c9f5 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/base-usage-donut-chart.js @@ -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 Ember from 'ember'; +import DonutChart from 'yarn-ui/components/donut-chart'; + +export default DonutChart.extend({ + mergeLongTails: function(usages, nItemsKept) { + var arr = []; + for (var i = 0; i < Math.min(usages.length, nItemsKept); i++) { + arr.push(usages[i]); + } + + var others = { + label: "Used by others", + value: 0 + } + + for (var i = nItemsKept; i < usages.length; i++) { + others.value += Number(usages[i].value); + } + others.value = others.value.toFixed(2); + + arr.push(others) + + return arr; + }, +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/donut-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/donut-chart.js index e6dcb12c508..9a90855ad7c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/donut-chart.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/donut-chart.js @@ -18,13 +18,15 @@ import Ember from 'ember'; import BaseChartComponent from 'yarn-ui/components/base-chart-component'; +import ColorUtils from 'yarn-ui/utils/color-utils'; +import Converter from 'yarn-ui/utils/converter'; export default BaseChartComponent.extend({ /* * data = [{label="xx", value=},{...}] */ renderDonutChart: function(data, title, showLabels = false, - middleLabel = "Total", middleValue = undefined) { + middleLabel = "Total", middleValue = undefined, suffix = "") { var g = this.chart.g; var layout = this.getLayout(); this.renderTitleAndBG(g, title, layout); @@ -39,7 +41,11 @@ export default BaseChartComponent.extend({ } if (!middleValue) { - middleValue = total; + if (this.get("type") == "memory") { + middleValue = Converter.memoryToSimpliedUnit(total); + } else { + middleValue = total; + } } //Width and height @@ -48,6 +54,8 @@ export default BaseChartComponent.extend({ // 50 is for title var outerRadius = (h - 50 - 2 * layout.margin) / 2; var innerRadius = outerRadius * 0.618; + console.log("inner:" + innerRadius + " outer:" + outerRadius); + var arc = d3.svg.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); @@ -104,12 +112,14 @@ export default BaseChartComponent.extend({ return this.colors[i]; } }.bind(this)) - .attr("stroke-dasharray", function(d, i) { - if (d.value <= 1e-6) { - return "10,10"; - } - }.bind(this)); this.bindTooltip(path); + path.on("click", function (d) { + var data = d.data; + if (data.link) { + this.tooltip.remove(); + document.location.href = data.link; + } + }.bind(this)) // Show labels if (showLabels) { @@ -126,27 +136,30 @@ export default BaseChartComponent.extend({ }.bind(this)) .attr("x", lx) .attr("y", function(d, i) { - return layout.y1 + 50 + (squareW + margin) * i + layout.margin; + return layout.y1 + 75 + (squareW + margin) * i + layout.margin; }) .attr("width", squareW) .attr("height", squareW); select.append("text") .attr("x", lx + squareW + margin) .attr("y", function(d, i) { - return layout.y1 + 50 + (squareW + margin) * i + layout.margin + squareW / 2; + return layout.y1 + 80 + (squareW + margin) * i + layout.margin + squareW / 2; }) .text(function(d) { - return d.label + ' = ' + d.value; - }); + var value = d.value; + if (this.get("type") == "memory") { + value = Converter.memoryToSimpliedUnit(value); + } + return d.label + ' = ' + value + suffix; + }.bind(this)); } if (middleLabel) { var highLightColor = this.colors[0]; g.append("text").text(middleLabel).attr("x", cx).attr("y", cy - 10). attr("class", "donut-highlight-text").attr("fill", highLightColor); - g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 20). - attr("class", "donut-highlight-text").attr("fill", highLightColor). - style("font-size", "30px"); + g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 15). + attr("class", "donut-highlight-sub").attr("fill", highLightColor); } path.transition() @@ -154,8 +167,22 @@ export default BaseChartComponent.extend({ .attrTween('d', tweenPie); }, + _dataChange: Ember.observer("data", function() { + this.chart.g.selectAll("*").remove(); + this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"), + this.get("middleLabel"), this.get("middleValue")); + }), + draw: function() { this.initChart(); + + var colorTargets = this.get("colorTargets"); + if (colorTargets) { + var colorTargetReverse = Boolean(this.get("colorTargetReverse")); + var targets = colorTargets.split(" "); + this.colors = ColorUtils.getColors(this.get("data").length, targets, colorTargetReverse); + } + this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"), this.get("middleLabel"), this.get("middleValue")); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js new file mode 100644 index 00000000000..af8ceb32f7c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js @@ -0,0 +1,209 @@ +/** + * 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 BaseChartComponent from 'yarn-ui/components/base-chart-component'; +import Mock from 'yarn-ui/utils/mock'; + +export default BaseChartComponent.extend({ + CELL_WIDTH: 250, + SAMPLE_CELL_WIDTH: 100, + SAMPLE_HEIGHT: 30, + CELL_HEIGHT: 30, + CELL_MARGIN: 2, + RACK_MARGIN: 20, + filter: "", + + bindTP: function(element) { + element.on("mouseover", function() { + this.tooltip + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + element.style("opacity", 1.0); + }.bind(this)) + .on("mousemove", function() { + // Handle pie chart case + var text = element.attr("tooltiptext"); + + this.tooltip.style("opacity", .9); + this.tooltip.html(text) + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }.bind(this)) + .on("mouseout", function() { + this.tooltip.style("opacity", 0); + element.style("opacity", 0.8); + }.bind(this)); + }, + + // data: + // [{label=label1, value=value1}, ...] + // ... + renderCells: function (model, title) { + var data = []; + model.forEach(function (o) { + data.push(o); + }); + + this.chart.g.remove(); + this.chart.g = this.chart.svg.append("g"); + var g = this.chart.g; + var layout = this.getLayout(); + layout.margin = 50; + + let racks = new Set(); + for (var i = 0; i < data.length; i++) { + racks.add(data[i].get("rack")); + } + + let racksArray = []; + racks.forEach(v => racksArray.push(v)); + + var xOffset = layout.margin; + var yOffset = layout.margin * 3; + + var colorFunc = d3.interpolate(d3.rgb("#bdddf5"), d3.rgb("#0f3957")); + + var sampleXOffset = (layout.x2 - layout.x1) / 2 - 2.5 * this.SAMPLE_CELL_WIDTH - + 2 * this.CELL_MARGIN; + var sampleYOffset = layout.margin * 2; + + for (var i = 1; i <= 5; i++) { + var ratio = i * 0.2 - 0.1; + + var rect = g.append("rect") + .attr("x", sampleXOffset) + .attr("y", sampleYOffset) + .attr("fill", colorFunc(ratio)) + .attr("width", this.SAMPLE_CELL_WIDTH) + .attr("height", this.SAMPLE_HEIGHT); + g.append("text") + .text("" + (ratio * 100).toFixed(1) + "% Used") + .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5) + .attr("x", sampleXOffset + this.SAMPLE_CELL_WIDTH / 2) + .attr("class", "heatmap-cell"); + sampleXOffset += this.CELL_MARGIN + this.SAMPLE_CELL_WIDTH; + } + + var chartXOffset = -1; + + for (var i = 0; i < racksArray.length; i++) { + var text = g.append("text") + .text(racksArray[i]) + .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) + .attr("x", layout.margin) + .attr("class", "heatmap-rack"); + + if (-1 == chartXOffset) { + chartXOffset = layout.margin + text.node().getComputedTextLength() + 30; + } + + xOffset = chartXOffset; + + for (var j = 0; j < data.length; j++) { + var rack = data[j].get("rack"); + var host = data[j].get("nodeHostName"); + + if (rack == racksArray[i]) { + if (!rack.includes(this.filter) && !host.includes(this.filter)) { + this.addNode(g, xOffset, yOffset, colorFunc, data[j], false); + var text = g.append("text") + .text(host) + .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) + .attr("x", xOffset + this.CELL_WIDTH / 2) + .attr("class", "heatmap-cell-notselected"); + } else { + this.addNode(g, xOffset, yOffset, colorFunc, data[j], true); + g.append("text") + .text(host) + .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) + .attr("x", xOffset + this.CELL_WIDTH / 2) + .attr("class", "heatmap-cell"); + } + + xOffset += this.CELL_MARGIN + this.CELL_WIDTH; + if (xOffset + this.CELL_MARGIN + this.CELL_WIDTH >= layout.x2 - + layout.margin) { + xOffset = chartXOffset; + yOffset = yOffset + this.CELL_MARGIN + this.CELL_HEIGHT; + } + + } + } + + while (xOffset > chartXOffset && xOffset + this.CELL_MARGIN + + this.CELL_WIDTH < layout.x2 - layout.margin) { + this.addPlaceholderNode(g, xOffset, yOffset); + xOffset += this.CELL_MARGIN + this.CELL_WIDTH; + } + + if (xOffset != chartXOffset) { + xOffset = chartXOffset; + yOffset += this.CELL_MARGIN + this.CELL_HEIGHT; + } + yOffset += this.RACK_MARGIN; + } + + layout.y2 = yOffset + layout.margin; + this.adjustMaxHeight(layout.y2); + this.renderTitleAndBG(g, title, layout, false); + }, + + addNode: function (g, xOffset, yOffset, colorFunc, data, selected) { + var rect = g.append("rect") + .attr("y", yOffset) + .attr("x", xOffset) + .attr("height", this.CELL_HEIGHT) + .attr("fill", colorFunc(data.get("usedMemoryMB") / + (data.get("usedMemoryMB") + data.get("availMemoryMB")))) + .attr("width", this.CELL_WIDTH) + .attr("tooltiptext", data.get("toolTipText")); + if (selected) { + rect.style("opacity", 0.8); + this.bindTP(rect); + } else { + rect.style("opacity", 0.8); + rect.attr("fill", "DimGray"); + } + }, + + addPlaceholderNode: function(g, xOffset, yOffset) { + var rect = g.append("rect") + .attr("y", yOffset) + .attr("x", xOffset) + .attr("height", this.CELL_HEIGHT) + .attr("fill", "grey") + .attr("width", this.CELL_WIDTH) + .style("opacity", 0.20); + }, + + draw: function() { + this.initChart(true); + this.renderCells(this.get("model"), this.get("title"), this.get("textWidth")); + }, + + didInsertElement: function () { + this.draw(); + }, + + actions: { + applyFilter: function(event) { + this.filter = event.srcElement.value; + this.didInsertElement(); + } + } +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-memusage-by-nodes-stacked-barchart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-memusage-by-nodes-stacked-barchart.js new file mode 100644 index 00000000000..7feb7bb1129 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-memusage-by-nodes-stacked-barchart.js @@ -0,0 +1,88 @@ +/** + * 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 StackedBarchart from 'yarn-ui/components/stacked-barchart'; +import Converter from 'yarn-ui/utils/converter'; + +export default StackedBarchart.extend({ + getDataForRender: function(containers, nodes) { + var arr = []; + var nodeToResources = {}; + nodes.forEach(function(n) { + nodeToResources[n.id] = + { + used: Number(n.get("usedMemoryMB")), + avail: Number(n.get("availMemoryMB")) + } + }); + + containers.forEach(function(c) { + res = nodeToResources[c.get("assignedNodeId")]; + if (res) { + if (!res.usedByTheApp) { + res.usedByTheApp = 0; + } + res.usedByTheApp += Number(c.get("allocatedMB")); + } + }); + + for (var nodeId in nodeToResources) { + var res = nodeToResources[nodeId]; + + var subArr = []; + var value = res.usedByTheApp ? res.usedByTheApp : 0; + subArr.push({ + value: value, + bindText: "This app uses " + Converter.memoryToSimpliedUnit(value) + ". On node=" + nodeId, + }); + + value = res.used - value; + value = Math.max(value, 0); + subArr.push({ + value: value, + bindText: "Other applications uses " + Converter.memoryToSimpliedUnit(value) + ". On node=" + nodeId, + }); + + subArr.push({ + value: res.avail, + bindText: "Free resource " + Converter.memoryToSimpliedUnit(res.avail) + " . On node=" + nodeId + }); + + arr.push(subArr); + } + + console.log(arr); + + return arr; + }, + + didInsertElement: function() { + this.initChart(true); + + this.colors = ["Orange", "Grey", "LimeGreen"]; + + var containers = this.get("rmContainers"); + var nodes = this.get("nodes"); + + var data = this.getDataForRender(containers, nodes); + + this.show( + data, this.get("title"), ["Used by this app", "Used by other apps", + "Available"]); + }, +}) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-ncontainers-by-nodes-stacked-barchart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-ncontainers-by-nodes-stacked-barchart.js new file mode 100644 index 00000000000..251f557c4ce --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/per-app-ncontainers-by-nodes-stacked-barchart.js @@ -0,0 +1,67 @@ +/** + * 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 StackedBarchart from 'yarn-ui/components/stacked-barchart'; + +export default StackedBarchart.extend({ + getDataForRender: function(containers, nodes) { + var arr = []; + var nodeToContainers = {}; + nodes.forEach(function(n) { + nodeToContainers[n.id] = 0; + }); + + containers.forEach(function(c) { + var nodeId = c.get("assignedNodeId"); + var n = nodeToContainers[nodeId]; + if (undefined != n) { + nodeToContainers[nodeId] += 1; + } + }); + + for (var nodeId in nodeToContainers) { + var n = nodeToContainers[nodeId]; + + var subArr = []; + subArr.push({ + value: n, + bindText: "This app has " + n + " containers running on node=" + nodeId + }); + + arr.push(subArr); + } + + console.log(arr); + + return arr; + }, + + didInsertElement: function() { + this.initChart(true); + + this.colors = ["Orange", "Grey", "Gainsboro"]; + + var containers = this.get("rmContainers"); + var nodes = this.get("nodes"); + + var data = this.getDataForRender(containers, nodes); + + this.show( + data, this.get("title"), ["Running containers from this app"]); + }, +}) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-usage-donut-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-usage-donut-chart.js new file mode 100644 index 00000000000..35327268650 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-usage-donut-chart.js @@ -0,0 +1,69 @@ +/** + * 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 DonutChart from 'yarn-ui/components/donut-chart'; +import BaseUsageDonutChart from 'yarn-ui/components/base-usage-donut-chart'; +import ColorUtils from 'yarn-ui/utils/color-utils'; +import HrefAddressUtils from 'yarn-ui/utils/href-address-utils'; + +export default BaseUsageDonutChart.extend({ + colors: d3.scale.category20().range(), + + draw: function() { + this.initChart(); + var usageByQueues = []; + var avail = 100; + + this.get("data").forEach(function (queue) { + var v = queue.get("absUsedCapacity"); + + if (queue.get("isLeafQueue")) { + if (v > 1e-2) { + usageByQueues.push({ + label: queue.get("id"), + link: HrefAddressUtils.getQueueLink(queue.get("id")), + value: v.toFixed(2) + }); + + avail = avail - v; + } + } + }); + + usageByQueues.sort(function(a, b) { + return b.value - a.value; + }); + + usageByQueues = this.mergeLongTails(usageByQueues, 8); + + usageByQueues.push({ + label: "Available", + value: avail.toFixed(4) + }); + + this.colors = ColorUtils.getColors(usageByQueues.length, ["others", "good"], true); + + this.renderDonutChart(usageByQueues, this.get("title"), this.get("showLabels"), + this.get("middleLabel"), "100%", "%"); + }, + + didInsertElement: function() { + this.draw(); + }, +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-view.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-view.js index 2a907719c0b..adedf9a8031 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-view.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-view.js @@ -90,7 +90,6 @@ export default Ember.Component.extend(ChartUtilsMixin, { .attr("class", "queue"); circle.on('mouseover', function () { - circle.style("fill", this.queueColors[1]); }.bind(this)); circle.on('mouseout', function () { if (circle != this.queues.selectedQueueCircle) { @@ -206,7 +205,7 @@ export default Ember.Component.extend(ChartUtilsMixin, { renderQueueCapacities: function (queue, layout) { // Render bar chart - this.renderBarChart(this.charts.g, [{ + this.renderCells(this.charts.g, [{ label: "Cap", value: queue.get("capacity") }, { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-table.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-table.js index e5da81afa2c..359583df2b5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-table.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-table.js @@ -1,3 +1,4 @@ + /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -24,6 +25,7 @@ export default Ember.Component.extend({ var ordering = this.get("ordering") ? true : this.get("ordering"); var info = this.get("info") ? true : this.get("info"); var bFilter = this.get("bFilter") ? true : this.get("bFilter"); + var defaultSearch = this.get("defaultSearch") ? this.get("defaultSearch") : ""; // Defines sorter for the columns if not default. // Can also specify a custom sorter. @@ -66,11 +68,14 @@ export default Ember.Component.extend({ console.log(orderArr[0]); Ember.$('#' + this.get('table-id')).DataTable({ "paging": paging, - "ordering": ordering, + "ordering": ordering, "info": info, "bFilter": bFilter, "order": orderArr, - "columnDefs": colDefs + "columnDefs": colDefs, + "oSearch": { + "sSearch": defaultSearch + } }); } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/stacked-barchart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/stacked-barchart.js new file mode 100644 index 00000000000..4a121fe3f0f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/stacked-barchart.js @@ -0,0 +1,198 @@ +/** + * 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 BaseChartComponent from 'yarn-ui/components/base-chart-component'; +import Mock from 'yarn-ui/utils/mock'; + +export default BaseChartComponent.extend({ + MAX_BAR_HEIGHT: 120, + MAX_BAR_WIDTH: 30, + GAP: 5, + filter: "", + WIDTH_OF_SAMPLE: 200, + + bindTP: function(element) { + element.on("mouseover", function() { + this.tooltip + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + element.style("opacity", 1.0); + }.bind(this)) + .on("mousemove", function() { + // Handle pie chart case + var text = element.attr("tooltiptext"); + + this.tooltip.style("opacity", .9); + this.tooltip.html(text) + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }.bind(this)) + .on("mouseout", function() { + this.tooltip.style("opacity", 0); + element.style("opacity", 0.8); + }.bind(this)); + + element.on("click", function() { + if (element.attr("link")) { + this.tooltip.remove(); + document.location.href = element.attr("link"); + } + }.bind(this)); + }, + + printSamples: function(n, layout, g, colorTitles) { + var yOffset = layout.margin * 3; + + for (var i = 0; i < n; i++) { + var xOffset = layout.x2 - this.WIDTH_OF_SAMPLE - layout.margin; + g.append("rect"). + attr("fill", this.colors[i]). + attr("x", xOffset). + attr("y", yOffset). + attr("width", 20). + attr("height", 20); + + g.append("text"). + attr("x", xOffset + 30). + attr("y", yOffset + 10). + text(colorTitles[i]); + + yOffset = yOffset + 30; + } + }, + + // data: + // [[{value=xx, bindText=xx}, {value=yy, bindText=yy}], [ ... ]] + // __________________________________________________ ___________ + // bar-1 bar-2 + show: function (data, title, colorTitles) { + var width = this.MAX_BAR_WIDTH; + var height = this.MAX_BAR_HEIGHT; + + this.chart.g.remove(); + this.chart.g = this.chart.svg.append("g"); + var g = this.chart.g; + var layout = this.getLayout(); + layout.margin = 50; + + var nBarPerRow = Math.floor((layout.x2 - layout.x1 - 3 * layout.margin - + this.WIDTH_OF_SAMPLE) / + (width + this.GAP)); + + var xOffset; + var yOffset = layout.margin * 2; + + var maxValue = 0; + var maxN = 0; + for (var i = 0; i < data.length; i++) { + var total = 0; + for (var j = 0; j < data[i].length; j++) { + total += data[i][j].value; + } + + if (total > maxValue) { + maxValue = total; + } + if (data[i].length > maxN) { + maxN = data[i].length; + } + } + + // print samples + this.printSamples(maxN, layout, g, colorTitles); + + // print data + data.sort(function(a, b) { + return b[0].value - a[0].value; + }); + + for (var i = 0; i < data.length; i++) { + if (i % nBarPerRow == 0) { + xOffset = layout.margin; + yOffset += layout.margin + height; + } + + var leftTopY = yOffset; + for (var j = 0; j < data[i].length; j++) { + var dy = data[i][j].value * height / maxValue; + if (dy > 0) { + leftTopY = leftTopY - dy; + + var node = g.append("rect"). + attr("fill", this.colors[j]). + attr("x", xOffset). + attr("y", leftTopY). + attr("width", width). + attr("height", dy). + attr("tooltiptext", + (data[i][j].bindText) ? data[i][j].bindText : data[i][j].value). + attr("link", data[i][j].link) + .style("opacity", 0.8); + + this.bindTP(node); + } + } + + if (data[i].length == 1) { + g.append("text") + .text(data[i][0].value) + .attr("y", leftTopY - 10) + .attr("x", xOffset + width / 2) + .attr("class", "heatmap-cell") + .style("fill", "black"); + } + + xOffset += width + this.GAP; + } + + layout.y2 = yOffset + layout.margin; + this.adjustMaxHeight(layout.y2); + this.renderTitleAndBG(g, title, layout, false); + }, + + draw: function(data, title, textWidth) { + this.initChart(true); + //Mock.initMockNodesData(this); + + // mock data + var arr = []; + for (var i = 0; i < 5; i++) { + var subArr = []; + for (var j = 0; j < Math.random() * 4 + 1; j++) { + subArr.push({ + value : Math.abs(Math.random()) + }); + } + arr.push(subArr); + } + + this.show( + arr, this.get("title")); + }, + + didInsertElement: function () { + this.draw(); + }, + + actions: { + applyFilter: function(event) { + this.filter = event.srcElement.value; + this.didInsertElement(); + } + } +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js index 8a2b3de3f2f..516b114505d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js @@ -105,7 +105,7 @@ export default Ember.Component.extend({ var border = 30; var singleBarHeight = this.getPerItemHeight(); var gap = this.getPerItemGap(); - var textWidth = 50; + var textWidth = 200; /* start-time end-time |--------------------------------------| diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js index 1af98aba328..5e7cfa039f2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js @@ -18,6 +18,8 @@ import Ember from 'ember'; +const INBETWEEN_HEIGHT = 130; + export default Ember.Component.extend({ // Map: map : undefined, @@ -124,12 +126,25 @@ export default Ember.Component.extend({ var nodeEnter = node.enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) - .on("click", function(d,i){ + .on("mouseover", function(d,i){ if (d.queueData.get("name") != this.get("selected")) { - document.location.href = "#/yarn-queue/" + d.queueData.get("name"); + document.location.href = "#/yarn-queues/" + d.queueData.get("name"); } - }.bind(this)); - // .on("click", click); + + Ember.run.later(this, function () { + var treeWidth = this.maxDepth * 200; + var treeHeight = this.numOfLeafQueue * INBETWEEN_HEIGHT; + var tree = d3.layout.tree().size([treeHeight, treeWidth]); + var diagonal = d3.svg.diagonal() + .projection(function(d) { return [d.y, d.x]; }); + + this.update(this.treeData, this.treeData, tree, diagonal); + }, 100); + + }.bind(this)) + .on("click", function (d) { + document.location.href = "#/yarn-queue/" + d.queueData.get("name"); + }); nodeEnter.append("circle") .attr("r", 1e-6) @@ -148,6 +163,7 @@ export default Ember.Component.extend({ nodeEnter.append("text") .attr("x", function(d) { return 0; }) .attr("dy", ".35em") + .attr("fill", "white") .attr("text-anchor", function(d) { return "middle"; }) .text(function(d) { var usedCap = d.queueData.get("usedCapacity"); @@ -161,9 +177,9 @@ export default Ember.Component.extend({ // append queue name nodeEnter.append("text") - .attr("x", function(d) { return 40; }) - .attr("dy", ".35em") - .attr("text-anchor", function(d) { return "start"; }) + .attr("x", "0px") + .attr("dy", "45px") + .attr("text-anchor", "middle") .text(function(d) { return d.name; }) .style("fill-opacity", 1e-6); @@ -173,14 +189,21 @@ export default Ember.Component.extend({ .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); nodeUpdate.select("circle") - .attr("r", 20) + .attr("r", 30) .attr("href", function(d) { return "#/yarn-queues/" + d.queueData.get("name"); }) + .style("stroke-width", function(d) { + if (d.queueData.get("name") == this.get("selected")) { + return 7; + } else { + return 2; + } + }.bind(this)) .style("stroke", function(d) { if (d.queueData.get("name") == this.get("selected")) { - return "red"; + return "gray"; } else { return "gray"; } @@ -239,7 +262,7 @@ export default Ember.Component.extend({ var margin = {top: 20, right: 120, bottom: 20, left: 120}; var treeWidth = this.maxDepth * 200; - var treeHeight = this.numOfLeafQueue * 80; + var treeHeight = this.numOfLeafQueue * INBETWEEN_HEIGHT; var width = treeWidth + margin.left + margin.right; var height = treeHeight + margin.top + margin.bottom; var layout = { }; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/cluster-overview.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/cluster-overview.js index dc2f6e4907a..22e62675589 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/cluster-overview.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/cluster-overview.js @@ -20,4 +20,13 @@ import Ember from 'ember'; export default Ember.Controller.extend({ loading: true, + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Cluster Overview", + routeName: 'cluster-overview', + }] + }); \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js new file mode 100644 index 00000000000..a458842f9eb --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js @@ -0,0 +1,40 @@ +/** + * 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({ + + breadcrumbs: Ember.computed("model.attempt.appId", function () { + var appId = this.get("model.attempt.appId"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Applications", + routeName: 'yarn-apps' + }, { + text: `App [${appId}]`, + routeName: 'yarn-app', + model: appId + }, { + text: "Attempt", + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js new file mode 100644 index 00000000000..9ebc2a63257 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js @@ -0,0 +1,40 @@ +/** + * 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({ + + breadcrumbs: Ember.computed("model.appId", function () { + var appId = this.get("model.appId"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Applications", + routeName: 'yarn-apps' + }, { + text: `App [${appId}]`, + routeName: 'yarn-app', + model: appId + }, { + text: "Attempts", + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js new file mode 100644 index 00000000000..f6b9404d89b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js @@ -0,0 +1,38 @@ +/** + * 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({ + + breadcrumbs: Ember.computed("model.app.id", function () { + var appId = this.get("model.app.id"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Applications", + routeName: 'yarn-apps' + }, { + text: `App [${appId}]`, + routeName: 'yarn-app', + model: appId + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js index dc99fd1acf8..396f83b58f3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js @@ -19,4 +19,13 @@ import Ember from 'ember'; export default Ember.Controller.extend({ + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Applications", + routeName: 'yarn-apps', + }] + }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-apps.js new file mode 100644 index 00000000000..4bfe9d01ac4 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-apps.js @@ -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 Ember from 'ember'; + +export default Ember.Controller.extend({ + + breadcrumbs: Ember.computed("model.attempt.appId", function () { + var nodeInfo = this.get("model.nodeInfo"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Nodes", + routeName: 'yarn-nodes' + }, { + text: `Node [ ${nodeInfo.id} ]`, + href: `/#/yarn-node/${nodeInfo.id}/${nodeInfo.addr}`, + }, { + text: "Applications", + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-containers.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-containers.js new file mode 100644 index 00000000000..59c859110ee --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node-containers.js @@ -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 Ember from 'ember'; + +export default Ember.Controller.extend({ + + breadcrumbs: Ember.computed("model.nodeInfo", function () { + var nodeInfo = this.get("model.nodeInfo"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Nodes", + routeName: 'yarn-nodes' + }, { + text: `Node [ ${nodeInfo.id} ]`, + href: `/#/yarn-node/${nodeInfo.id}/${nodeInfo.addr}`, + }, { + text: "Containers", + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node.js new file mode 100644 index 00000000000..e5050220792 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-node.js @@ -0,0 +1,37 @@ +/** + * 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({ + + breadcrumbs: Ember.computed("model.attempt.appId", function () { + var nodeInfo = this.get("model.nodeInfo"); + return [{ + text: "Home", + routeName: 'application' + },{ + text: "Nodes", + routeName: 'yarn-nodes' + }, { + text: `Node [ ${nodeInfo.id} ]`, + href: `/#/yarn-node/${nodeInfo.id}/${nodeInfo.addr}`, + }]; + }) + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes-heatmap.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes-heatmap.js new file mode 100644 index 00000000000..fbe77fa2dbf --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes-heatmap.js @@ -0,0 +1,36 @@ +/** + * 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({ + needReload: true, + selectedQueue: undefined, + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Nodes", + routeName: 'yarn-nodes', + }, { + text: "Heatmap", + routeName: 'yarn-nodes-heatmap', + }] + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes.js new file mode 100644 index 00000000000..b4bf0f0f182 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-nodes.js @@ -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 Ember from 'ember'; + +export default Ember.Controller.extend({ + needReload: true, + selectedQueue: undefined, + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Nodes", + routeName: 'yarn-nodes', + }] + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js new file mode 100644 index 00000000000..e7bedd64390 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js @@ -0,0 +1,46 @@ +/** + * 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({ + needReload: true, + selectedQueue: undefined, + + breadcrumbs: Ember.computed("model.selected", function () { + var queueName = this.get("model.selected"); + + return [{ + text: "Home", + routeName: 'application' + }, { + text: "Queues", + routeName: 'yarn-queues', + model: 'root' + }, { + text: `Queue [ ${queueName} ]`, + routeName: 'yarn-queue', + model: queueName + }, { + text: "Applications", + }]; + + }), + + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js index 38cf35235b3..0b4150fce46 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js @@ -21,4 +21,24 @@ import Ember from 'ember'; export default Ember.Controller.extend({ needReload: true, selectedQueue: undefined, + + breadcrumbs: Ember.computed("model.selected", function () { + var queueName = this.get("model.selected"); + + return [{ + text: "Home", + routeName: 'application' + }, { + text: "Queues", + routeName: 'yarn-queues', + model: 'root' + }, { + text: `Queue [ ${queueName} ]`, + routeName: 'yarn-queue', + model: queueName + }]; + + }), + + }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js new file mode 100644 index 00000000000..941e150121b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js @@ -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 Ember from 'ember'; + +export default Ember.Controller.extend({ + needReload: true, + selectedQueue: undefined, + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Queues", + routeName: 'yarn-queues', + model: 'root' + }] + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js new file mode 100644 index 00000000000..597962aa59f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js @@ -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 Ember from 'ember'; + +export default Ember.Controller.extend({ + + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Applications", + routeName: 'yarn-apps', + }, { + text: "Long Running Services", + routeName: 'yarn-services', + }] + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/cluster-metric.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/cluster-metric.js index 981375ac263..bc6e27ae0bf 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/cluster-metric.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/cluster-metric.js @@ -125,7 +125,7 @@ export default DS.Model.extend({ }); arr.push({ label: "Available", - value: this.get("available" + type) + value: Math.max(this.get("available" + type), 0) }); return arr; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js index b913a336439..f30d1434885 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js @@ -30,6 +30,17 @@ export default DS.Model.extend({ hosts: DS.attr('string'), logsLink: DS.attr('string'), state: DS.attr('string'), + appAttemptId: DS.attr('string'), + + appId: Ember.computed("id",function () { + var id = this.get("id"); + id = id.split("_"); + + id[0] = "application"; + id.pop(); + + return id.join("_"); + }), attemptStartedTime: function() { var startTime = this.get("startTime"); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js index a96c17ce58f..0a5df87ba6d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js @@ -36,6 +36,7 @@ export default DS.Model.extend({ unmanagedApplication: DS.attr('string'), amNodeLabelExpression: DS.attr('string'), applicationTags: DS.attr('string'), + applicationType: DS.attr('string'), priority: DS.attr('number'), allocatedMB: DS.attr('number'), allocatedVCores: DS.attr('number'), @@ -46,6 +47,9 @@ export default DS.Model.extend({ preemptedResourceVCores: DS.attr('number'), numNonAMContainerPreempted: DS.attr('number'), numAMContainerPreempted: DS.attr('number'), + clusterUsagePercentage: DS.attr('number'), + queueUsagePercentage: DS.attr('number'), + currentAppAttemptId: DS.attr('string'), isFailed: function() { return this.get('finalStatus') == "FAILED" diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-rm-node.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-rm-node.js index 9a1082c5c06..a15a20f5010 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-rm-node.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-rm-node.js @@ -89,4 +89,11 @@ export default DS.Model.extend({ }); return arr; }.property("availableVirtualCores", "usedVirtualCores"), + + toolTipText: function() { + return "

Rack: " + this.get("rack") + '

' + + "

Host: " + this.get("nodeHostName") + '

' + + "

Used Memory: " + Math.round(this.get("usedMemoryMB")) + ' MB

' + + "

Available Memory: " + Math.round(this.get("availMemoryMB")) + ' MB

'; + }.property(), }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js index 8f7ce5fe260..87a018d38e5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js @@ -24,8 +24,15 @@ var Router = Ember.Router.extend({ }); Router.map(function() { - this.route('yarn-apps'); - this.route('yarn-nodes'); + this.route('yarn-apps', function () { + this.route('apps'); + this.route('services'); + }); + this.route('yarn-nodes', function(){ + this.route('table'); + this.route('heatmap'); + }); + this.route('yarn-nodes-heatmap'); this.route('yarn-node', { path: '/yarn-node/:node_id/:node_addr' }); this.route('yarn-node-apps', { path: '/yarn-node-apps/:node_id/:node_addr' }); this.route('yarn-node-app', @@ -37,11 +44,15 @@ Router.map(function() { this.route('yarn-container-log', { path: '/yarn-container-log/:node_id/:node_addr/:container_id/:filename' }); this.route('yarn-queue', { path: '/yarn-queue/:queue_name' }); + this.route('cluster-overview'); this.route('yarn-app', { path: '/yarn-app/:app_id' }); this.route('yarn-app-attempt', { path: '/yarn-app-attempt/:app_attempt_id'}); this.route('error'); this.route('notfound', { path: '*:' }); + this.route('yarn-app-attempts', { path: '/yarn-app-attempts/:app_id' }); + this.route('yarn-queues', { path: '/yarn-queues/:queue_name' }); + this.route('yarn-queue-apps', { path: '/yarn-queue-apps/:queue_name' }); }); export default Router; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js index b7a5754bc30..07b3792751e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js @@ -27,6 +27,8 @@ export default Ember.Route.extend({ * error handler page. */ error: function (error) { + Ember.Logger.log(error.stack); + if (error && error.errors[0] && error.errors[0].status == 404) { this.intermediateTransitionTo('/notfound'); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js index 4b4e5544809..36892741bad 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js @@ -20,7 +20,14 @@ import Ember from 'ember'; export default Ember.Route.extend({ model() { - return this.store.findAll('ClusterMetric'); + return Ember.RSVP.hash({ + clusterMetrics: this.store.findAll('ClusterMetric'), + apps: this.store.query('yarn-app', + { + state: "RUNNING" + }), + queues: this.store.findAll('yarn-queue'), + }); }, afterModel() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempts.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempts.js new file mode 100644 index 00000000000..1a526c7a16b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempts.js @@ -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 Ember from 'ember'; + +export default Ember.Route.extend({ + model(param) { + return this.store.query('yarn-app-attempt', { appId: param.app_id}).then(function (attempts) { + return { + appId: param.app_id, + attempts: attempts + }; + }); + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app.js index f5384b83bb7..ab84632c2b7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app.js @@ -22,7 +22,22 @@ export default Ember.Route.extend({ model(param) { return Ember.RSVP.hash({ app: this.store.find('yarn-app', param.app_id), - attempts: this.store.query('yarn-app-attempt', { appId: param.app_id}) + + rmContainers: this.store.find('yarn-app', param.app_id).then(function(app) { + return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) { + if (attempts && attempts.get('firstObject')) { + var appAttemptId = attempts.get('firstObject').get('appAttemptId'); + var rmContainers = this.store.query('yarn-container', + { + app_attempt_id: appAttemptId, + is_rm: true + }); + return rmContainers; + } + }.bind(this)); + }.bind(this)), + + nodes: this.store.findAll('yarn-rm-node'), }); } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js index ff494030e9d..b9454510afe 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js @@ -20,7 +20,9 @@ import Ember from 'ember'; export default Ember.Route.extend({ model() { - var apps = this.store.findAll('yarn-app'); - return apps; + return Ember.RSVP.hash({ + apps: this.store.findAll('yarn-app'), + clusterMetrics: this.store.findAll('ClusterMetric'), + }); } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js new file mode 100644 index 00000000000..871917068fd --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js @@ -0,0 +1,22 @@ +/** + * 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.Route.extend({ +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js new file mode 100644 index 00000000000..871917068fd --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js @@ -0,0 +1,22 @@ +/** + * 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.Route.extend({ +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js index 6e5738803c5..64a1b3e46c4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js @@ -22,6 +22,7 @@ export default Ember.Route.extend({ model(param) { // Fetches data from both NM and RM. RM is queried to get node usage info. return Ember.RSVP.hash({ + nodeInfo: { id: param.node_id, addr: param.node_addr }, node: this.store.findRecord('yarn-node', param.node_addr), rmNode: this.store.findRecord('yarn-rm-node', param.node_id) }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js index 5c466301d4d..56393690bb9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js @@ -20,6 +20,9 @@ import Ember from 'ember'; export default Ember.Route.extend({ model() { - return this.store.findAll('yarn-rm-node'); + return Ember.RSVP.hash({ + nodes: this.store.findAll('yarn-rm-node'), + clusterMetrics: this.store.findAll('ClusterMetric'), + }); } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/heatmap.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/heatmap.js new file mode 100644 index 00000000000..871917068fd --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/heatmap.js @@ -0,0 +1,22 @@ +/** + * 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.Route.extend({ +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/table.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/table.js new file mode 100644 index 00000000000..38ae5d15f4c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes/table.js @@ -0,0 +1,22 @@ +/** + * 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.Route.extend({ +}); \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js new file mode 100644 index 00000000000..dff4ee9b3e8 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js @@ -0,0 +1,36 @@ +/** + * 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.Route.extend({ + model(param) { + return Ember.RSVP.hash({ + selected : param.queue_name, + queues: this.store.findAll('yarn-queue'), + selectedQueue : undefined, + apps: undefined, // apps of selected queue + }); + }, + + afterModel(model) { + var store = this.store; + model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected); + model.apps = store.findAll('yarn-app'); + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js new file mode 100644 index 00000000000..06ceafbf2c1 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js @@ -0,0 +1,38 @@ +/** + * 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.Route.extend({ + model(param) { + return Ember.RSVP.hash({ + selected : param.queue_name, + queues: this.store.findAll('yarn-queue'), + selectedQueue : undefined, + apps: undefined, // apps of selected queue + }); + }, + + afterModel(model) { + model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected); + model.apps = this.store.findAll('yarn-app'); + model.apps.forEach(function(o) { + console.log(o); + }) + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-attempt.js index 4c542c48f19..3de377a7a38 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-attempt.js @@ -40,7 +40,8 @@ export default DS.JSONAPISerializer.extend({ nodeId: payload.nodeId, hosts: payload.host, state: payload.appAttemptState, - logsLink: payload.logsLink + logsLink: payload.logsLink, + appAttemptId: payload.appAttemptId } }; @@ -59,12 +60,16 @@ export default DS.JSONAPISerializer.extend({ // return expected is { data: [ {}, {} ] } var normalizedArrayResponse = {}; - // payload has apps : { app: [ {},{},{} ] } - // need some error handling for ex apps or app may not be defined. - normalizedArrayResponse.data = payload.appAttempts.appAttempt.map(singleApp => { - return this.internalNormalizeSingleResponse(store, primaryModelClass, - singleApp, singleApp.id, requestType); - }, this); + if (payload.appAttempts && payload.appAttempts.appAttempt) { + // payload has apps : { app: [ {},{},{} ] } + // need some error handling for ex apps or app may not be defined. + normalizedArrayResponse.data = payload.appAttempts.appAttempt.map(singleApp => { + return this.internalNormalizeSingleResponse(store, primaryModelClass, + singleApp, singleApp.id, requestType); + }, this); + } else { + normalizedArrayResponse.data = []; + } return normalizedArrayResponse; } }); \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app.js index ba8c1f4eec1..427c3d82691 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app.js @@ -39,6 +39,7 @@ export default DS.JSONAPISerializer.extend({ finishedTime: Converter.timeStampToDate(payload.finishedTime), finalStatus: payload.finalStatus, progress: payload.progress, + applicationType: payload.applicationType, diagnostics: payload.diagnostics, amContainerLogs: payload.amContainerLogs, amHostHttpAddress: payload.amHostHttpAddress, @@ -54,7 +55,10 @@ export default DS.JSONAPISerializer.extend({ preemptedResourceMB: payload.preemptedResourceMB, preemptedResourceVCores: payload.preemptedResourceVCores, numNonAMContainerPreempted: payload.numNonAMContainerPreempted, - numAMContainerPreempted: payload.numAMContainerPreempted + numAMContainerPreempted: payload.numAMContainerPreempted, + clusterUsagePercentage: payload.clusterUsagePercentage, + queueUsagePercentage: payload.queueUsagePercentage, + currentAppAttemptId: payload.currentAppAttemptId } }; @@ -75,7 +79,7 @@ export default DS.JSONAPISerializer.extend({ // payload has apps : { app: [ {},{},{} ] } // need some error handling for ex apps or app may not be defined. - if(payload.apps) { + if(payload.apps && payload.apps.app) { normalizedArrayResponse.data = payload.apps.app.map(singleApp => { return this.internalNormalizeSingleResponse(store, primaryModelClass, singleApp, singleApp.id, requestType); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-container.js index e0513967caa..b9b923d2363 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-container.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-container.js @@ -57,13 +57,19 @@ export default DS.JSONAPISerializer.extend({ var normalizedArrayResponse = {}; if (payload && payload.container) { - // payload has apps : { app: [ {},{},{} ] } - // need some error handling for ex apps or app may not be defined. - normalizedArrayResponse.data = payload.container.map(singleContainer => { - return this.internalNormalizeSingleResponse(store, primaryModelClass, - singleContainer, singleContainer.id, requestType); - }, this); - return normalizedArrayResponse; + if (Array.isArray(payload.container)) { + // payload has apps : { app: [ {},{},{} ] } + // need some error handling for ex apps or app may not be defined. + normalizedArrayResponse.data = payload.container.map(singleContainer => { + return this.internalNormalizeSingleResponse(store, primaryModelClass, + singleContainer, singleContainer.id, requestType); + }, this); + } else { + normalizedArrayResponse.data = [this.internalNormalizeSingleResponse( + store, primaryModelClass, payload.container, payload.container.id, + requestType)]; + } + return normalizedArrayResponse; } else { normalizedArrayResponse.data = []; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css index e2d09dccb5b..409aa159b7c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css @@ -16,11 +16,20 @@ * limitations under the License. */ +body, html, body > .ember-view { + height: 100%; + overflow: visible; + color: @text-color; +} +body, html { + min-width: 1024px; +} + /* Over all style */ text { - font: 12px sans-serif; + font: 16px sans-serif; } text.small { @@ -35,6 +44,7 @@ html, body width: 100%; } + /* queue's style (left banner of queues) */ @@ -45,14 +55,30 @@ text.queue { fill : gray; } -path.queue { - stroke: gray; - fill: none; +text.heatmap-cell { + font: 14px sans-serif; + font-weight: bold; + text-anchor: middle; + fill: Azure; + text-align: center; } -circle.queue { - r: 10; - fill: Steelblue; +text.heatmap-cell-notselected { + font: 14px sans-serif; + font-weight: bold; + text-anchor: middle; + fill: Silver; + text-align: center; +} + +text.heatmap-rack { + font: 20px sans-serif; + fill: DimGray; +} + +path.queue { + stroke: "red"; + fill: none; } /* @@ -76,24 +102,21 @@ text.chart-title { fill: Gray; } -text.donut-highlight-text { - font-size: 20px; +text.donut-highlight-text, text.donut-highlight-sub { + font-size: 15px; font-family: sans-serif; text-anchor: middle; fill: Gray; vertical-align: middle; } -rect.chart-frame { - fill: none; - stroke: gray; - stroke-dasharray: 10,10; +text.donut-highlight-sub { + font-size: 23px; + margin-top: 10px; } -line.chart-leftbanner { - stroke-width: 2; - stroke: gray; - stroke-dasharray: 10,10; +rect.chart-frame { + fill: none; } text.bar-chart-text { @@ -106,9 +129,8 @@ text.bar-chart-text { div.tooltip { position: absolute; text-align: center; - /*height: 28px;*/ - padding: 2px; - font: 12px sans-serif; + padding: 2px; + font: 24px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px; @@ -135,6 +157,19 @@ table.dataTable thead .sorting_desc_disabled { background-image: url("/assets/images/datatables/sort_desc_disabled.png"); } +.add-ellipsis { + overflow: hidden; + text-overflow: ellipsis; +} + +.breadcrumb { + padding-bottom: 3px; +} + +.navbar-default .navbar-nav > li > a { + color: #337ab7; +} + /* * Queue selector */ @@ -158,6 +193,70 @@ table.dataTable thead .sorting_desc_disabled { stroke-width: 2px; } +.lr-margin { + margin: 0px 30px; +} + +.footer { + background-color: @white; + color: @text-color; + + padding: 10px 0px; + margin: 0px; + + border-top: 1px lightgrey solid; + + font-size: .9em; +} + +.table { + margin-bottom: 0px; + border: none; + + overflow: hidden; +} + +.table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { + border: none !important; +} + +.dataTables_wrapper .table { + border: 1px solid lightgrey; + border-bottom: 1px solid lightgrey !important; + border-radious: 5px; +} + +.dataTables_wrapper .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { + border: 1px solid lightgrey; +} + +td { + padding: 8px 15px 8px 15px !important; +} + +.footer-frame { + height: 60px; +} +.footer { + height: 40px; +} + +.footer-pusher { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -40px; // Must be same as footer & footer-frame +} + +.panel-default .container-fluid { + margin-top: -45px !important; + margin-bottom: -10px !important; +} + +.panel-heading { + font-weight: bold; +} + .hadoop-brand-image { margin-top: -10px; width: auto; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs index 03b2c4a3612..7783db4040c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs @@ -16,47 +16,70 @@ * limitations under the License. }} - - -{{outlet}} + + diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/cluster-overview.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/cluster-overview.hbs index 2094092c115..fa90799d063 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/cluster-overview.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/cluster-overview.hbs @@ -16,59 +16,137 @@ * limitations under the License. }} -
-
- {{donut-chart data=model.firstObject.getFinishedAppsDataForDonutChart - title="Finished Apps" - showLabels=true - parentId="finishedapps-donut-chart" - ratio=0.55 - maxHeight=350}} +
+ {{em-breadcrumbs items=breadcrumbs}} +
+ +{{#if model}} + +
+
+
+
+
+ Cluster Resource Usage By Applications +
+
+ {{app-usage-donut-chart data=model.apps + showLabels=true + parentId="appusage-donut-chart" + ratio=0.6 + maxHeight=400}} +
+
+
+ +
+
+
+ Cluster Resource Usage By Leaf Queues +
+
+ {{queue-usage-donut-chart data=model.queues + showLabels=true + parentId="queueusage-donut-chart" + ratio=0.6 + maxHeight=400}} +
+
+
+
+
+ +
+
+
+
+ Finished Apps +
+
+ {{donut-chart data=model.clusterMetrics.firstObject.getFinishedAppsDataForDonutChart + showLabels=true + parentId="finishedapps-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="good warn error"}} +
+
+
+ +
+
+
+ Running Apps +
+
+ {{donut-chart data=model.clusterMetrics.firstObject.getRunningAppsDataForDonutChart + showLabels=true + parentId="runningapps-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="warn good"}} +
+
+
+ +
+
+
+ Node Managers +
+
+ {{donut-chart data=model.clusterMetrics.firstObject.getNodesDataForDonutChart + showLabels=true + parentId="nodes-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="good error warn"}} +
+
+
-
- {{donut-chart data=model.firstObject.getRunningAppsDataForDonutChart - title="Running Apps" - showLabels=true - parentId="runningapps-donut-chart" - ratio=0.55 - maxHeight=350}} +
+
+ +
+
+
+ Resource - Memory +
+
+ {{donut-chart data=model.clusterMetrics.firstObject.getMemoryDataForDonutChart + showLabels=true + parentId="mem-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="good" + colorTargetReverse=true + type="memory"}} +
+
+
+ +
+
+
+ Resource - VCores +
+
+ {{donut-chart data=model.clusterMetrics.firstObject.getVCoreDataForDonutChart + showLabels=true + parentId="vcore-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="good" + colorTargetReverse=true}} +
+
+
-
+{{/if}} -
-
- {{donut-chart data=model.firstObject.getNodesDataForDonutChart - title="Node Managers" - showLabels=true - parentId="nodes-donut-chart" - ratio=0.55 - maxHeight=350}} -
-
- -
- -
-
- {{donut-chart data=model.firstObject.getMemoryDataForDonutChart - title="Resource - Memory" - showLabels=true - parentId="mem-donut-chart" - ratio=0.55 - maxHeight=350}} -
- -
- {{donut-chart data=model.firstObject.getVCoreDataForDonutChart - title="Resource - VCores" - showLabels=true - parentId="vcore-donut-chart" - ratio=0.6 - maxHeight=350}} -
-
{{outlet}} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-table.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-table.hbs index 0788d9c2403..a036a0cf243 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-table.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-table.hbs @@ -20,6 +20,7 @@ Application ID + Application Type Name User Queue @@ -30,13 +31,15 @@ Finished Time Priority Progress - + %Cluster + {{#if arr}} {{#each arr as |app|}} {{app.id}} + {{app.applicationType}} {{app.appName}} {{app.user}} {{app.queue}} @@ -53,11 +56,13 @@
+ {{app.clusterUsagePercentage}} {{/each}} {{else}} {{app.id}} + {{app.applicationType}} {{app.appName}} {{app.user}} {{app.queue}} @@ -74,7 +79,8 @@
- + {{app.clusterUsagePercentage}} + {{/if}} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/node-menu-panel.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/node-menu-panel.hbs index 1e07e899dfb..d2486c9ff6f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/node-menu-panel.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/node-menu-panel.hbs @@ -19,7 +19,7 @@
-

Node Manager
({{node-name nodeId}})

+

Node Manager