diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js index 2389f16..d5f3d0c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js @@ -26,7 +26,9 @@ export default AbstractAdapter.extend({ urlForQuery(query/*, modelName*/) { var url = this._buildURL(); - return url + '/apps/' + query.appId + "/appattempts"; + var appId = query.appId; + delete query.appId; + return url + '/apps/' + appId + "/appattempts"; }, urlForFindRecord(id/*, modelName, snapshot*/) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js new file mode 100644 index 0000000..23ecd1b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.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 AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var flowrunUid = query['flowrunUid']; + delete query.flowrunUid; + url = url + '/run-uid/' + flowrunUid + '/apps?fields=ALL'; + return url; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js new file mode 100644 index 0000000..831649c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForFindRecord(id/*, modelName, snapshot*/) { + var url = this._buildURL(); + url = url + '/apps/' + id + '?fields=ALL'; + return url; + }, + + pathForType(/*modelName*/) { + return 'apps'; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js index 348a805..476c9be 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js @@ -25,31 +25,17 @@ export default DS.JSONAPIAdapter.extend({ }, host: function() { - return undefined; + return this.get(`hosts.rmWebAddress`); }.property(), namespace: function() { - return undefined; + return this.get(`env.app.namespaces.cluster`); }.property(), urlForQuery(query/*, modelName*/) { - var rmHosts = this.get(`hosts.rmWebAddress`); - var tsHosts = this.get(`hosts.timelineWebAddress`); - var rmNamespaces = this.get(`env.app.namespaces.cluster`); - var tsNamespaces = this.get(`env.app.namespaces.timeline`); - - if (query.is_rm) { - this.set("host", rmHosts); - this.set("namespace", rmNamespaces); - } else { - this.set("host", tsHosts); - this.set("namespace", tsNamespaces); - } - var url = this._buildURL(); url = url + '/apps/' + Converter.attemptIdToAppId(query.app_attempt_id) + "/appattempts/" + query.app_attempt_id + "/containers"; - console.log(url); return url; }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js new file mode 100644 index 0000000..3d7338f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var appUid = query.app_uid; + var entityType = query.entity_type; + delete query.app_uid; + delete query.entity_type; + url = url + '/app-uid/' + appUid + '/entities/' + entityType + '?fields=INFO'; + return url; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js new file mode 100644 index 0000000..a8c436a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.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 AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + pathForType(/*modelName*/) { + return 'flows'; // move to some common place, return path by modelname. + }, +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js new file mode 100644 index 0000000..ea9c6cb --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var flowuid = query['flowuid']; + delete query.flowuid; + return url + '/flow-uid/' + flowuid + '/runs?fields=ALL'; + }, +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js new file mode 100644 index 0000000..9163c83 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.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 AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQueryRecord(query/*, modelName*/){ + var url = this._buildURL(); + var flowrunuid = query.flowrun_uid; + delete query.flowrun_uid; + url = url + '/run-uid/' + flowrunuid; + return url; + }, + + pathForType(/*modelName*/) { + return 'run-uid'; // move to some common place, return path by modelname. + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js new file mode 100644 index 0000000..2557a86 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbstractAdapter from './abstract'; +import Converter from 'yarn-ui/utils/converter'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/) { + var url = this._buildURL(); + var appId = query.appId; + query.fields = 'ALL'; + delete query.appId; + return url + '/apps/' + appId + "/entities/YARN_APPLICATION_ATTEMPT"; + }, + + urlForFindRecord(id/*, modelName, snapshot*/) { + var url = this._buildURL(); + return url + '/apps/' + Converter.attemptIdToAppId(id) + + "/entities/YARN_APPLICATION_ATTEMPT/" + id + "?fields=ALL"; + } + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js new file mode 100644 index 0000000..f47335a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.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 AbstractAdapter from './abstract'; +import Converter from 'yarn-ui/utils/converter'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "ATS", + + urlForQuery(query/*, modelName*/){ + var url = this._buildURL(); + var app_attempt_id = query.app_attempt_id; + query.fields = 'ALL'; + delete query.app_attempt_id; + url = url + '/apps/' + Converter.attemptIdToAppId(app_attempt_id) + + '/entities/YARN_CONTAINER'; + return url; + }, + + pathForType(/*modelName*/) { + return ''; + } +}); 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 index ef6e46e..3acc5de 100644 --- 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 @@ -52,7 +52,7 @@ export default BaseChartComponent.extend({ bindSelectCategory: function(element, i) { element.on("click", function() { - if (this.selectedCategory == i) { + if (this.selectedCategory === i) { // Remove selection for second click this.selectedCategory = 0; } else { @@ -76,7 +76,7 @@ export default BaseChartComponent.extend({ } var usage = node.get("usedMemoryMB") / - (node.get("usedMemoryMB") + node.get("availMemoryMB")) + (node.get("usedMemoryMB") + node.get("availMemoryMB")); var lowerLimit = (this.selectedCategory - 1) * 0.2; var upperLimit = this.selectedCategory * 0.2; if (lowerLimit <= usage && usage <= upperLimit) { @@ -116,6 +116,7 @@ export default BaseChartComponent.extend({ var sampleXOffset = (layout.x2 - layout.x1) / 2 - 2.5 * this.SAMPLE_CELL_WIDTH - 2 * this.CELL_MARGIN; var sampleYOffset = layout.margin * 2; + var text; for (i = 1; i <= 5; i++) { var ratio = i * 0.2 - 0.1; @@ -128,7 +129,7 @@ export default BaseChartComponent.extend({ .attr("height", this.SAMPLE_HEIGHT) .attr("class", "hyperlink"); this.bindSelectCategory(rect, i); - var text = g.append("text") + text = 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) @@ -137,8 +138,8 @@ export default BaseChartComponent.extend({ sampleXOffset += this.CELL_MARGIN + this.SAMPLE_CELL_WIDTH; } - if (this.selectedCategory != 0) { - var text = g.append("text") + if (this.selectedCategory !== 0) { + text = g.append("text") .text("Clear") .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5) .attr("x", sampleXOffset + 20) @@ -149,7 +150,7 @@ export default BaseChartComponent.extend({ var chartXOffset = -1; for (i = 0; i < racksArray.length; i++) { - var text = g.append("text") + text = g.append("text") .text(racksArray[i]) .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) .attr("x", layout.margin) @@ -163,7 +164,6 @@ export default BaseChartComponent.extend({ for (var j = 0; j < data.length; j++) { var rack = data[j].get("rack"); - var host = data[j].get("nodeHostName"); if (rack === racksArray[i]) { this.addNode(g, xOffset, yOffset, colorFunc, data[j]); @@ -217,11 +217,11 @@ export default BaseChartComponent.extend({ href = `#/yarn-node/${node_id}/${node_addr}`; var a = g.append("a") .attr("href", href); - var text = a.append("text") + a.append("text") .text(data.get("nodeHostName")) .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5) .attr("x", xOffset + this.CELL_WIDTH / 2) - .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : "heatmap-cell-notselected") + .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : "heatmap-cell-notselected"); if (this.isNodeSelected(data)) { this.bindTP(a, rect); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js new file mode 100644 index 0000000..8527e91 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js @@ -0,0 +1,206 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + data: [], + xAxisTickFormatter: null, + yAxisTickFormatter: null, + xAxisText: '', + yAxisText: '', + enableTooltip: true, + onBarChartClickCallback: Ember.K, + hideTootlipOnBarChartClick: true, + + initChart() { + this.height = 400; + this.barWidth = 30; + this.width = Math.max(500, 40 * this.data.length); + }, + + drawChart() { + var margin = {top: 20, right: 20, bottom: 100, left: 100}, + axisLabelPadding = 10, + width = this.width - margin.left - margin.right - axisLabelPadding, + height = this.height - margin.top - margin.bottom - axisLabelPadding, + xAxisText = this.xAxisText? this.xAxisText : '', + yAxisText = this.yAxisText? this.yAxisText : '', + data = this.data, + self = this; + + var xScale = d3.scale.ordinal().rangeRoundBands([0, width], 0.1); + var yScale = d3.scale.linear().range([height, 0]); + + var xAxis = d3.svg.axis() + .scale(xScale) + .orient("bottom") + .tickFormat(function(tick) { + if (self.isFunction(self.xAxisTickFormatter)) { + return self.xAxisTickFormatter(tick); + } else { + return tick; + } + }); + + var yAxis = d3.svg.axis() + .scale(yScale) + .orient("left") + .tickFormat(function(tick) { + if (self.isFunction(self.yAxisTickFormatter)) { + return self.yAxisTickFormatter(tick); + } else { + return tick; + } + }); + + var svg = d3.select(this.element) + .append("svg") + .attr("class", "simple-bar-chart") + .attr("width", width + margin.left + margin.right + axisLabelPadding) + .attr("height", height + margin.top + margin.bottom + axisLabelPadding) + .append("g") + .attr("transform", "translate("+(margin.left+axisLabelPadding)+","+(margin.top)+")"); + + xScale.domain(data.map(function(d) { return d.label; })); + yScale.domain([0, d3.max(data, function(d) { return d.value; })]); + + var gx = svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(xAxis); + + gx.selectAll("text") + .style("text-anchor", "end") + .attr("dx", "-.8em") + .attr("dy", "-.3em") + .attr("transform", "rotate(-60)"); + + gx.append("text") + .attr("transform", "translate("+(width/2)+","+(margin.bottom)+")") + .style("text-anchor", "middle") + .text(xAxisText); + + var gy = svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + gy.append("text") + .attr("transform", "translate("+(-margin.left)+","+(height/2)+")rotate(-90)") + .style("text-anchor", "middle") + .text(yAxisText); + + var barWidth = this.barWidth; + var minBarWidth = Math.min(barWidth, xScale.rangeBand()); + var bars = svg.selectAll("bar") + .data(data) + .enter().append("rect") + .attr("x", function(d) { + var padding = 0; + var rangeBand = xScale.rangeBand(); + if ((rangeBand - barWidth) > 0) { + padding = (rangeBand - barWidth) / 2; + } + return xScale(d.label) + padding; + }) + .attr("width", minBarWidth) + .attr("y", function() { + return yScale(0); + }) + .attr("height", function() { + return height - yScale(0); + }) + .on('click', function(d) { + if (self.enableTooltip && self.hideTootlipOnBarChartClick) { + self.hideTootlip(); + } + if (self.isFunction(self.onBarChartClickCallback)) { + self.onBarChartClickCallback(d); + } + }); + + bars.transition() + .duration(1000) + .delay(100) + .attr("y", function(d) { + return yScale(d.value); + }) + .attr("height", function(d) { + return height - yScale(d.value); + }); + + if (this.enableTooltip) { + this.bindTooltip(bars); + } + }, + + bindTooltip(bars) { + var self = this; + var tooltip = this.tooltip; + if (tooltip) { + bars.on("mouseenter", function(d) { + tooltip.html(d.tooltip); + self.showTooltip(); + }).on("mousemove", function() { + tooltip.style("left", (d3.event.pageX + 5) + "px") + .style("top", (d3.event.pageY - 25) + "px"); + }).on("mouseout", function() { + self.hideTootlip(); + }); + } + }, + + initTooltip() { + this.tooltip = d3.select("body") + .append("div") + .attr("class", "tooltip simple-barchart-tooltip") + .style("opacity", 1); + + this.hideTootlip(); + }, + + hideTootlip() { + if (this.tooltip) { + this.tooltip.style("display", "none"); + } + }, + + showTooltip() { + if (this.tooltip) { + this.tooltip.style("display", "block"); + } + }, + + isFunction(func) { + return Ember.typeOf(func) === "function"; + }, + + didInsertElement() { + this.initChart(); + if (this.enableTooltip) { + this.initTooltip(); + } + this.drawChart(); + }, + + willDestroyElement() { + if (this.tooltip) { + this.tooltip.remove(); + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js new file mode 100644 index 0000000..3a2302a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js @@ -0,0 +1,261 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + + didInsertElement: function() { + var json = buildHierarchy(this.get("arr")); + createVisualization(json); + }, + +}); +// Dimensions of sunburst. +var width = 1000; +var height = 750; +var radius = Math.min(width, height) / 2; +// Breadcrumb dimensions: width, height, spacing, width of tip/tail. +var b = { w: 225, h: 30, s: 3, t: 10 }; +// Total size of all segments; we set this later, after loading the data. +var totalSize = 0; +var vis = null; +var partition = null; +var arc = null; +var colors = d3.scale.category20c(); + +function colorMap(d) { + return colors(d.name); +} + +// Given a node in a partition layout, return an array of all of its ancestor +// nodes, highest first, but excluding the root. +function getAncestors(node) { + var path = []; + var current = node; + while (current.parent) { + path.unshift(current); + current = current.parent; + } + return path; +} + +// Main function to draw and set up the visualization, once we have the data. +function createVisualization(json) { + partition = d3.layout.partition() + .size([2 * Math.PI, radius * radius]) + .value(function(d) { return d.size; }); + arc = d3.svg.arc() + .startAngle(function(d) { return d.x; }) + .endAngle(function(d) { return d.x + d.dx; }) + .innerRadius(function(d) { return Math.sqrt(d.y); }) + .outerRadius(function(d) { return Math.sqrt(d.y + d.dy); }); + // Basic setup of page elements. + initializeBreadcrumbTrail(); + //drawLegend(); + //d3.select("#togglelegend").on("click", toggleLegend); + + // Bounding circle underneath the sunburst, to make it easier to detect + // when the mouse leaves the parent g. + vis = d3.select("#chart").append("svg:svg") + .attr("width", width) + .attr("height", height) + .append("svg:g") + .attr("id", "container") + .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); + vis.append("svg:circle").attr("r", radius) + .style("opacity", 0); + + // For efficiency, filter nodes to keep only those large enough to see. + var nodes = partition.nodes(json) + .filter(function(d) { + return (d.dx > 0.005); // 0.005 radians = 0.29 degrees + }); + + var path = vis.data([json]).selectAll("path") + .data(nodes) + .enter().append("svg:path") + .attr("display", function(d) { return d.depth ? null : "none"; }) + .attr("d", arc) + .attr("fill-rule", "evenodd") + .attr("fill", colorMap) + .style("opacity", 1) + .on("mouseover", mouseover); + // Add the mouseleave handler to the bounding circle. + d3.select("#container").on("mouseleave", mouseleave); + + // Get total size of the tree = value of root node from partition. + totalSize = path.node().__data__.value; +} + + // Take a 2-column CSV and transform it into a hierarchical structure suitable + // for a partition layout. The first column is a sequence of step names, from + // root to leaf, separated by hyphens. The second column is a count of how + // often that sequence occurred. +function buildHierarchy(csv) { + var root = {"name": "root", "children": []}; + for (var i = 0; i < csv.length; i++) { + var sequence = csv[i][0]; + var size = +csv[i][1]; + if (isNaN(size)) { // e.g. if this is a header row + continue; + } + var parts = sequence.split("-"); + var currentNode = root; + for (var j = 0; j < parts.length; j++) { + var children = currentNode["children"]; + var nodeName = parts[j]; + var childNode; + if (j + 1 < parts.length) { + // Not yet at the end of the sequence; move down the tree. + var foundChild = false; + for (var k = 0; k < children.length; k++) { + if (children[k]["name"] === nodeName) { + childNode = children[k]; + foundChild = true; + break; + } + } + // If we don't already have a child node for this branch, create it. + if (!foundChild) { + childNode = {"name": nodeName, "children": []}; + children.push(childNode); + } + currentNode = childNode; + } else { + // Reached the end of the sequence; create a leaf node. + childNode = {"name": nodeName, "size": size, "children": [], "sequence": sequence}; + children.push(childNode); + } + } + } + return root; +} + +// Fade all but the current sequence, and show it in the breadcrumb trail. +function mouseover(d) { + //var percentage = (100 * d.value / totalSize).toPrecision(3); + //var percentageString = percentage + "%"; + var percentageString = d.value; + + d3.select("#percentage").html('
' + percentageString + + '
(' + d.name + ')
'); + d3.select("#explanation").style("visibility", ""); + + var sequenceArray = getAncestors(d); + updateBreadcrumbs(sequenceArray, percentageString); + + // Fade all the segments. + d3.selectAll("path").style("opacity", 0.2); + + // Then highlight only those that are an ancestor of the current segment. + vis.selectAll("path") + .filter(function(node) { + return (sequenceArray.indexOf(node) >= 0); + }) + .style("opacity", 1); +} + +// Restore everything to full opacity when moving off the visualization. +function mouseleave() { + // Hide the breadcrumb trail + d3.select("#trail").style("visibility", "hidden"); + + // Deactivate all segments during transition. + d3.selectAll("path").on("mouseover", null); + + // Transition each segment to full opacity and then reactivate it. + d3.selectAll("path") + .transition() + .duration(1000) + .style("opacity", 1) + .each("end", function() { + d3.select(this).on("mouseover", mouseover); + }); + + d3.select("#explanation") + .style("visibility", "hidden"); +} + +function initializeBreadcrumbTrail() { + // Add the svg area. + var trail = d3.select("#sequence").append("svg:svg") + .attr("width", width) + .attr("height", 50) + .attr("id", "trail"); + // Add the label at the end, for the percentage. + trail.append("svg:text") + .attr("id", "endlabel") + .style("fill", "#000"); +} + +// Generate a string that describes the points of a breadcrumb polygon. +function breadcrumbPoints(d, i) { + var points = []; + points.push("0,0"); + points.push(b.w + ",0"); + points.push(b.w + b.t + "," + (b.h / 2)); + points.push(b.w + "," + b.h); + points.push("0," + b.h); + if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex. + points.push(b.t + "," + (b.h / 2)); + } + return points.join(" "); +} + +// Update the breadcrumb trail to show the current sequence and percentage. +function updateBreadcrumbs(nodeArray, percentageString) { + // Data join; key function combines name and depth (= position in sequence). + var g = d3.select("#trail") + .selectAll("g") + .data(nodeArray, function(d) { return d.name + d.depth; }); + + // Add breadcrumb and label for entering nodes. + var entering = g.enter().append("svg:g"); + + entering.append("svg:polygon") + .attr("points", breadcrumbPoints) + .attr("fill", colorMap); + + entering.append("svg:text") + .attr("x", (b.w + b.t) / 2) + .attr("y", b.h / 2) + .attr("dy", "0.35em") + .attr("text-anchor", "middle") + .text(function(d) { return d.name; }); + + // Set position for entering and updating nodes. + g.attr("transform", function(d, i) { + return "translate(" + i * (b.w + b.s) + ", 0)"; + }); + + // Remove exiting nodes. + g.exit().remove(); + + // Now move and update the percentage at the end. + d3.select("#trail").select("#endlabel") + .attr("x", (nodeArray.length + 0.5) * (b.w + b.s)) + .attr("y", b.h / 2) + .attr("dy", "0.35em") + .attr("text-anchor", "middle") + .text(percentageString); + + // Make the breadcrumb trail visible, if it's hidden. + d3.select("#trail") + .style("visibility", ""); +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js index 44a7c1c..fffaf17 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js @@ -17,7 +17,6 @@ */ import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import TableDefinition from 'em-table/utils/table-definition'; import AppTableController from '../app-table-columns'; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js index 44a7c1c..fffaf17 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js @@ -17,7 +17,6 @@ */ import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import TableDefinition from 'em-table/utils/table-definition'; import AppTableController from '../app-table-columns'; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js new file mode 100644 index 0000000..61e7823 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js @@ -0,0 +1,125 @@ +/** + * 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 TableDef from 'em-table/utils/table-definition'; +import ColumnDef from 'em-table/utils/column-definition'; +import lodash from 'lodash/lodash'; + +function _createColumns() { + var columns = []; + columns.push({ + id: 'flowName', + headerTitle: 'Flow Name', + contentPath: 'flowName', + observePath: true, + }, { + id: 'user', + headerTitle: 'User', + contentPath: 'user', + observePath: true + }, { + id: 'uid', + headerTitle: 'Flow ID', + contentPath: 'uid', + observePath: true, + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-flow.info', + id: row.get('uid'), + displayText: row.get('uid') + }; + } + }, { + id: 'lastExecDate', + headerTitle: 'Last Execution Date', + contentPath: 'lastExecDate', + observePath: true + }); + return ColumnDef.make(columns); +} + +function _getAggregatedFlowsData(flows) { + var aggregatedFlows = []; + flows = flows? flows.get('content') : []; + + var aggregated = lodash.groupBy(flows, function(flow) { + return flow.getRecord().get('uid'); + }); + + lodash.forIn(aggregated, function(flows) { + let flowsInAsc = lodash.sortBy(flows, function(flow) { + return flow.getRecord().get('lastExecDate'); + }); + let flowsInDesc = flowsInAsc.reverse(); + aggregatedFlows.push(flowsInDesc[0].getRecord()); + }); + + return aggregatedFlows; +} + +function _createRows(flows) { + var data = [], + aggregatedFlows = null, + row = null; + + aggregatedFlows = _getAggregatedFlowsData(flows); + + aggregatedFlows.forEach(function(flow) { + row = Ember.Object.create({ + user: flow.get('user'), + flowName: flow.get('flowName'), + uid: flow.get('uid'), + lastExecDate: flow.get('lastExecDate') + }); + data.push(row); + }); + + return Ember.A(data); +} + +export default Ember.Controller.extend({ + breadcrumbs: [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity', + }], + + columns: _createColumns(), + + rows: Ember.computed('model', function() { + return _createRows(this.get('model')); + }), + + tableDefinition: TableDef.create({ + sortColumnId: 'lastExecDate', + sortOrder: 'desc' + }), + + getLastFlowExecutionInfoByFlowUid: function(uid) { + var aggregatedFlows = _getAggregatedFlowsData(this.get('model')); + var recent = aggregatedFlows.find(function(flow) { + return flow.get('uid') === uid; + }); + return recent; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js new file mode 100644 index 0000000..216ab11 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.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({ + breadcrumbs: Ember.computed("model.flowUid", function() { + var flowUid = this.get('model.flowUid'); + return [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity' + }, { + text: `Flow Info [${flowUid}]`, + routeName: 'yarn-flow.info', + model: flowUid + }]; + }) +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js new file mode 100644 index 0000000..fc4dd23 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; + +export default Ember.Controller.extend({ + flowUid: function() { + return this.get('model.flowUid'); + }.property('model.flowUid'), + + flowLastExecutionDate: function() { + if (this.get('model.lastFlowExecutionInfo')) { + return this.get('model.lastFlowExecutionInfo').get('lastExecDate'); + } else { + return ''; + } + }.property('model.lastFlowExecutionInfo'), + + flowInfo: function() { + var info = {}; + var firstRunObj = this.get('model.flowRuns').get('firstObject'); + info.flowUid = this.get('flowUid'); + info.flowName = firstRunObj.get('flowName'); + info.user = firstRunObj.get('user'); + info.lastExecutionDate = this.get('flowLastExecutionDate'); + info.firstRunStarted = this.get('earliestStartTime'); + info.lastRunFinished = this.get('latestFinishTime'); + return info; + }.property('model.flowRuns', 'flowLastExecutionDate'), + + earliestStartTime: function() { + var earliestStart = Number.MAX_VALUE; + this.get('model.flowRuns').forEach(function(flowrun) { + if (flowrun.get('createTimeRaw') < earliestStart) { + earliestStart = flowrun.get('createTimeRaw'); + } + }); + return Converter.timeStampToDate(earliestStart); + }.property('model.flowRuns'), + + latestFinishTime: function() { + var latestFinish = 0; + this.get('model.flowRuns').forEach(function(flowrun) { + if (flowrun.get('endTimeRaw') > latestFinish) { + latestFinish = flowrun.get('endTimeRaw'); + } + }); + return Converter.timeStampToDate(latestFinish); + }.property('model.flowRuns') +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js new file mode 100644 index 0000000..7321437 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js @@ -0,0 +1,169 @@ +/** + * 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 TableDef from 'em-table/utils/table-definition'; +import ColumnDef from 'em-table/utils/column-definition'; +import Converter from 'yarn-ui/utils/converter'; + +function createColumn() { + var columns = []; + + // Generate columns + columns.push({ + id: 'runid', + headerTitle: 'Run ID', + contentPath: 'runid', + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-flowrun.info', + id: row.get('uid'), + displayText: row.get('shownid') + }; + } + }); + + columns.push({ + id: 'runDurationTs', + headerTitle: 'Run Duration', + contentPath: 'runDurationTs', + getCellContent: function(row) { + return Converter.msToElapsedTimeUnit(row.get('runDurationTs')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores' + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + getCellContent: function(row) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + }); + + columns.push({ + id: 'createTime', + headerTitle: 'Creation Time', + contentPath: 'createTime' + }); + + columns.push({ + id: 'endTime', + headerTitle: 'End Time', + contentPath: 'endTime' + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + vizWidgets: { + runDuration: true, + cpuVcores: false, + memoryUsed: false + }, + + actions: { + addVizWidget(widget) { + Ember.set(this.vizWidgets, widget, true); + }, + + removeVizWidget(widget) { + Ember.set(this.vizWidgets, widget, false); + } + }, + + columns: createColumn(), + + tableDefinition: TableDef.create({ + sortColumnId: 'createTime', + sortOrder: 'desc' + }), + + elapsedTimeVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getElapsedTimeVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + elapsedTimeFormatter: function(tick) { + return Converter.msToElapsedTimeUnit(tick, true); + }, + + cpuVCoresVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getCpuVCoresVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + memoryVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getMemoryVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.flowRuns'), + + memoryFormatter: function(tick) { + return Converter.memoryBytesToMB(tick); + }, + + onBarChartClick: function() { + var self = this; + return function(data) { + self.transitionToRoute('yarn-flowrun.info', data.flowrunUid); + }; + }.property(), + + getSortedVizDataInDesc: function(data) { + return data.sort(function(d1, d2) { + return d2.value - d1.value; + }); + }, + + getRefactoredVizData: function(data) { + data.forEach(function(viz, idx) { + viz.label = "Run " + (++idx); + }, this); + return data; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js new file mode 100644 index 0000000..6af87ab --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js @@ -0,0 +1,50 @@ +/** + * 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.flowrun_uid', 'model.parentFlowUid', function() { + var flowRunId = this.get('model.flowrun_uid'); + var parentFlowUid = this.get('model.parentFlowUid'); + var crumbs = [{ + text: "Home", + routeName: 'application' + }, { + text: "Flow Activities", + routeName: 'yarn-flow-activity' + }]; + if (parentFlowUid) { + crumbs.push({ + text: `Flow Info [${parentFlowUid}]`, + routeName: 'yarn-flow.info', + model: parentFlowUid + }, { + text: `Flow Runs [${parentFlowUid}]`, + routeName: 'yarn-flow.runs', + model: parentFlowUid + }); + } + crumbs.push({ + text: `Run Info [${flowRunId}]`, + routeName: 'yarn-flowrun.info', + model: flowRunId + }); + return crumbs; + }) +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js new file mode 100644 index 0000000..a58ed81 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js @@ -0,0 +1,147 @@ +/** + * 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 ColumnDef from 'em-table/utils/column-definition'; +import Converter from 'yarn-ui/utils/converter'; + +function createColumn() { + var columns = []; + + // Generate columns + columns.push({ + id: 'appId', + headerTitle: 'Application ID', + contentPath: 'appId', + cellComponentName: 'em-table-linked-cell', + minWidth: "300px", + getCellContent: function (row) { + return { + routeName: 'yarn-app', + id: row.get('appId'), + displayText: row.get('appId') + }; + } + }); + + columns.push({ + id: 'appType', + headerTitle: 'Application Type', + contentPath: 'type' + }); + + columns.push({ + id: 'state', + headerTitle: 'State', + contentPath: 'state', + cellComponentName: 'em-table-status-cell', + }); + + columns.push({ + id: 'elapsedTs', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTs', + getCellContent: function(row) { + return Converter.msToElapsedTimeUnit(row.get('elapsedTs')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores' + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + getCellContent: function(row) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + vizWidgets: { + cpuVcores: true, + memoryUsed: false + }, + + actions: { + addVizWidget(widget) { + Ember.set(this.vizWidgets, widget, true); + }, + + removeVizWidget(widget) { + Ember.set(this.vizWidgets, widget, false); + } + }, + + columns: createColumn(), + + cpuVCoresVizData: function() { + var data = []; + this.get('model.apps').forEach(function(app) { + var vizData = app.getCpuVCoresVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.apps'), + + memoryVizData: function() { + var data = []; + this.get('model.apps').forEach(function(app) { + var vizData = app.getMemoryVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + data = this.getSortedVizDataInDesc(data); + return this.getRefactoredVizData(data); + }.property('model.apps'), + + memoryFormatter: function(tick) { + return Converter.memoryBytesToMB(tick); + }, + + onBarChartClick: function() { + var self = this; + return function(data) { + self.transitionToRoute('yarn-app', data.label); + }; + }.property(), + + getSortedVizDataInDesc: function(data) { + return data.sort(function(d1, d2) { + return d2.value - d1.value; + }); + }, + + getRefactoredVizData: function(data) { + data.forEach(function(viz, idx) { + viz.label = "App " + (++idx); + }, this); + return data; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js new file mode 100644 index 0000000..97b1e07 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js @@ -0,0 +1,126 @@ +/** + * 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 ColumnDef from 'em-table/utils/column-definition'; + +function _createColumns() { + var columns = []; + + columns.push({ + id: 'name', + headerTitle: 'Name', + contentPath: 'name', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + var plainName = row.name; + if (plainName.indexOf('MAP:') > -1 || plainName.indexOf('REDUCE:') > -1) { + plainName = plainName.substring(plainName.indexOf(':') + 1); + } + return `${plainName}`; + } + }, { + id: 'value', + headerTitle: 'Value', + contentPath: 'value', + observePath: true + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + mapMetrics: null, + reduceMetrics: null, + generalMetrics: null, + + columns: Ember.computed(function() { + return _createColumns(this.get('model.flowrun_uid')); + }), + + metricsObserver: Ember.observer('model.flowrun', function() { + var metrics = this.get('model.flowrun.metrics'); + var mapConfigs = [], + reduceConfigs = [], + generalConfigs = []; + + metrics.forEach(function(metric) { + let id = metric.id; + if (id.startsWith('MAP:')) { + mapConfigs.push(metric); + } else if (id.startsWith('REDUCE:')) { + reduceConfigs.push(metric); + } else { + generalConfigs.push(metric); + } + }, this); + + this.set('mapMetrics', mapConfigs); + this.set('reduceMetrics', reduceConfigs); + this.set('generalMetrics', generalConfigs); + }), + + mapConfigRows: Ember.computed('mapMetrics', function() { + var row = null, + data = []; + + this.get('mapMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }), + + reduceConfigRows: Ember.computed('reduceMetrics', function() { + var row = null, + data = []; + + this.get('reduceMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }), + + generalConfigRows: Ember.computed('generalMetrics', function() { + var row = null, + data = []; + + this.get('generalMetrics').forEach(function(map) { + let value = map.values[Object.keys(map.values)[0]]; + row = Ember.Object.create({ + name: map.id, + value: value + }); + data.push(row); + }, this); + + return Ember.A(data); + }) +}); 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 index eeb6205..a2c80f7 100644 --- 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 @@ -18,9 +18,19 @@ import Ember from 'ember'; import AppTableController from './app-table-columns'; - +import TableDefinition from 'em-table/utils/table-definition'; export default AppTableController.extend({ + queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'], + tableDefinition: TableDefinition.create({ + sortColumnId: 'stTime', + sortOrder: 'desc' + }), + searchText: Ember.computed.alias('tableDefinition.searchText'), + sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'), + sortOrder: Ember.computed.alias('tableDefinition.sortOrder'), + pageNum: Ember.computed.alias('tableDefinition.pageNum'), + rowCount: Ember.computed.alias('tableDefinition.rowCount'), breadcrumbs: [{ text: "Home", diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/single-metric-table.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/single-metric-table.js new file mode 100644 index 0000000..662bec1 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/single-metric-table.js @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +/** + * Represent log files as comma separated list. + */ +export default Ember.Helper.helper(function(params,hash) { + var metrics = hash.metrics; + var uid = hash.uid; + var html = '| '; + if (metrics[i].values[j] > 0) { + html = html + '' + metrics[i].id + ' | '; + } else { + html = html + metrics[i].id + ''; + } + html = html + '' + metrics[i].values[j] + ' | '; + html = html + '
Id:" + this.get("id") + - "
ElapsedTime:" + + return "
Id:" + this.get("id") + + "
ElapsedTime:" + String(this.get("elapsedTime")) + "
"; }.property(), @@ -141,4 +140,4 @@ export default DS.Model.extend({ return this.get("state"); }.property(), -}); \ No newline at end of file +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js new file mode 100644 index 0000000..a8a7471 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.Model.extend({ + appId: DS.attr('string'), + type: DS.attr('string'), + uid: DS.attr('string'), + metrics: DS.attr('array'), + startedTs: DS.attr('number'), + finishedTs: DS.attr('number'), + state: DS.attr('string'), + cpuVCores: DS.attr('number'), + memoryUsed: DS.attr('number'), + + elapsedTs: function() { + return this.get('finishedTs') - this.get('startedTs'); + }.property('startedTs', 'finishedTs'), + + getCpuVCoresVizDataForBarChart: function() { + return { + label: this.get('appId'), + value: this.get('cpuVCores'), + tooltip: this.get("appId") + "Id:" + this.get("id") + - "
ElapsedTime:" + + return "
Id:" + this.get("id") + + "
ElapsedTime:" + String(this.get("elapsedTime")) + "
"; }.property(), -}); \ No newline at end of file +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js new file mode 100644 index 0000000..a06d6ab --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.Model.extend({ + entityId: DS.attr('string'), + type: DS.attr('string'), + uid: DS.attr('string'), + metrics: DS.attr('array') +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js new file mode 100644 index 0000000..1095cfe --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.Model.extend({ + cluster: DS.attr('string'), + flowName: DS.attr('string'), + lastExecDate: DS.attr('string'), + user: DS.attr('string'), + flowruns: DS.attr('string'), + uid: DS.attr('string') +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flowrun-brief.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flowrun-brief.js new file mode 100644 index 0000000..8d9fca3 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flowrun-brief.js @@ -0,0 +1,70 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.Model.extend({ + flowName: DS.attr('string'), + runid: DS.attr('string'), + shownid: DS.attr('string'), + type: DS.attr('string'), + createTime: DS.attr('string'), + createTimeRaw: DS.attr(), + endTime: DS.attr('string'), + endTimeRaw: DS.attr(), + user: DS.attr('string'), + uid: DS.attr('string'), + cpuVCores: DS.attr('number'), + memoryUsed: DS.attr('number'), + + runDurationTs: function() { + var duration = this.get('endTimeRaw') - this.get('createTimeRaw'); + if (duration <= 0) { + duration = Date.now() - this.get('createTimeRaw'); + } + return duration; + }.property('createTimeRaw', 'endTimeRaw'), + + getElapsedTimeVizDataForBarChart: function() { + return { + label: this.get('runid'), + value: this.get('runDurationTs'), + tooltip: this.get("shownid") + "| ' + metrics[i].id + ' | '; + for(var j in metrics[i].values){ + html = html + '' + metrics[i].values[j] + ' | '; + break; + } + html = html + '
Id:" + this.get("id") + + "
ElapsedTime:" + + String(this.get("elapsedTime")) + "
"; + }.property(), + + link: function() { + return "/yarn-app-attempt/" + this.get("id"); + }.property(), + + linkname: function() { + return "yarn-app-attempt"; + }.property(), + + attemptState: function() { + return this.get("state"); + }.property(), + +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-timeline-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-timeline-container.js new file mode 100644 index 0000000..7f39345 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-timeline-container.js @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.Model.extend({ + allocatedMB: DS.attr('number'), + allocatedVCores: DS.attr('number'), + assignedNodeId: DS.attr('string'), + priority: DS.attr('number'), + startedTime: DS.attr('number'), + finishedTime: DS.attr('number'), + logUrl: DS.attr('string'), + containerExitStatus: DS.attr('number'), + containerState: DS.attr('string'), + nodeHttpAddress: DS.attr('string'), + + startTs: function() { + return Converter.dateToTimeStamp(this.get("startedTime")); + }.property("startedTime"), + + finishedTs: function() { + var ts = Converter.dateToTimeStamp(this.get("finishedTime")); + return ts; + }.property("finishedTime"), + + validatedFinishedTs: function() { + if (this.get("finishedTs") < this.get("startTs")) { + return ""; + } + return this.get("finishedTime"); + }.property("finishedTime"), + + elapsedTime: function() { + var elapsedMs = this.get("finishedTs") - this.get("startTs"); + if (elapsedMs <= 0) { + elapsedMs = Date.now() - this.get("startTs"); + } + return Converter.msToElapsedTimeUnit(elapsedMs); + }.property(), + + tooltipLabel: function() { + return "Id:" + this.get("id") + + "
ElapsedTime:" + + String(this.get("elapsedTime")) + "
"; + }.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 a45861e..00d6d3e 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 @@ -56,6 +56,18 @@ Router.map(function() { 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-flow-activity'); + this.route('yarn-flow', { path: '/yarn-flow/:flow_uid'}, function() { + this.route('info'); + this.route('runs'); + }); + this.route('yarn-flowrun', { path: '/yarn-flowrun/:flowrun_uid'}, function() { + this.route('info'); + this.route('metrics'); + }); + this.route('yarn-flowrun-metric', { path: '/yarn-flowrun-metric/:flowrun_uid/:metric_id'}); + this.route('timeline-error', {path: 'timeline-error/:error_id'}); }); export default Router; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/timeline-error.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/timeline-error.js new file mode 100644 index 0000000..c2e5fc5 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/timeline-error.js @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Route.extend({ + afterModel(model/*, transition*/) { + model.error_id = "error"; + model.isValidErrorCode = false; + if (model.errorCode && model.errorCode !== "0") { + model.isValidErrorCode = true; + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js index d449adf..b561bf6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js @@ -17,34 +17,28 @@ */ import Ember from 'ember'; - import AbstractRoute from './abstract'; +import AppAttemptMixin from 'yarn-ui/mixins/app-attempt'; -export default AbstractRoute.extend({ +export default AbstractRoute.extend(AppAttemptMixin, { model(param) { return Ember.RSVP.hash({ - attempt: this.store.findRecord('yarn-app-attempt', param.app_attempt_id, {reload: true}), - - rmContainers: this.store.query('yarn-container', - { - app_attempt_id: param.app_attempt_id, - is_rm: true - }), - - tsContainers: this.store.query('yarn-container', - { - app_attempt_id: param.app_attempt_id, - is_rm: false - }).catch (function() { - // Promise rejected, fulfill with some default value to - // use as the route's model and continue on with the transition - return []; - }) + attempt: this.fetchAttemptInfoFromRMorATS(param.app_attempt_id, this.store), + rmContainers: this.store.query('yarn-container', { + app_attempt_id: param.app_attempt_id + }), + tsContainers: this.store.query('yarn-timeline-container', { + app_attempt_id: param.app_attempt_id + }).catch(function() { + return []; + }) }); }, unloadAll() { this.store.unloadAll('yarn-app-attempt'); + this.store.unloadAll('yarn-timeline-appattempt'); this.store.unloadAll('yarn-container'); + this.store.unloadAll('yarn-timeline-container'); } }); 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 index 78ff1c9..233bfc8 100644 --- 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 @@ -16,19 +16,20 @@ * limitations under the License. */ +import Ember from 'ember'; import AbstractRoute from './abstract'; +import AppAttemptMixin from 'yarn-ui/mixins/app-attempt'; -export default AbstractRoute.extend({ +export default AbstractRoute.extend(AppAttemptMixin, { model(param) { - return this.store.query('yarn-app-attempt', { appId: param.app_id}).then(function (attempts) { - return { - appId: param.app_id, - attempts: attempts - }; + return Ember.RSVP.hash({ + appId: param.app_id, + attempts: this.fetchAttemptListFromRMorATS(param.app_id, this.store) }); }, unloadAll() { this.store.unloadAll('yarn-app-attempt'); + this.store.unloadAll('yarn-timeline-appattempt'); } }); 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 86d845c..98b0cc8 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 @@ -17,29 +17,26 @@ */ import Ember from 'ember'; - import AbstractRoute from './abstract'; +import AppAttemptMixin from 'yarn-ui/mixins/app-attempt'; -export default AbstractRoute.extend({ +export default AbstractRoute.extend(AppAttemptMixin, { model(param) { return Ember.RSVP.hash({ - app: this.store.find('yarn-app', param.app_id), + app: this.fetchAppInfoFromRMorATS(param.app_id, this.store), rmContainers: this.store.find('yarn-app', param.app_id).then(function() { 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; + return this.store.query('yarn-container', { + app_attempt_id: appAttemptId + }); } }.bind(this)); }.bind(this)), - nodes: this.store.findAll('yarn-rm-node'), + nodes: this.store.findAll('yarn-rm-node', {reload: true}), }); }, @@ -48,5 +45,6 @@ export default AbstractRoute.extend({ this.store.unloadAll('yarn-app-attempt'); this.store.unloadAll('yarn-container'); this.store.unloadAll('yarn-rm-node'); + this.store.unloadAll('yarn-app-timeline'); } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow-activity.js new file mode 100644 index 0000000..4c1d02e --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow-activity.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 AbstractRoute from './abstract'; +import ErrorUtils from 'yarn-ui/utils/error-utils'; + +export default AbstractRoute.extend({ + model() { + return this.store.findAll('yarn-flow-activity', {reload: true}); + }, + + unloadAll() { + this.store.unloadAll('yarn-flow-activity'); + }, + + actions: { + error(err/*, transition*/) { + var errObj = ErrorUtils.stripErrorCodeAndMessageFromError(err); + this.transitionTo('timeline-error', errObj); + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow.js new file mode 100644 index 0000000..1da9064 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow.js @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +import AbstractRoute from './abstract'; +import ErrorUtils from 'yarn-ui/utils/error-utils'; + +export default AbstractRoute.extend({ + model(params) { + return Ember.RSVP.hash({ + flowRuns: this.store.query('yarn-flowrun-brief', {flowuid: params.flow_uid}), + flowUid: params.flow_uid, + lastFlowExecutionInfo: this.getLastFlowExecutionInfo(params.flow_uid) + }); + }, + + getLastFlowExecutionInfo(flowUid) { + var yarnfaCtrl = this.controllerFor('yarn-flow-activity'); + var recentFlow = yarnfaCtrl.getLastFlowExecutionInfoByFlowUid(flowUid); + if (recentFlow) { + return recentFlow; + } else { + return null; + } + }, + + unloadAll() { + this.store.unloadAll('yarn-flowrun-brief'); + }, + + actions: { + error(err/*, transition*/) { + var errObj = ErrorUtils.stripErrorCodeAndMessageFromError(err); + this.transitionTo('timeline-error', errObj); + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow/info.js new file mode 100644 index 0000000..8719170 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow/info.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-flow/runs.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow/runs.js new file mode 100644 index 0000000..8719170 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow/runs.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-flowrun-metric.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun-metric.js new file mode 100644 index 0000000..f77f1c2 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun-metric.js @@ -0,0 +1,115 @@ +/** + * 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 ErrorUtils from 'yarn-ui/utils/error-utils'; + +export default Ember.Route.extend({ + model: function(params) { + var _this = this; + var appsArr = []; + var flowrun = _this.store.queryRecord('yarn-flowrun', {flowrun_uid: params.flowrun_uid, + metricstoretrieve: params.metric_id}).then(function(value) { + var apps = _this.store.query('yarn-app-flowrun', {flowrunUid: params.flowrun_uid, + metricstoretrieve: params.metric_id}).then(function(value) { + for (var i = 0; i < value.content.length; i++) { + var tasks = undefined; + // No need to fetch task or container info for Job counters. + if (params.metric_id.indexOf("JobCounter") === -1) { + var entityType = "MAPREDUCE_TASK"; + // CPU and MEMORY are container metrics. + if (params.metric_id === "CPU" || params.metric_id === "MEMORY") { + entityType = "YARN_CONTAINER"; + } + // tasks = _this.store.query('yarn-entity', {app_uid: value.content[i]._data.uid, metricslimit: 100, + // metricstoretrieve: params.metric_id, entity_type: entityType}).then(function(value) { + // var tasksArr = []; + // for (var j = 0; j < value.content.length; j++) { + // tasksArr.push(Ember.RSVP.hash({id: value.content[j].id, metrics: value.content[j]._data.metrics})); + // } + // return Ember.RSVP.all(tasksArr); + // }); + tasks = _this.fetchTasksForEntity(value.content[i]._data.uid, params.metric_id, entityType); + } + appsArr.push(Ember.RSVP.hash({id: value.content[i].id, tasks: tasks , metrics: value.content[i]._data.metrics})); + } + return Ember.RSVP.all(appsArr); + }); + return Ember.RSVP.hash({run: value, id: value.id, metrics: value._internalModel._data.metrics, apps: apps}); + }); + return Ember.RSVP.all([Ember.RSVP.hash({flowrun:flowrun, metricId: params.metric_id})]); + }, + + fetchTasksForEntity: function(appUid, metricId, entityType) { + return this.store.query('yarn-entity', { + app_uid: appUid, + metricstoretrieve: metricId, + entity_type: entityType, + metricslimit: 100 + }).then(function(value) { + var tasksArr = []; + for (var j = 0; j < value.content.length; j++) { + tasksArr.push(Ember.RSVP.hash({id: value.content[j].id, metrics: value.content[j]._data.metrics})); + } + return Ember.RSVP.all(tasksArr); + }); + }, + + getMetricValue: function(metrics) { + var metricValue = 0; + if (metrics.length > 0) { + for (var j in metrics[0].values) { + metricValue = metrics[0].values[j]; + break; + } + } + return metricValue.toString(); + }, + + setupController: function(controller, model) { + var metricsArr = []; + var flowRunId = model[0].flowrun.id; + metricsArr.push([model[0].flowrun.id, this.getMetricValue(model[0].flowrun.metrics)]); + for (var i = 0; i < model[0].flowrun.apps.length; i++) { + var appId = flowRunId + '-' + model[0].flowrun.apps[i].id; + metricsArr.push([appId, this.getMetricValue(model[0].flowrun.apps[i].metrics)]); + if (model[0].flowrun.apps[i].tasks) { + for (var j = 0; j < model[0].flowrun.apps[i].tasks.length; j++) { + var taskId = appId + '-' + model[0].flowrun.apps[i].tasks[j].id; + metricsArr.push([taskId, this.getMetricValue(model[0].flowrun.apps[i].tasks[j].metrics)]); + } + } + } + controller.set('flowrun', model[0].flowrun); + controller.set('metric_id', model[0].metricId); + controller.set('arr', metricsArr); + }, + + unloadAll: function() { + this.store.unloadAll('yarn-flowrun'); + this.store.unloadAll('yarn-app-flowrun'); + this.store.unloadAll('yarn-entity'); + }, + + actions: { + error(err/*, transition*/) { + var errObj = ErrorUtils.stripErrorCodeAndMessageFromError(err); + this.transitionTo('timeline-error', errObj); + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun.js new file mode 100644 index 0000000..3163a67 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun.js @@ -0,0 +1,58 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +import AbstractRoute from './abstract'; +import ErrorUtils from 'yarn-ui/utils/error-utils'; + +export default AbstractRoute.extend({ + model: function(params) { + return Ember.RSVP.hash({ + flowrun: this.store.findRecord('yarn-flowrun', params.flowrun_uid), + apps: this.store.query('yarn-app-flowrun', {flowrunUid: params.flowrun_uid}), + flowrun_uid: params.flowrun_uid, + parentFlowUid: this.getParentFlowUid() + }); + }, + + getParentFlowUid: function() { + var parentFlowModel = this.modelFor('yarn-flow'); + if (parentFlowModel) { + return parentFlowModel.flowUid; + } else { + return ''; + } + }, + + unloadAll: function() { + this.store.unloadAll('yarn-flowrun'); + this.store.unloadAll('yarn-app-flowrun'); + }, + + actions: { + reload: function() { + this.modelFor('apps').reload(); + }, + + error(err/*, transition*/) { + var errObj = ErrorUtils.stripErrorCodeAndMessageFromError(err); + this.transitionTo('timeline-error', errObj); + } + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun/info.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun/info.js new file mode 100644 index 0000000..8719170 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun/info.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-flowrun/metrics.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun/metrics.js new file mode 100644 index 0000000..8719170 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun/metrics.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/serializers/yarn-app-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-flowrun.js new file mode 100644 index 0000000..2fa0694 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-flowrun.js @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.JSONAPISerializer.extend({ + + normalizeSingleResponse(store, primaryModelClass, payload, id, + requestType) { + var events = payload.events, + appFinishedEvent = events.findBy('id', 'YARN_APPLICATION_FINISHED'), + finishedTs = appFinishedEvent? appFinishedEvent.timestamp : Date.now(), + metrics = payload.metrics, + cpuMetric = metrics.findBy('id', 'CPU'), + memoryMetric = metrics.findBy('id', 'MEMORY'), + cpu = cpuMetric? cpuMetric.values[Object.keys(cpuMetric.values)[0]] : 0, + memory = memoryMetric? memoryMetric.values[Object.keys(memoryMetric.values)[0]] : 0; + + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, + attributes: { + appId: payload.id, + type: payload.info.YARN_APPLICATION_TYPE, + uid: payload.info.UID, + metrics: metrics, + startedTs: payload.createdtime, + finishedTs: finishedTs, + state: payload.info.YARN_APPLICATION_STATE, + cpuVCores: cpu, + memoryUsed: memory + } + }; + + return this._super(store, primaryModelClass, fixedPayload, id, requestType); + }, + + normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) { + var normalizedArrayResponse = {}; + + normalizedArrayResponse.data = payload.map(singleApp => { + return this.normalizeSingleResponse(store, primaryModelClass, + singleApp, singleApp.id, requestType); + }); + + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-timeline.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-timeline.js new file mode 100644 index 0000000..680fe8c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-timeline.js @@ -0,0 +1,76 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + internalNormalizeSingleResponse(store, primaryModelClass, payload, id) { + + var events = payload.events, + appFinishedEvent = events.findBy('id', 'YARN_APPLICATION_FINISHED'), + startedTime = payload.createdtime, + finishedTime = appFinishedEvent? appFinishedEvent.timestamp : Date.now(), + elapsedTime = finishedTime - startedTime, + diagnostics = payload.info.YARN_APPLICATION_DIAGNOSTICS_INFO, + priority = payload.info.YARN_APPLICATION_PRIORITY; + + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, + attributes: { + appName: payload.info.YARN_APPLICATION_NAME, + user: payload.info.YARN_APPLICATION_USER, + queue: "N/A", + state: payload.info.YARN_APPLICATION_STATE, + startTime: Converter.timeStampToDate(startedTime), + elapsedTime: elapsedTime, + finishedTime: Converter.timeStampToDate(finishedTime), + finalStatus: payload.info.YARN_APPLICATION_FINAL_STATUS, + progress: 100, + applicationType: payload.info.YARN_APPLICATION_TYPE, + diagnostics: (diagnostics && diagnostics !== 'null')? diagnostics : '', + amContainerLogs: '', + amHostHttpAddress: '', + logAggregationStatus: '', + unmanagedApplication: payload.info.YARN_APPLICATION_UNMANAGED_APPLICATION || 'N/A', + amNodeLabelExpression: payload.configs.YARN_AM_NODE_LABEL_EXPRESSION, + priority: (priority !== undefined)? priority : 'N/A', + allocatedMB: 0, + allocatedVCores: 0, + runningContainers: 0, + memorySeconds: payload.info.YARN_APPLICATION_MEM_METRIC, + vcoreSeconds: payload.info.YARN_APPLICATION_CPU_METRIC, + preemptedResourceMB: 0, + preemptedResourceVCores: 0, + numNonAMContainerPreempted: 0, + numAMContainerPreempted: 0, + clusterUsagePercentage: 0, + queueUsagePercentage: 0, + currentAppAttemptId: payload.info.YARN_APPLICATION_LATEST_APP_ATTEMPT + } + }; + + return fixedPayload; + }, + + normalizeSingleResponse(store, primaryModelClass, payload, id/*, requestType*/) { + var p = this.internalNormalizeSingleResponse(store, primaryModelClass, payload, id); + return {data: p}; + } +}); 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 172286f..1462f5a 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 @@ -43,7 +43,6 @@ export default DS.JSONAPISerializer.extend({ queue: payload.queue, state: payload.state, startTime: Converter.timeStampToDate(payload.startedTime), - //elapsedTime: Converter.msToElapsedTime(payload.elapsedTime), elapsedTime: payload.elapsedTime, finishedTime: Converter.timeStampToDate(payload.finishedTime), finalStatus: payload.finalStatus, @@ -55,7 +54,7 @@ export default DS.JSONAPISerializer.extend({ logAggregationStatus: payload.logAggregationStatus, unmanagedApplication: payload.unmanagedApplication || 'N/A', amNodeLabelExpression: payload.amNodeLabelExpression, - priority: payload.priority || 'N/A', + priority: (payload.priority !== undefined)? payload.priority : 'N/A', allocatedMB: payload.allocatedMB, allocatedVCores: payload.allocatedVCores, runningContainers: payload.runningContainers, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-entity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-entity.js new file mode 100644 index 0000000..9ed70cf --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-entity.js @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; + +export default DS.JSONAPISerializer.extend({ + + normalizeSingleResponse(store, primaryModelClass, payload, id, + requestType) { + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, // yarn-entity + attributes: { + entityId: payload.id, + type: payload.type, + uid: payload.info.UID, + metrics: payload.metrics + } + }; + + return this._super(store, primaryModelClass, fixedPayload, id, + requestType); + }, + + normalizeArrayResponse(store, primaryModelClass, payload, id, + requestType) { + // return expected is { data: [ {}, {} ] } + var normalizedArrayResponse = {}; + + normalizedArrayResponse.data = payload.map(singleApp => { + return this.normalizeSingleResponse(store, primaryModelClass, + singleApp, singleApp.id, requestType); + }, this); + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flow-activity.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flow-activity.js new file mode 100644 index 0000000..c26872b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flow-activity.js @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + + normalizeSingleResponse(store, primaryModelClass, payload, id, + requestType) { + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, // yarn-timeline-flow + attributes: { + cluster: payload.info.SYSTEM_INFO_CLUSTER, + flowName: payload.info.SYSTEM_INFO_FLOW_NAME, + lastExecDate: Converter.timeStampToDateOnly(payload.info.SYSTEM_INFO_DATE), + user: payload.info.SYSTEM_INFO_USER, + flowruns: payload.flowruns, + uid: payload.info.UID + } + }; + + return this._super(store, primaryModelClass, fixedPayload, id, + requestType); + }, + + normalizeArrayResponse(store, primaryModelClass, payload, id, + requestType) { + // return expected is { data: [ {}, {} ] } + var normalizedArrayResponse = {}; + + normalizedArrayResponse.data = payload.map(singleEntity => { + return this.normalizeSingleResponse(store, primaryModelClass, + singleEntity, singleEntity.id, requestType); + }, this); + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun-brief.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun-brief.js new file mode 100644 index 0000000..88b0361 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun-brief.js @@ -0,0 +1,64 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + + normalizeSingleResponse(store, primaryModelClass, payload, id, + requestType) { + var metrics = payload.metrics, + cpuMetric = metrics.findBy('id', 'CPU'), + cpu = cpuMetric? cpuMetric.values[Object.keys(cpuMetric.values)[0]] : 0, + memMetric = metrics.findBy('id', 'MEMORY'), + memory = memMetric? memMetric.values[Object.keys(memMetric.values)[0]] : 0; + + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, // yarn-flowrun-brief + attributes: { + flowName: payload.info.SYSTEM_INFO_FLOW_NAME, + runid: payload.info.SYSTEM_INFO_FLOW_RUN_ID, + shownid: payload.id, + type: payload.type, + createTime: Converter.timeStampToDate(payload.createdtime), + createTimeRaw: payload.createdtime, + endTime: Converter.timeStampToDate(payload.info.SYSTEM_INFO_FLOW_RUN_END_TIME), + endTimeRaw: payload.info.SYSTEM_INFO_FLOW_RUN_END_TIME || 0, + user: payload.info.SYSTEM_INFO_USER, + uid: payload.info.UID, + cpuVCores: cpu, + memoryUsed: memory + } + }; + + return this._super(store, primaryModelClass, fixedPayload, id, requestType); + }, + + normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) { + var normalizedArrayResponse = {data: []}; + + normalizedArrayResponse.data = payload.map(singleApp => { + return this.normalizeSingleResponse(store, primaryModelClass, + singleApp, singleApp.id, requestType); + }); + + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun.js new file mode 100644 index 0000000..931d134 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun.js @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + + internalNormalizeSingleResponse(store, primaryModelClass, payload, id) { + var recordId = id; + if (!recordId) { + recordId = payload.id; + } + var fixedPayload = { + id: recordId, + type: primaryModelClass.modelName, + attributes: { + flowName: payload.info.SYSTEM_INFO_FLOW_NAME, + runid: payload.info.SYSTEM_INFO_FLOW_RUN_ID, + shownid: payload.id, + type: payload.type, + createTime: Converter.timeStampToDate(payload.createdtime), + endTime: Converter.timeStampToDate(payload.info.SYSTEM_INFO_FLOW_RUN_END_TIME), + user: payload.info.SYSTEM_INFO_USER, + metrics: payload.metrics, + } + }; + + return fixedPayload; + }, + + normalizeSingleResponse(store, primaryModelClass, payload, id/*, requestType*/) { + var p = this.internalNormalizeSingleResponse(store, + primaryModelClass, payload, id); + return { data: p }; + }, + + normalizeArrayResponse(store, primaryModelClass, payload/*, id, requestType*/) { + // return expected is { data: [ {}, {} ] } + var normalizedArrayResponse = {}; + + normalizedArrayResponse.data = payload.map(singleApp => { + return this.internalNormalizeSingleResponse(store, primaryModelClass, + singleApp, singleApp.id); + }, this); + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-queue.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-queue.js index 766c5c7..4fc1a29 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-queue.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-queue.js @@ -116,30 +116,14 @@ export default DS.JSONAPISerializer.extend({ }; }, - normalizeArrayResponse(store, primaryModelClass, payload, id, - requestType) { + normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) { var normalizedArrayResponse = {}; - var result = this.handleQueue(store, - primaryModelClass, + var result = this.handleQueue(store, primaryModelClass, payload.scheduler.schedulerInfo, "root", requestType); normalizedArrayResponse.data = result.data; normalizedArrayResponse.included = result.includedData; - console.log(normalizedArrayResponse); - - return normalizedArrayResponse; - - /* - // 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.apps.app.map(singleApp => { - return this.normalizeSingleResponse(store, primaryModelClass, singleApp, singleApp.id, requestType); - }, this); 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-timeline-appattempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-appattempt.js new file mode 100644 index 0000000..0245b20 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-appattempt.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 DS from 'ember-data'; +import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + internalNormalizeSingleResponse(store, primaryModelClass, payload) { + var payloadEvents = payload.events, + createdEvent = payloadEvents.filterBy('id', 'YARN_APPLICATION_ATTEMPT_REGISTERED')[0], + startedTime = createdEvent? createdEvent.timestamp : Date.now(), + finishedEvent = payloadEvents.filterBy('id', 'YARN_APPLICATION_ATTEMPT_FINISHED')[0], + finishedTime = finishedEvent? finishedEvent.timestamp : Date.now(); + + var fixedPayload = { + id: payload.id, + type: primaryModelClass.modelName, + attributes: { + startTime: Converter.timeStampToDate(startedTime), + startedTime: Converter.timeStampToDate(startedTime), + finishedTime: Converter.timeStampToDate(finishedTime), + containerId: payload.info.YARN_APPLICATION_ATTEMPT_MASTER_CONTAINER, + amContainerId: payload.info.YARN_APPLICATION_ATTEMPT_MASTER_CONTAINER, + nodeHttpAddress: '', + nodeId: '', + hosts: payload.info.YARN_APPLICATION_ATTEMPT_HOST, + state: payload.info.YARN_APPLICATION_ATTEMPT_HOST, + logsLink: '', + appAttemptId: payload.id + } + }; + return fixedPayload; + }, + + normalizeSingleResponse(store, primaryModelClass, payload/*, id, requestType*/) { + var normalized = this.internalNormalizeSingleResponse(store, + primaryModelClass, payload); + return {data: normalized}; + }, + + normalizeArrayResponse(store, primaryModelClass, payload/*, id, requestType*/) { + var normalizedArrayResponse = { + data: [] + }; + if (payload && Ember.isArray(payload) && !Ember.isEmpty(payload)) { + normalizedArrayResponse.data = payload.map(singleAttempt => { + return this.internalNormalizeSingleResponse(store, primaryModelClass, + singleAttempt); + }); + } + return normalizedArrayResponse; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-container.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-container.js new file mode 100644 index 0000000..f2c60f6 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-container.js @@ -0,0 +1,71 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import DS from 'ember-data'; +import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; + +export default DS.JSONAPISerializer.extend({ + internalNormalizeSingleResponse(store, primaryModelClass, payload) { + var payloadEvents = payload.events, + createdEvent = payloadEvents.filterBy('id', 'YARN_RM_CONTAINER_CREATED')[0], + startedTime = createdEvent? createdEvent.timestamp : Date.now(), + finishedEvent = payloadEvents.filterBy('id', 'YARN_RM_CONTAINER_FINISHED')[0], + finishedTime = finishedEvent? finishedEvent.timestamp : Date.now(), + containerExitStatus = finishedEvent? finishedEvent.info.YARN_CONTAINER_EXIT_STATUS : '', + containerState = finishedEvent? finishedEvent.info.YARN_CONTAINER_STATE : ''; + + var fixedPayload = { + id: payload.id, + type: primaryModelClass.modelName, + attributes: { + allocatedMB: payload.info.YARN_CONTAINER_ALLOCATED_MEMORY, + allocatedVCores: payload.info.YARN_CONTAINER_ALLOCATED_VCORE, + assignedNodeId: payload.info.YARN_CONTAINER_ALLOCATED_HOST, + priority: payload.info.YARN_CONTAINER_ALLOCATED_PRIORITY, + startedTime: Converter.timeStampToDate(startedTime), + finishedTime: Converter.timeStampToDate(finishedTime), + nodeHttpAddress: payload.info.YARN_CONTAINER_ALLOCATED_HOST_HTTP_ADDRESS, + containerExitStatus: containerExitStatus, + containerState: containerState + } + }; + return fixedPayload; + }, + + normalizeSingleResponse(store, primaryModelClass, payload/*, id, requestType*/) { + var normalized = this.internalNormalizeSingleResponse(store, + primaryModelClass, payload); + return { + data: normalized + }; + }, + + normalizeArrayResponse(store, primaryModelClass, payload/*, id, requestType*/) { + var normalizedArrayResponse = { + data: [] + }; + if (payload && Ember.isArray(payload) && !Ember.isEmpty(payload)) { + normalizedArrayResponse.data = payload.map(singleContainer => { + return this.internalNormalizeSingleResponse(store, primaryModelClass, + singleContainer); + }); + } + return normalizedArrayResponse; + } +}); 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 e3dfcd9..8b8ea56 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 @@ -314,3 +314,86 @@ div.attempt-info-panel table > tbody > tr > td:last-of-type { overflow: hidden; text-overflow: ellipsis; } + +#main { + float: left; + width: 750px; +} + +#sidebar { + float: right; + width: 100px; +} + +#sequence { + width: 600px; + height: 70px; +} + +#legend { + padding: 10px 0 0 3px; +} + +#sequence text, #legend text { + font-weight: 600; + fill: #fff; +} + +#chart { + position: relative; +} + +#chart path { + stroke: #fff; +} + +#explanation { + position: absolute; + top: 360px; + left: 385px; + width: 230px; + text-align: center; + color: #666; + z-index: -1; +} + +.simple-bar-chart .axis text { + font: 10px sans-serif; +} + +.simple-bar-chart .axis path, .simple-bar-chart .axis line { + fill: none; + stroke: #000; + stroke-width: 1px; +} + +.simple-bar-chart rect { + fill: steelblue; +} + +.simple-bar-chart rect:hover { + fill: brown; + cursor: pointer; +} + +.yarn-flow-runs .chart-panel, .yarn-flow-runinfo .chart-panel { + overflow: auto; +} + +.yarn-flow-runs .glyphicon-remove, .yarn-flow-runinfo .glyphicon-remove { + cursor: pointer; +} + +.yarn-flow-runs .glyphicon-remove:hover, .yarn-flow-runinfo .glyphicon-remove:hover { + color: #c9302c; +} + +.yarn-flow-runs .dropdown-menu .item-text, .yarn-flow-runinfo .dropdown-menu .item-text { + width: auto; + display: inline-block; +} + +.yarn-flow-runs .dropdown-menu .item-icon, .yarn-flow-runinfo .dropdown-menu .item-icon { + width: 14px; + display: inline-block; +} 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 a6d247b..c3154b4 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 @@ -56,6 +56,11 @@ (current) {{/link-to}} {{/link-to}} + {{#link-to 'yarn-flow-activity' tagName="li"}} + {{#link-to 'yarn-flow-activity' class="navigation-link"}}Flow Activity + (current) + {{/link-to}} + {{/link-to}} {{#link-to 'yarn-nodes.table' tagName="li" current-when="yarn-nodes.table yarn-nodes.heatmap"}} {{#link-to 'yarn-nodes.table' class="navigation-link"}}Nodes (current) @@ -73,7 +78,6 @@