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..c52730f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.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: "YTS", + + urlForQuery(query, modelName){ + var url = this._buildURL(); + var flowrunUid = 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..e785014 --- /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: "YTS", + + 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-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js index 67a2847..528e455 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js @@ -25,9 +25,7 @@ export default AbstractAdapter.extend({ urlForQuery(query, modelName) { var url = this._buildURL(); - if (query.state) { - url = url + '/apps/?state=' + query.state; - } + url = url + '/apps'; return url; }, 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 fd6a6f8..c2c8056 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 @@ -36,14 +36,14 @@ export default DS.JSONAPIAdapter.extend({ 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`); + var ahsNamespaces = this.get(`env.app.namespaces.applicationHistory`); if (query.is_rm) { this.set("host", rmHosts); this.set("namespace", rmNamespaces); } else { this.set("host", tsHosts); - this.set("namespace", tsNamespaces); + this.set("namespace", ahsNamespaces); } var url = this._buildURL(); 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..bf7b374 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.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: "YTS", + + urlForQuery(query, modelName){ + var url = this._buildURL(); + var appUid = query.app_uid; + url = url + '/app-uid/' + appUid + '/entities/' + query.entity_type + '?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..8417499 --- /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: "YTS", + + 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..0daabbe --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js @@ -0,0 +1,31 @@ +/** + * 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: "YTS", + + urlForQuery(query, modelName){ + var url = this._buildURL(); + var flowuid = 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..7b5b871 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.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 AbstractAdapter from './abstract'; + +export default AbstractAdapter.extend({ + address: "timelineWebAddress", + restNameSpace: "timelineV2", + serverName: "YTS", + urlForQueryRecord(query, modelName){ + var url = this._buildURL(); + var flowrunuid = 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-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..9df27a2 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.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: "YTS", + + 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) + + '/appattempts/' + app_attempt_id + '/containers'; + console.log(url); + return url; + }, + + pathForType(modelName) { + return ''; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js new file mode 100644 index 0000000..56fc68a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js @@ -0,0 +1,23 @@ +/** + * 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({ + content: null +}); 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..44e6812 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js @@ -0,0 +1,222 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import Converter from 'yarn-ui/utils/converter'; + +export default Ember.Component.extend({ + data: [], + xAxisTickFormatter: null, + yAxisTickFormatter: null, + xAxisText: '', + yAxisText: '', + sortVizDataDesc: false, + enableTooltip: true, + onBarChartClickCallback: Ember.K, + hideTootlipOnBarChartClick: true, + beforeChartRenderCallback: Ember.K, + + initChart() { + this.height = 400; + this.barWidth = 32; + this.width = Math.max(500, this.barWidth * 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; + + if (this.sortVizDataDesc) { + this.data.sort(function(d1, d2) { + return d2.value - d1.value; + }); + } + + 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") + .ticks(10) + .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+axisLabelPadding)+")"); + + 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, i) { + 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(d) { + return yScale(0); + }) + .attr("height", function(d) { + 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(d) { + tooltip.style("left", (d3.event.pageX + 5) + "px") + .style("top", (d3.event.pageY - 25) + "px"); + }).on("mouseout", function(d) { + 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(); + }, + + willRender() { + if (this.isFunction(this.beforeChartRenderCallback)) { + this.beforeChartRenderCallback(); + } + }, + + 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..3675a78 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js @@ -0,0 +1,268 @@ +/** + * 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 uniqueNames = (function(a) { + var output = []; + a.forEach(function(d) { + if (output.indexOf(d.name) === -1) output.push(d.name); + }); + return output; + })(nodes); + + 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(d) { + // 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/components/timeline-view.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js index 516b114..e1782ed 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js @@ -18,6 +18,8 @@ import Ember from 'ember'; import Converter from 'yarn-ui/utils/converter'; +import TableDef from 'em-table/utils/table-definition'; +import ColumnDef from 'em-table/utils/column-definition'; export default Ember.Component.extend({ canvas: { @@ -31,6 +33,8 @@ export default Ember.Component.extend({ modelArr: [], colors: d3.scale.category10().range(), _selected: undefined, + gridColumns: [], + gridRows: [], selected: function() { return this._selected; @@ -206,7 +210,7 @@ export default Ember.Component.extend({ .on("mousemove", function(d) { this.tooltip.style("opacity", .9); this.tooltip.html(d.get("tooltipLabel")) - .style("left", (d3.event.pageX) + "px") + .style("left", (d3.event.pageX + 5) + "px") .style("top", (d3.event.pageY - 28) + "px"); }.bind(this)) .on("mouseout", function(d) { @@ -273,5 +277,188 @@ export default Ember.Component.extend({ if (this.modelArr.length > 0) { this.setSelected(this.modelArr[0]); } + + if (this.get('attemptModel')) { + this.setAttemptsGridColumnsAndRows(); + } else { + this.setContainersGridColumnsAndRows(); + } + }, + + setAttemptsGridColumnsAndRows: function() { + var columns = [], + data = [], + row = null; + + columns.push({ + id: 'attemptId', + headerTitle: 'Attempt ID', + contentPath: 'attemptId', + observePath: true, + cellComponentName: 'em-table-linked-cell', + getCellContent: function(row) { + return { + displayText: row.get('attemptId'), + routeName: 'yarn-app-attempt', + id: row.get('attemptId') + }; + } + }, { + id: 'startTime', + headerTitle: 'Start Time', + contentPath: 'startTime', + observePath: true + }, { + id: 'finishedTime', + headerTitle: 'Finished Time', + contentPath: 'finishedTime', + observePath: true + }, { + id: 'elapsedTime', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTime', + observePath: true + }, { + id: 'amContainerId', + headerTitle: 'AM Container ID', + contentPath: 'amContainerId', + observePath: true + }, { + id: 'amNodeId', + headerTitle: 'AM Node ID', + contentPath: 'amNodeId', + observePath: true + }, { + id: 'nodeManagerWebUrl', + headerTitle: 'NodeManager Web UI', + contentPath: 'nodeManagerWebUrl', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + return `${row.get('nodeManagerWebUrl')}`; + } + }, { + id: 'logsUrl', + headerTitle: 'Logs', + contentPath: 'logsUrl', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + return `Link`; + } + }); + + var gridCols = ColumnDef.make(columns); + this.set('gridColumns', gridCols); + + this.modelArr.forEach(function(attempt) { + row = Ember.Object.create({ + attemptId: attempt.get('id'), + startTime: attempt.get('attemptStartedTime'), + finishedTime: attempt.get('finishedTime'), + elapsedTime: attempt.get('elapsedTime'), + amContainerId: attempt.get('appMasterContainerId'), + amNodeId: attempt.get('amNodeId'), + nodeManagerWebUrl: attempt.get('nodeHttpAddress'), + logsUrl: attempt.get('logsLink'), + attemptState: attempt.get('attemptState') + }); + data.push(row); + }); + + var gridRows = Ember.A(data); + this.set('gridRows', gridRows); }, -}); \ No newline at end of file + + setContainersGridColumnsAndRows: function() { + var columns = [], + data = [], + row = null; + + columns.push({ + id: 'containerId', + headerTitle: 'Container ID', + contentPath: 'containerId', + observePath: true + }, { + id: 'startTime', + headerTitle: 'Start Time', + contentPath: 'startTime', + observePath: true + }, { + id: 'finishedTime', + headerTitle: 'Finished Time', + contentPath: 'finishedTime', + observePath: true + }, { + id: 'elapsedTime', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTime', + observePath: true + }, { + id: 'priority', + headerTitle: 'Priority', + contentPath: 'priority', + observePath: true + }, { + id: 'exitStatus', + headerTitle: 'Exit Status', + contentPath: 'exitStatus', + observePath: true + }, { + id: 'state', + headerTitle: 'State', + contentPath: 'state', + observePath: true + }, { + id: 'logUrl', + headerTitle: 'Logs', + contentPath: 'logUrl', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + var url = row.get('logUrl'); + if (url) { + return `${url}`; + } else { + return ''; + } + } + }, { + id: 'nodeManagerAddress', + headerTitle: 'Node Manager UI', + contentPath: 'nodeManagerAddress', + observePath: true, + cellComponentName: 'em-table-html-cell', + getCellContent: function(row) { + var address = row.get('nodeManagerAddress'); + if (address) { + return `${address}`; + } else { + return ''; + } + } + }); + + var gridCols = ColumnDef.make(columns); + this.set('gridColumns', gridCols); + + this.modelArr.forEach(function(container) { + row = Ember.Object.create({ + containerId: container.get('id'), + startTime: container.get('startedTime'), + finishedTime: container.get('finishedTime'), + elapsedTime: container.get('elapsedTime'), + priority: container.get('priority'), + exitStatus: container.get('containerExitStatus'), + state: container.get('containerState'), + logUrl: container.get('logUrl'), + nodeManagerAddress: container.get('nodeHttpAddress') + }); + data.push(row); + }); + + var gridRows = Ember.A(data); + this.set('gridRows', gridRows); + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js index 2effb13..30c5d70 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/application.js @@ -48,7 +48,12 @@ export default Ember.Controller.extend({ html = html + ' class="active"'; } html = html + '>Nodes' + - '(current)'; + '(current)
  • Flow Activities(current)
  • '; return Ember.String.htmlSafe(html); }.property('currentPath') }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js index a458842..414adf2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js @@ -27,13 +27,17 @@ export default Ember.Controller.extend({ routeName: 'application' },{ text: "Applications", - routeName: 'yarn-apps' + routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, routeName: 'yarn-app', model: appId }, { - text: "Attempt", + text: `Attempts List [${appId}]`, + routeName: 'yarn-app-attempts', + model: appId + }, { + text: "Attempt" }]; }) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js index 9ebc2a6..92de2f9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js @@ -27,7 +27,7 @@ export default Ember.Controller.extend({ routeName: 'application' },{ text: "Applications", - routeName: 'yarn-apps' + routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, routeName: 'yarn-app', diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js index 309c895..9c1cb5d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js @@ -27,7 +27,7 @@ export default Ember.Controller.extend({ routeName: 'application' },{ text: "Applications", - routeName: 'yarn-apps' + routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, routeName: 'yarn-app', diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-appattempt-containers.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-appattempt-containers.js new file mode 100644 index 0000000..4a047c5 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-appattempt-containers.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'; + +export default Ember.Controller.extend({ + breadcrumbs: Ember.computed("model.attempt.appId", "model.attempt.id", function () { + var appId = this.get("model.attempt.appId"); + var attemptId = this.get("model.attempt.id"); + return [{ + text: "Home", + routeName: 'application' + }, { + text: "Applications", + routeName: 'yarn-apps.apps' + }, { + text: `App [${appId}]`, + routeName: 'yarn-app', + model: appId + }, { + text: `Attempts List [${appId}]`, + routeName: 'yarn-app-attempts', + model: appId + }, { + text: `Attempt [${attemptId}]`, + routeName: 'yarn-app-attempt', + model: attemptId + }, { + text: "Containers" + }]; + }) +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js index 396f83b..3aa7f04 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps.js @@ -19,13 +19,12 @@ import Ember from 'ember'; export default Ember.Controller.extend({ - breadcrumbs: [{ text: "Home", routeName: 'application' }, { text: "Applications", - routeName: 'yarn-apps', + routeName: 'yarn-apps.apps', }] }); 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..fa991f1 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js @@ -0,0 +1,122 @@ +/** + * 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: 'flowId', + headerTitle: 'Flow ID', + contentPath: 'flowId', + observePath: true, + cellComponentName: 'em-table-linked-cell', + getCellContent: function (row) { + return { + routeName: 'yarn-flow.info', + id: row.get('flowId'), + displayText: row.get('flowId') + }; + } + }, { + 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, uid) { + 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'), + flowId: 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..5ac1548 --- /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 [${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..fee405f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js @@ -0,0 +1,210 @@ +/** + * 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: 'flowName', + headerTitle: 'Flow Name', + contentPath: 'flowName', + observePath: true + }); + + columns.push({ + id: 'user', + headerTitle: 'User', + contentPath: 'user', + observePath: true + }); + + columns.push({ + id: 'runid', + headerTitle: 'Run ID', + contentPath: 'runid', + observePath: true, + cellComponentName: 'em-table-linked-cell', + getCellContent: function (row) { + return { + routeName: 'yarn-flowrun.info', + id: row.get('uid'), + displayText: row.get('shownid') + }; + } + }); + + columns.push({ + id: 'runDuration', + headerTitle: 'Run Duration', + contentPath: 'runDuration', + observePath: true, + getCellContent: function(row) { + return Converter.msToElapsedTime(row.get('runDuration')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores', + observePath: true + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + observePath: true, + getCellContent: function(row) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + }); + + columns.push({ + id: 'createTime', + headerTitle: 'Creation Time', + contentPath: 'createTime', + observePath: true + }); + + columns.push({ + id: 'endTime', + headerTitle: 'End Time', + contentPath: 'endTime', + observePath: true + }); + + 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(), + + rows: function() { + var data = [], + row; + // Generate static part of data + this.get('model.flowRuns').forEach(function(currRun) { + row = Ember.Object.create(); + row.set('flowName', currRun.get('flowName')); + row.set('runid', currRun.get('runid')); + row.set('type', currRun.get('type')); + row.set('createTime', currRun.get('createTime')); + row.set('endTime', currRun.get('endTime')); + row.set('user', currRun.get('user')); + row.set('uid', currRun.get('uid')); + row.set('shownid', currRun.get('shownid')); + row.set('runDuration', currRun.get('runDurationTs')); + row.set('cpuVCores', currRun.get('cpuVCores')); + row.set('memoryUsed', currRun.get('memoryUsed')); + data.push(row); + }); + return Ember.A(data); + }.property('model.flowRuns'), + + 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); + } + }); + return data; + }.property('model.flowRuns'), + + elapsedTimeFormatter: function(tick) { + return Converter.msToReadableTimeUnit(tick); + }, + + cpuVCoresVizData: function() { + var data = []; + this.get('model.flowRuns').forEach(function(run) { + var vizData = run.getCpuVCoresVizDataForBarChart(); + if (vizData.value > 0) { + data.push(vizData); + } + }); + return 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); + } + }); + return 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(), + + flowrunCounter: 0, + + flowrunIdFormatter: function() { + var self = this; + return function(tick) { + return "Run " + (++self.flowrunCounter); + }; + }.property(), + + beforeChartRender: function() { + var self = this; + return function() { + self.set("flowrunCounter", 0); + }; + }.property() +}); 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..b143e94 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Controller.extend({ + 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 [${parentFlowUid}]`, + routeName: 'yarn-flow.info', + model: parentFlowUid + }); + } + crumbs.push({ + text: `Flow Run [${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..f023e98 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js @@ -0,0 +1,104 @@ +/** + * 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: 'appId', + headerTitle: 'Application ID', + contentPath: 'appId', + observePath: true, + cellComponentName: 'em-table-linked-cell', + getCellContent: function (row) { + return { + routeName: 'yarn-app', + id: row.get('appId'), + displayText: row.get('appId') + }; + } + }); + + columns.push({ + id: 'appType', + headerTitle: 'Application Type', + contentPath: 'type', + observePath: true + }); + + columns.push({ + id: 'state', + headerTitle: 'State', + contentPath: 'state', + observePath: true + }); + + columns.push({ + id: 'elapsedTime', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTime', + observePath: true, + getCellContent: function(row) { + return Converter.msToElapsedTime(row.get('elapsedTime')); + } + }); + + columns.push({ + id: 'cpuVCores', + headerTitle: 'CPU VCores', + contentPath: 'cpuVCores', + observePath: true + }); + + columns.push({ + id: 'memoryUsed', + headerTitle: 'Memory Used', + contentPath: 'memoryUsed', + observePath: true, + getCellContent: function(row) { + return Converter.memoryBytesToMB(row.get('memoryUsed')); + } + }); + + return ColumnDef.make(columns); +} + +export default Ember.Controller.extend({ + columns: createColumn(), + rows: function() { + var data = [], + row; + this.get('model.apps').forEach(function(currApp) { + row = Ember.Object.create(); + row.set('appId', currApp.get('appId')); + row.set('type', currApp.get('type')); + row.set('elapsedTime', currApp.get('elapsedTs')); + row.set('state', currApp.get('state')); + row.set('cpuVCores', currApp.get('cpuVCores')); + row.set('memoryUsed', currApp.get('memoryUsed')); + data.push(row); + }); + return Ember.A(data); + }.property('model.apps') +}); 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..7540be0 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js @@ -0,0 +1,127 @@ +/** + * 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'; + +function _createColumns(flowrunUid) { + 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/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..be09c95 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/single-metric-table.js @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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 = '
    '; + html = html + '
    '; + html = html + '
    Metrics
    '; + html = html + ''; + for (var i = 0; i < metrics.length; i++) { + var k = 0; + for(var j in metrics[i].values){ + html = html + ''; + } else { + html = html + metrics[i].id + ''; + } + html = html + ''; + html = html + ''; + break; + } + } + html = html + '
    '; + if (metrics[i].values[j] > 0) { + html = html + '' + metrics[i].id + '' + metrics[i].values[j] + '
    '; + return Ember.String.htmlSafe(html); +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js index f30d143..5162e62 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js @@ -140,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..915707b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.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 DS from 'ember-data'; + +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') +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js new file mode 100644 index 0000000..0ec14d3 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js @@ -0,0 +1,101 @@ +/** + * 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({ + appName: DS.attr('string'), + user: DS.attr('string'), + queue: DS.attr('string'), + state: DS.attr('string'), + startTime: DS.attr('string'), + elapsedTime: DS.attr('string'), + finalStatus: DS.attr('string'), + finishedTime: DS.attr('finishedTime'), + progress: DS.attr('number'), + diagnostics: DS.attr('string'), + amContainerLogs: DS.attr('string'), + amHostHttpAddress: DS.attr('string'), + logAggregationStatus: DS.attr('string'), + unmanagedApplication: DS.attr('string'), + amNodeLabelExpression: DS.attr('string'), + applicationTags: DS.attr('string'), + applicationType: DS.attr('string'), + priority: DS.attr('number'), + allocatedMB: DS.attr('number'), + allocatedVCores: DS.attr('number'), + runningContainers: DS.attr('number'), + memorySeconds: DS.attr('number'), + vcoreSeconds: DS.attr('number'), + preemptedResourceMB: DS.attr('number'), + preemptedResourceVCores: DS.attr('number'), + numNonAMContainerPreempted: DS.attr('number'), + numAMContainerPreempted: DS.attr('number'), + clusterUsagePercentage: DS.attr('number'), + queueUsagePercentage: DS.attr('number'), + currentAppAttemptId: DS.attr('string'), + + isFailed: function() { + return this.get('finalStatus') == "FAILED" + }.property("finalStatus"), + + validatedFinishedTs: function() { + if (this.get("finishedTime") < this.get("startTime")) { + return ""; + } + return this.get("finishedTime"); + }.property("finishedTime"), + + allocatedResource: function() { + return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores")); + }.property("allocatedMB", "allocatedVCores"), + + preemptedResource: function() { + return Converter.resourceToString(this.get("preemptedResourceMB"), this.get("preemptedResourceVCores")); + }.property("preemptedResourceMB", "preemptedResourceVCores"), + + aggregatedResourceUsage: function() { + return Converter.resourceToString(this.get("memorySeconds"), this.get("vcoreSeconds")) + " (× Secs)"; + }.property("memorySeconds", "vcoreSeconds"), + + progressStyle: function() { + return "width: " + this.get("progress") + "%"; + }.property("progress"), + + runningContainersNumber: function() { + if(this.get("runningContainers") < 0) { + return 0; + } + return this.get("runningContainers"); + }.property("progress"), + + finalStatusStyle: function() { + var style = "default"; + var finalStatus = this.get("finalStatus"); + if (finalStatus == "KILLED") { + style = "warning"; + } else if (finalStatus == "FAILED") { + style = "danger"; + } else { + style = "success"; + } + + return "label label-" + style; + }.property("finalStatus") +}); 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..483b96f --- /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") + "
    " + Converter.msToReadableTimeUnit(this.get('runDurationTs'), true), + flowrunUid: this.get('uid') + }; + }, + + getCpuVCoresVizDataForBarChart: function() { + return { + label: this.get('runid'), + value: this.get('cpuVCores'), + tooltip: this.get("shownid") + "
    " + 'CPU VCores: ' + this.get('cpuVCores'), + flowrunUid: this.get('uid') + }; + }, + + getMemoryVizDataForBarChart: function() { + return { + label: this.get('runid'), + value: this.get('memoryUsed'), + tooltip: this.get("shownid") + "
    " + 'Memory Used: ' + Converter.memoryBytesToMB(this.get('memoryUsed')), + flowrunUid: this.get('uid') + }; + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flowrun.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flowrun.js new file mode 100644 index 0000000..cc0c327 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-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 Ember from 'ember'; +import DS from 'ember-data'; + +// For now, similar to yarn-flowrun-brief, but may add more in future. + +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'), + endTime: DS.attr('string'), + user: DS.attr('string'), + metrics: DS.attr('array'), + singleMetricHtml: function() { + var html = '
    '; + html = html + '
    '; + html = html + '
    Metrics
    '; + html = html + ''; + var metrics = this.get("metrics"); + for (var i = 0; i < metrics.length; i++) { + html = html + ''; + var k = 0; + for(var j in metrics[i].values){ + html = html + ''; + break; + } + html = html + ''; + } + html = html + '
    ' + metrics[i].id + '' + metrics[i].values[j] + '
    '; + return Ember.String.htmlSafe(html); + }.property("metrics") +}); 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..17f6cca --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-timeline-container.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.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.msToElapsedTime(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 87a018d..2c7d435 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 @@ -48,11 +48,25 @@ Router.map(function() { this.route('cluster-overview'); this.route('yarn-app', { path: '/yarn-app/:app_id' }); this.route('yarn-app-attempt', { path: '/yarn-app-attempt/:app_attempt_id'}); + this.route('yarn-appattempt-containers', {path: '/yarn-appattempt-containers/:app_attempt_id'}); + + 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('error'); this.route('notfound', { path: '*:' }); this.route('yarn-app-attempts', { path: '/yarn-app-attempts/:app_id' }); this.route('yarn-queues', { path: '/yarn-queues/:queue_name' }); this.route('yarn-queue-apps', { path: '/yarn-queue-apps/:queue_name' }); + 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/application.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js index 07b3792..d540fb5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/application.js @@ -28,7 +28,6 @@ export default Ember.Route.extend({ */ error: function (error) { Ember.Logger.log(error.stack); - if (error && error.errors[0] && error.errors[0].status == 404) { this.intermediateTransitionTo('/notfound'); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js index 1068126..7572249 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js @@ -41,4 +41,4 @@ export default AbstractRoute.extend({ this.store.unloadAll('yarn-app'); this.store.unloadAll('yarn-queue'); } -}); \ No newline at end of file +}); 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..6a42263 --- /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 762fb29..242ee60 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 @@ -23,28 +23,11 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model(param) { return Ember.RSVP.hash({ - attempt: this.store.findRecord('yarn-app-attempt', param.app_attempt_id), - - 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.store.findRecord('yarn-app-attempt', param.app_attempt_id) }); }, unloadAll() { this.store.unloadAll('yarn-app-attempt'); - this.store.unloadAll('yarn-container'); } }); \ No newline at end of file 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 000b02f..4643daf 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 @@ -23,18 +23,16 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model(param) { return Ember.RSVP.hash({ - app: this.store.find('yarn-app', param.app_id), + app: this.fetchAppInfoFromRMorATS(param.app_id), - rmContainers: this.store.find('yarn-app', param.app_id).then(function(app) { + rmContainers: this.fetchAppInfoFromRMorATS(param.app_id).then(function(app) { return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) { if (attempts && attempts.get('firstObject')) { var appAttemptId = attempts.get('firstObject').get('appAttemptId'); - var rmContainers = this.store.query('yarn-container', - { - app_attempt_id: appAttemptId, - is_rm: true - }); - return rmContainers; + return this.store.query('yarn-container', { + app_attempt_id: appAttemptId, + is_rm: true + }); } }.bind(this)); }.bind(this)), @@ -43,10 +41,30 @@ export default AbstractRoute.extend({ }); }, + fetchAppInfoFromRMorATS(appId) { + var self = this; + return new Ember.RSVP.Promise(function(resolve, reject) { + self.store.find('yarn-app', appId).then(function(rmApp) { + resolve(rmApp); + }, function(rmErrs) { + if (rmErrs.errors && rmErrs.errors[0] && rmErrs.errors[0].status == "404") { + self.store.find('yarn-app-timeline', appId).then(function(atsApp) { + resolve(atsApp); + }, function(atsErrs) { + reject(atsErrs); + }); + } else { + reject(rmErrs); + } + }); + }); + }, + unloadAll() { this.store.unloadAll('yarn-app'); 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-appattempt-containers.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-appattempt-containers.js new file mode 100644 index 0000000..6c84fa5 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-appattempt-containers.js @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; +import AbstractRoute from './abstract'; + +export default AbstractRoute.extend({ + model(params) { + return Ember.RSVP.hash({ + attempt: this.store.findRecord('yarn-app-attempt', params.app_attempt_id), + rmContainers: this.store.query('yarn-container', { + app_attempt_id: params.app_attempt_id, + is_rm: true + }), + tsContainers: this.store.query('yarn-timeline-container', { + app_attempt_id: params.app_attempt_id + }).catch(function() { + return []; + }) + }); + }, + + unloadAll() { + this.store.unloadAll('yarn-app-attempt'); + 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-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js index 0ac503c..e6c0c11 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js @@ -24,7 +24,7 @@ export default AbstractRoute.extend({ model() { return Ember.RSVP.hash({ apps: this.store.findAll('yarn-app'), - clusterMetrics: this.store.findAll('ClusterMetric'), + clusterMetrics: this.store.findAll('ClusterMetric') }); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js index 8719170..d006e6f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/apps.js @@ -19,4 +19,5 @@ import Ember from 'ember'; export default Ember.Route.extend({ + }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js index 8719170..d006e6f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps/services.js @@ -19,4 +19,5 @@ 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-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..933f213 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flow-activity.js @@ -0,0 +1,42 @@ +/** + * 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() { + return this.store.findAll('yarn-flow-activity'); + }, + + unloadAll() { + this.store.unloadAll('yarn-flow-activity'); + }, + + actions: { + error(err, transition) { + if (err && err.errors && err.errors[0]) { + var logMsg = `${err.errors[0].status}: App Timeline Server - ${err.errors[0].title}`; + Ember.Logger.log(logMsg); + } + 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..24937f5 --- /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..6a6df6b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-flowrun-metric.js @@ -0,0 +1,93 @@ +/** + * 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); + }); + } + 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})]); + }, + + 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); + }, + + 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..bf35fd5 --- /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..67bbbad --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-flowrun.js @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 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) { + // 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.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-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..630cc82 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-app-timeline.js @@ -0,0 +1,78 @@ +/** + * 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, requestType) { + + var metrics = payload.metrics, + events = payload.events, + appFinishedEvent = events.findBy('id', 'YARN_APPLICATION_FINISHED'), + startedTime = payload.createdtime, + finishedTime = appFinishedEvent? appFinishedEvent.timestamp : Date.now(), + elapsedTime = finishedTime - startedTime; + + var fixedPayload = { + id: id, + type: primaryModelClass.modelName, + attributes: { + appName: payload.info.YARN_APPLICATION_NAME, + user: payload.info.YARN_APPLICATION_USER, + queue: "Not Available", + state: payload.info.YARN_APPLICATION_STATE, + startTime: Converter.timeStampToDate(startedTime), + elapsedTime: Converter.msToElapsedTime(elapsedTime), + finishedTime: Converter.timeStampToDate(finishedTime), + finalStatus: payload.info.YARN_APPLICATION_FINAL_STATUS, + progress: 100, + applicationType: payload.info.YARN_APPLICATION_TYPE, + diagnostics: payload.info.YARN_APPLICATION_DIAGNOSTICS_INFO, + amContainerLogs: '', + amHostHttpAddress: '', + logAggregationStatus: '', + unmanagedApplication: payload.info.YARN_APPLICATION_UNMANAGED_APPLICATION, + amNodeLabelExpression: payload.configs.YARN_AM_NODE_LABEL_EXPRESSION, + priority: payload.info.YARN_APPLICATION_PRIORITY, + allocatedMB: -1, + allocatedVCores: -1, + runningContainers: -1, + 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, requestType); + return {data: p}; + } +}); 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..9ae2dd3 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-entity.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 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 = {}; + + // payload has apps : { app: [ {},{},{} ] } + // need some error handling for ex apps or app may not be defined. + 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..2c91aa4 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flow-activity.js @@ -0,0 +1,56 @@ +/** + * 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 = {}; + + // payload has apps : { app: [ {},{},{} ] } + // need some error handling for ex apps or app may not be defined. + 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..7b5b875 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun-brief.js @@ -0,0 +1,68 @@ +/** + * 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) { + // 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.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-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..fa8f9b7 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-flowrun.js @@ -0,0 +1,68 @@ +/** + * 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, + requestType) { + 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, requestType); + return { data: p }; + }, + + normalizeArrayResponse(store, primaryModelClass, payload, id, + requestType) { + // 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.map(singleApp => { + return this.internalNormalizeSingleResponse(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-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..129a3f6 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/serializers/yarn-timeline-container.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.JSONAPISerializer.extend({ + internalNormalizeSingleResponse(store, primaryModelClass, payload, id, requestType) { + 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, id, requestType); + 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, singleContainer.id, requestType); + }); + } + 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 da5b4bf..4b2f856 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 @@ -277,3 +277,122 @@ li a.navigation-link.ember-view { .x-scroll { overflow-x: scroll; } + +#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 { + overflow: auto; +} + +.yarn-flow-runs .glyphicon-remove { + cursor: pointer; +} + +.yarn-flow-runs .glyphicon-remove:hover { + color: #c9302c; +} + +.yarn-flow-runs .dropdown-menu-item { + width: 171px; + display: inline-block; +} + +/* em-table styles */ +.em-table .table-column .table-cell:nth-child(odd) { + background-color: #f9f9f9; +} + +.em-table .search-ui button, .em-table .search-ui input { + height: 26px; + border-radius: 5px; + color: #000; + background-color: #fff; + border-width: 1px; + outline: none; + padding: 4px 8px; + vertical-align: middle; +} + +.em-table .search-ui button:hover { + background-color: #f0f0f0; +} + +.em-table .search-ui input:focus { + border-color: #66afe9; +} + +.em-table .pagination-ui .page-list li { + height: 26px; + vertical-align: middle; + padding: 4px 10px; +} +.em-table .pagination-ui select { + height: 26px; + outline: none; + border-width: 1px; + border-radius: 5px; + padding: 4px; +} + +.em-table .pagination-ui select:focus { + border-color: #66afe9; +} 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 7783db4..b6fe4c3 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 @@ -51,6 +51,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"}} {{#link-to 'yarn-nodes.table' class="navigation-link"}}Nodes (current) @@ -68,7 +73,6 @@


    -
    +
    -

    -
    -
    - - -
    -
    -
    - {{#if selected.link}} - {{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}} - {{else}} - {{selected.id}} - {{/if}} +
    +
    +

    +
    + +
    +
    +
    + {{#if selected.link}} + {{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}} + {{else}} + {{selected.id}} + {{/if}} +
    + {{#if attemptModel}} + {{app-attempt-table attempt=selected}} + {{else}} + {{container-table container=selected}} + {{/if}} +
    - {{#if attemptModel}} - {{app-attempt-table attempt=selected}} - {{else}} - {{container-table container=selected}} - {{/if}} +
    +
    + {{em-table columns=gridColumns rows=gridRows}}
    -{{outlet}} \ No newline at end of file +{{outlet}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/timeline-error.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/timeline-error.hbs new file mode 100644 index 0000000..cf8ff2a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/timeline-error.hbs @@ -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. +--}} + +{{#if model.isValidErrorCode}} +

    {{model.errorCode}}: {{model.errorType}}

    +{{/if}} +

    Timeline server failed with an error

    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs index 1dbae9a..1c08383 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempt.hbs @@ -18,26 +18,41 @@ {{breadcrumb-bar breadcrumbs=breadcrumbs}}


    -
    -
    - {{#if model.attempt}} -
    +
    +
    +
    +
    +
    + Application Attempts +
    +
    +
    + +
    +
    +
    +
    +
    + {{#if model.attempt}}
    - Application attempt Information + Application Attempt Information
    {{app-attempt-table attempt=model.attempt}}
    -
    - {{/if}} -
    - - -
    - {{#if (or model.rmContainers model.tsContainers)}} - {{timeline-view parent-id="containers-timeline-div" my-id="timeline-view" height="400" rmModel=model.rmContainers tsModel=model.tsContainers label="shortAppAttemptId" attemptModel=false}} - {{/if}} + {{/if}} +
    +
    + {{outlet}} +
    - -{{outlet}} \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs index acf00d1..ffd4be4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs @@ -172,8 +172,16 @@ - Link - Link + + {{#if model.app.amContainerLogs}} + Link + {{/if}} + + + {{#if model.app.amHostHttpAddress}} + Link + {{/if}} + {{model.app.amNodeLabelExpression}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-appattempt-containers.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-appattempt-containers.hbs new file mode 100644 index 0000000..93378a0 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-appattempt-containers.hbs @@ -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. +}} + +{{breadcrumb-bar breadcrumbs=breadcrumbs}} + +
    +
    +
    +
    +
    + Application Attempts +
    +
    +
    + +
    +
    +
    +
    +
    + {{#if (or model.rmContainers model.tsContainers)}} + {{timeline-view parent-id="containers-timeline-div" my-id="timeline-view" height="400" rmModel=model.rmContainers tsModel=model.tsContainers label="shortAppAttemptId" attemptModel=false}} + {{/if}} +
    +
    +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-apps.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-apps.hbs index d5f6347..ec78e6e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-apps.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-apps.hbs @@ -24,18 +24,18 @@
    -

    Application

    +
    + YARN Applications +
    @@ -44,7 +44,7 @@
    - {{#if model.clusterMetrics}} + {{#if (and model.clusterMetrics)}}
    @@ -87,4 +87,4 @@
    -
    \ No newline at end of file +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow-activity.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow-activity.hbs new file mode 100644 index 0000000..c9b682c --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow-activity.hbs @@ -0,0 +1,45 @@ +{{!-- + 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. +--}} + +
    +
    + {{breadcrumb-bar breadcrumbs=breadcrumbs}} +
    +
    +
    +
    +
    + Flow Activity +
    +
    + +
    +
    +
    +
    +

    Recent Flow Activities

    + {{em-table columns=columns rows=rows definition=tableDefinition}} +
    +
    +
    + +{{outlet}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow.hbs new file mode 100644 index 0000000..2e98958 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow.hbs @@ -0,0 +1,49 @@ +{{!-- + 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. +--}} + +
    +
    + {{breadcrumb-bar breadcrumbs=breadcrumbs}} +
    +
    +
    +
    +
    +
    + Flow Information +
    +
    +
    + +
    +
    +
    +
    + {{outlet}} +
    +
    +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/info.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/info.hbs new file mode 100644 index 0000000..492803b --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/info.hbs @@ -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. +--}} + +

    Flow Information

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + {{#if flowInfo.lastExecutionDate}} + + + + + {{/if}} + +
    Flow Name{{flowInfo.flowName}}
    User{{flowInfo.user}}
    Flow ID{{flowInfo.flowUid}}
    First Run Started{{flowInfo.firstRunStarted}}
    Last Run Finished{{flowInfo.lastRunFinished}}
    Last Execution Date{{flowInfo.lastExecutionDate}}
    +
    +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/runs.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/runs.hbs new file mode 100644 index 0000000..b1e345f --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flow/runs.hbs @@ -0,0 +1,128 @@ +{{!-- + 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. +--}} + +
    + + + +

    Flow Runs

    + {{em-table columns=columns rows=rows definition=tableDefinition}} +
    + +
    + {{#if (and elapsedTimeVizData vizWidgets.runDuration)}} +
    +
    +
    +
    +

    Flow Run Vs Run Duration

    + {{simple-bar-chart + class="chart-panel" + data=elapsedTimeVizData + xAxisTickFormatter=flowrunIdFormatter + yAxisTickFormatter=elapsedTimeFormatter + xAxisText="Flow Run" + yAxisText="Run Duration" + sortVizDataDesc=true + onBarChartClickCallback=onBarChartClick + beforeChartRenderCallback=beforeChartRender + }} +
    +
    +
    + {{/if}} + + {{#if (and cpuVCoresVizData vizWidgets.cpuVcores)}} +
    +
    +
    +
    +

    Flow Run Vs CPU VCores

    + {{simple-bar-chart + class="chart-panel" + data=cpuVCoresVizData + xAxisTickFormatter=flowrunIdFormatter + xAxisText="Flow Run" + yAxisText="CPU VCores" + sortVizDataDesc=true + onBarChartClickCallback=onBarChartClick + beforeChartRenderCallback=beforeChartRender + }} +
    +
    +
    + {{/if}} + + {{#if (and memoryVizData vizWidgets.memoryUsed)}} +
    +
    +
    +
    +

    Flow Run Vs Memory Used

    + {{simple-bar-chart + class="chart-panel" + data=memoryVizData + xAxisTickFormatter=flowrunIdFormatter + yAxisTickFormatter=memoryFormatter + xAxisText="Flow Run" + yAxisText="Memory Used" + sortVizDataDesc=true + onBarChartClickCallback=onBarChartClick + beforeChartRenderCallback=beforeChartRender + }} +
    +
    +
    + {{/if}} +
    + +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun-metric.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun-metric.hbs new file mode 100644 index 0000000..832b47a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun-metric.hbs @@ -0,0 +1,34 @@ +{{!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +--}} + +
    +
    +

    Sunburst chart for Metric "{{metric_id}}"

    +

    (Flowrun: {{flowrun.id}})

    +
    +
    +
    + +
    +
    +
    +
    +{{sunburst-chart arr=arr}} +{{outlet}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun.hbs new file mode 100644 index 0000000..eb0b4bd --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun.hbs @@ -0,0 +1,49 @@ +{{!-- + 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. +--}} + +
    +
    + {{breadcrumb-bar breadcrumbs=breadcrumbs}} +
    +
    +
    +
    +
    +
    + Flow Run Information +
    +
    +
    + +
    +
    +
    +
    + {{outlet}} +
    +
    +
    diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/info.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/info.hbs new file mode 100644 index 0000000..ec778ec --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/info.hbs @@ -0,0 +1,55 @@ +{{!-- + 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. +--}} + +

    Flow Run Info

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Flow Name{{model.flowrun.flowName}}
    Run ID{{model.flowrun.shownid}}
    Launched By{{model.flowrun.user}}
    Run Sequence ID{{model.flowrun.runid}}
    Start Time{{model.flowrun.createTime}}
    End Time{{model.flowrun.endTime}}
    +
    +
    +
    + +

    Applications

    +{{em-table columns=columns rows=rows}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/metrics.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/metrics.hbs new file mode 100644 index 0000000..01c7359 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-flowrun/metrics.hbs @@ -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. +--}} + +

    Flow Run {{model.flowrun_uid}}

    +
    + +

    GENERAL Metrics

    +{{em-table columns=columns rows=generalConfigRows}} +
    + +{{#if mapMetrics}} +

    MAP Metrics

    + {{em-table columns=columns rows=mapConfigRows}} +
    +{{/if}} + +{{#if reduceMetrics}} +

    REDUCER Metrics

    + {{em-table columns=columns rows=reduceConfigRows}} +{{/if}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-nodes.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-nodes.hbs index 874b3c4..59f26b4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-nodes.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-nodes.hbs @@ -22,7 +22,9 @@
    -

    Nodes

    +
    + Nodes +