ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From srihar...@apache.org
Subject [1/3] ambari git commit: AMBARI-18431: Storm Ambari view - Fixes to DAG, kafka offset info , Misc fixes.
Date Fri, 27 Jan 2017 05:17:03 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk a5df40868 -> 7e00f5859


http://git-wip-us.apache.org/repos/asf/ambari/blob/7e00f585/contrib/views/storm/src/main/resources/scripts/components/BarChart.jsx
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/scripts/components/BarChart.jsx b/contrib/views/storm/src/main/resources/scripts/components/BarChart.jsx
index 7dabed1..ef05422 100644
--- a/contrib/views/storm/src/main/resources/scripts/components/BarChart.jsx
+++ b/contrib/views/storm/src/main/resources/scripts/components/BarChart.jsx
@@ -55,7 +55,7 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
 		setUpSVG: function(){
 			this.svg = d3.select(ReactDOM.findDOMNode(this))
 				.attr('width', this.props.width+"px")
-				.attr('height', this.props.height+30+"px")
+				.attr('height', this.props.height+50+"px")
 				// .attr("viewBox", "-46 -5 " + (this.props.width+82) + " " + (this.props.height+28)
);
 
 			this.container = this.svg.append("g")
@@ -136,7 +136,37 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
 			this.xAxisGrp = container['xAxisEl'] = container.append("g")
 				.attr("class", "x axis")
 				.attr("transform", "translate(0," + height + ")")
-				.call(xAxis);
+				.call(xAxis)
+				.selectAll(".tick text")
+				.call(this.wrap, this.x.rangeBand());
+		},
+		wrap: function(text, width) {
+			text.each(function() {
+				var text = d3.select(this),
+					words = text.text().split(/-+/).reverse(),
+					word,
+					line = [],
+					lineNumber = 0,
+					lineHeight = 1.1, // ems
+					y = text.attr("y"),
+					dy = parseFloat(text.attr("dy")),
+					tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
+
+				//Hack to show hidden div to find getComputedTextLength
+				$('#lag-graph').css({visibility: 'hidden', display: 'block', position: 'absolute'});
+
+				while (word = words.pop()) {
+					line.push(word);
+					tspan.text(line.join(" "));
+					if (tspan.node().getComputedTextLength() > width) {
+						line.pop();
+						tspan.text(line.join(" "));
+						line = [word];
+						tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight
+ dy + "em").text(word);
+					}
+				}
+				$('#lag-graph').css({visibility: '', display: 'none', position: ''});
+			});
 		},
 		drawYAxis: function(x) {
 			var yAxis = this.yAxis;

http://git-wip-us.apache.org/repos/asf/ambari/blob/7e00f585/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx b/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx
index 44afd5d..8679661 100644
--- a/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx
+++ b/contrib/views/storm/src/main/resources/scripts/components/TopologyGraph.jsx
@@ -16,7 +16,7 @@
  limitations under the License.
 */
 
-define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM, d3) {
+define(['react', 'react-dom', 'd3', 'dagreD3', 'd3.tip'], function(React, ReactDOM, d3, dagreD3)
{
 	'use strict';
 	return React.createClass({
 		displayName: 'TopologyGraph',
@@ -26,39 +26,24 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
             height: React.PropTypes.string
         },
 		getInitialState: function(){
-			this.width = this.props.width || '1100';
-			this.height = this.props.height || '260';
 			this.syncData(this.props.data);
 			return null;
 		},
-        componentWillUpdate: function(){
-
-        },
 		componentDidUpdate: function(){
 			this.syncData(this.props.data);
             this.updateGraph();
-            this.force.start();
-            for (var i = 300; i > 0; --i) this.force.tick();
-            this.force.stop();
 		},
 		componentDidMount: function(){
-			var width = this.width,
-                height = this.height,
-                nodes = this.nodeArray,
-                links = this.linkArray,
-                radius = this.radius = 20.75;
-
-            var svg = this.svg = d3.select(ReactDOM.findDOMNode(this))
-                .attr('width', width)
-                .attr('height', height);
-
+            var that = this;
+            this.svg = d3.select(ReactDOM.findDOMNode(this))
             //Set up tooltip
-            this.tip = d3.tip()
+            this.tooltip = d3.tip()
                 .attr('class', function() {
-                    return 'd3-tip';
+                    return 'd3-tip testing';
                 })
                 .offset([-10, 0])
-                .html(function(d) {
+                .html(function(data) {
+                    var d = that.g.node(data);
                     var tip = "<ul>";
                     if (d[":capacity"] !== null) tip += "<li>Capacity: " + d[":capacity"].toFixed(2)
+ "</li>";
                     if (d[":latency"] !== null) tip += "<li>Latency: " + d[":latency"].toFixed(2)
+ "</li>";
@@ -66,171 +51,105 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
                     tip += "</ul>";
                     return tip;
                 });
-            svg.call(this.tip);
-
-            // define arrow markers for graph links
-            svg.append('svg:defs').append('svg:marker')
-                .attr('id', 'end-arrow')
-                .attr('viewBox', '0 -5 10 10')
-                .attr('refX', 6)
-                .attr('markerWidth', 6)
-                .attr('markerHeight', 6.5)
-                .attr('orient', 'auto')
-                .append('svg:path')
-                .attr('d', 'M0,-5L10,0L0,5');
-
-            svg.append('svg:defs').append('svg:marker')
-                .attr('id', 'start-arrow')
-                .attr('viewBox', '0 -5 10 10')
-                .attr('refX', 4)
-                .attr('markerWidth', 3)
-                .attr('markerHeight', 3)
-                .attr('orient', 'auto')
-                .append('svg:path')
-                .attr('d', 'M10,-5L0,0L10,5');
-
-            // handles to link and node element groups
-            this.path = svg.append('svg:g').selectAll('path');
-            this.image = svg.append('svg:g').selectAll('g');
-
-            this.selected_node = null;
-			
-			// only respond once per keydown
-            this.lastKeyDown = -1;
-            d3.select(window)
-                .on('keydown', this.keydown)
-                .on('keyup', this.keyup);
-            this.updateGraph();
-            this.force.start();
-            this.force.tick();
-            this.force.stop();
-		},
+            //Set up zoom
+            this.zoom = d3.behavior.zoom()
+                .scaleExtent([0, 8])
+                .on("zoom", this.zoomed);
+        },
+        zoomed: function(){
+            this.inner.attr("transform",
+                "translate(" + this.zoom.translate() + ")" +
+                "scale(" + this.zoom.scale() + ")"
+            );
+        },
 		// update graph (called when needed)
 		updateGraph: function(){
-			// init D3 force layout
-            this.force = d3.layout.force()
-                .nodes(this.nodeArray)
-                .links(this.linkArray)
-                .size([this.width, this.height])
-                .linkDistance(150)
-                .charge(-500)
-                .on('tick', this.tick);
-
-			// path (link) group
-            this.path = this.path.data(this.linkArray);
-
-            // update existing links
-            this.path.style('marker-start', function(d) {
-                    return ''; })
-                .style('marker-end', function(d) {
-                    return 'url(#end-arrow)'; });
-
-
-            // add new links
-            this.path.enter().append('svg:path')
-                .attr('class', 'link')
-                .style('marker-start', function(d) {
-                    return ''; })
-                .attr("stroke-dasharray", "5, 5")
-                .attr('stroke-width', '2')
-                .style('marker-end', function(d) {
-                    return 'url(#end-arrow)'; });
-
-            // remove old links
-            this.path.exit().remove();
-
-
-            // image (node) group
-            // NB: the function arg is crucial here! nodes are known by id, not by index!
-            this.image = this.image.data(this.nodeArray, function(d) {
-                return d.id; 
-            });
-
-            //update old nodes
-            this.image
-                .on('mouseover', function(d) {
-                    this.tip.show(d);
-                }.bind(this))
-                .on('mouseout', function(d) {
-                    this.tip.hide();
-                }.bind(this));
-
-            // add new nodes
-            var g = this.image.enter().append('svg:g');
+            var that = this;
+            var g = ReactDOM.findDOMNode(this).children[0];
+            if(g){
+                g.remove();
+            }
+            var inner = this.inner = this.svg.append("g");
+            // Create the renderer
+            var render = new dagreD3.render();
+            
+            render.arrows().arrowPoint = function normal(parent, id, edge, type) {
+                var marker = parent.append("marker")
+                    .attr("id", id)
+                    .attr("viewBox", "0 0 10 10")
+                    .attr("refX", 5)
+                    .attr("refY", 5)
+                    .attr("markerUnits", "strokeWidth")
+                    .attr("markerWidth", 6)
+                    .attr("markerHeight", 6.5)
+                    .attr("orient", "auto");
+
+                var path = marker.append("path")
+                    .attr("d", "M 0 0 L 10 5 L 0 10 z")
+                    .style("stroke-width", 1)
+                    .style("stroke-dasharray", "1,0")
+                    .style("fill", "grey")
+                    .style("stroke", "grey");
+                dagreD3.util.applyStyle(path, edge[type + "Style"]);
+            };
+
+            render.shapes().img = function circle(parent, bbox, node) {
+                var shapeSvg = parent.insert("image")
+                    .attr("class", "nodeImage")
+                    .attr("xlink:href", function(d) {
+                        if (node) {
+                            if(node.type === 'spout'){
+                                return "images/icon-spout.png";
+                            } else if(node.type === 'bolt'){
+                                return "images/icon-bolt.png";
+                            }
+                        }
+                    }).attr("x", "-12px")
+                    .attr("y", "-12px")
+                    .attr("width", "30px")
+                    .attr("height", "30px");
+                node.intersect = function(point) {
+                    return dagreD3.intersect.circle(node, 20, point);
+                };
+                return shapeSvg;
+            }
+            this.svg.call(this.zoom).call(this.tooltip);
+            // Run the renderer. This is what draws the final graph.
+            render(inner, this.g);
 
-            g.append('svg:image')
-            	.attr("xlink:href", function(d){
-					if(d.type === 'spout'){
-						return "images/icon-spout.png";
-					} else if(d.type === 'bolt'){
-						return "images/icon-bolt.png";
-					}
-				})
-				.attr("width", "30px")
-				.attr("height", "30px")
+            inner.selectAll("g.nodes image")
                 .on('mouseover', function(d) {
-                    this.tip.show(d);
-                }.bind(this))
+                    that.tooltip.show(d);
+                })
                 .on('mouseout', function(d) {
-                    this.tip.hide();
-                }.bind(this));
-
-            g.append("svg:text")
-                .attr("dx", 18)
-                .attr("dy", 38)
-                .text(function(d) {
-                    return d.id; });
-
-            // remove old nodes
-            this.image.exit().remove();
-		},
-		// update force layout (called automatically each iteration)
-		tick: function(){
-			// draw directed edges with proper padding from node centers
-            this.path.attr('d', function(d) {
-                var deltaX = d.target.x - d.source.x,
-                    deltaY = d.target.y - d.source.y,
-                    dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY),
-                    normX = deltaX / dist,
-                    normY = deltaY / dist,
-                    sourcePadding = 30,
-                    targetPadding = 5,
-                    sourceX = d.source.x + (sourcePadding * normX),
-                    sourceY = d.source.y + (sourcePadding * normY) + 15,
-                    targetX = d.target.x - (targetPadding * normX),
-                    targetY = d.target.y - (targetPadding * normY) + 15;
-                return 'M' + sourceX + ',' + sourceY + 'L' + targetX + ',' + targetY;
-            });
-            
-            this.image.attr('transform', function(d) {
-                return 'translate(' + Math.max(this.radius, Math.min(this.width - this.radius,
d.x)) + ',' + Math.max(this.radius, Math.min(this.height - this.radius, d.y)) + ')';
-            }.bind(this));
-		},
-		keydown: function(){
-			if (this.lastKeyDown !== -1) return;
-            this.lastKeyDown = d3.event.keyCode;
+                    that.tooltip.hide();
+                });
 
-            // ctrl
-            if (d3.event.keyCode === 17) {
-                d3.event.preventDefault();
-                this.tip.hide();
-                this.image.call(this.force.drag);
-                this.svg.classed('ctrl', true);
+            inner.selectAll("g.nodes g.label")
+                    .attr("transform", "translate(2,-30)");
+            // Center the graph
+            var initialScale = 1;
+            var svgWidth = this.svg[0][0].parentNode.clientWidth;
+            var svgHeight = this.svg[0][0].parentNode.clientHeight;
+            if(this.linkArray.length > 0){
+                this.zoom.translate([(svgWidth - this.g.graph().width * initialScale) / 2,
(svgHeight - this.g.graph().height * initialScale) / 2])
+                    .scale(initialScale)
+                    .event(this.svg);
             }
-		},
-		keyup: function(){
-			this.lastKeyDown = -1;
-            // ctrl
-            if (d3.event.keyCode === 17) {
-                this.image
-                    .on('mousedown.drag', null)
-                    .on('touchstart.drag', null);
-                this.svg.classed('ctrl', false);
-            }
-		},
+        },
 		syncData: function(data){
 			this.nodeArray = [];
             this.linkArray = [];
+            this.g = new dagreD3.graphlib.Graph().setGraph({
+                nodesep: 50,
+                ranksep: 190,
+                rankdir: "LR",
+                marginx: 20,
+                marginy: 20,
+                // transition: function transition(selection) {
+                //     return selection.transition().duration(500);
+                // }
+            });
             if(data){
             	var keys = _.keys(data);
             	keys.map(function(key){
@@ -243,10 +162,11 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
 
             	var spoutObjArr = _.where(this.nodeArray, { "type": "spout" });
 	            if (spoutObjArr.length > 1) {
-	            	var index = this.nodeArray.length - 1;
-	                this.nodeArray[index].x = 50;
-	                this.nodeArray[index].y = 100;
-	                this.nodeArray[index].fixed = true;
+                    for(var i = 0; i < spoutObjArr.length; i++){
+                        spoutObjArr[i].x = 50;
+                        spoutObjArr[i].y = parseInt(i+'10', 10);
+                        spoutObjArr[i].fixed = true;
+                    }
 	            } else if (spoutObjArr.length == 1) {
 	                spoutObjArr[0].x = 50;
 	                spoutObjArr[0].y = 100;
@@ -257,10 +177,14 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
 	            	var inputArr = node[":inputs"] || [];
 	            	inputArr.map(function(input){
 	            		if(!input[":component"].startsWith("__")){
-	            			this.linkArray.push({
-	            				source: _.findWhere(this.nodeArray, {id: input[":component"]}),
+	            			var sourceNode = _.findWhere(this.nodeArray, {id: input[":component"]});
+                            this.linkArray.push({
+	            				source: sourceNode,
 	            				target: node
 	            			});
+                            this.g.setNode(sourceNode.id, _.extend(sourceNode, {label: sourceNode.id,
shape: 'img'}));
+                            this.g.setNode(node.id, _.extend(node, {label: node.id, shape:
'img'}));
+                            this.g.setEdge(sourceNode.id, node.id, {"arrowhead": 'arrowPoint'});
 	            		}
 	            	}.bind(this));
 	            }.bind(this));
@@ -268,7 +192,7 @@ define(['react', 'react-dom', 'd3', 'd3.tip'], function(React, ReactDOM,
d3) {
 		},
 		render: function() {
 			return (
-				<svg className="topology-graph"></svg>
+				<svg className="topology-graph" width="100%" height="300"></svg>
 			);
 		},
 	});

http://git-wip-us.apache.org/repos/asf/ambari/blob/7e00f585/contrib/views/storm/src/main/resources/scripts/main.js
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/scripts/main.js b/contrib/views/storm/src/main/resources/scripts/main.js
index 6b8fe95..7bd2201 100644
--- a/contrib/views/storm/src/main/resources/scripts/main.js
+++ b/contrib/views/storm/src/main/resources/scripts/main.js
@@ -49,6 +49,10 @@ require.config({
     'd3.tip': {
       deps: ['d3']
     },
+    'dagreD3':{
+      deps: ['d3'],
+      exports: 'dagreD3'
+    },
     'x-editable': {
       deps: ['bootstrap']
     }
@@ -70,7 +74,8 @@ require.config({
     'react-dom': '../libs/react/js/react-dom',
     'JSXTransformer': '../libs/jsx/JSXTransformer',
     'jsx': "../libs/jsx/jsx",
-    'x-editable':'../libs/Bootstrap/js/bootstrap-editable.min'
+    'x-editable':'../libs/Bootstrap/js/bootstrap-editable.min',
+    'dagreD3': '../libs/dagre-d3/dagre-d3.min'
   },
   jsx: {
     fileExtension: '.jsx',

http://git-wip-us.apache.org/repos/asf/ambari/blob/7e00f585/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx b/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx
index 24d3271..136d95f 100644
--- a/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx
+++ b/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx
@@ -50,7 +50,6 @@ define([
 			this.lagCollection = new BaseCollection();
 			this.systemFlag = false;
 			this.windowSize = ':all-time';
-			this.initializeData();
 			return {
 				model: this.model,
 				graphData: {},
@@ -63,6 +62,7 @@ define([
 		},
 		componentWillMount: function(){
 			$('.loader').show();
+			this.initializeData();
 		},
 		componentDidMount: function(){
 			$(".boot-switch.systemSum").bootstrapSwitch({
@@ -89,7 +89,6 @@ define([
 			$('.loader').hide();
 		},
 		componentWillUpdate: function(){
-			$('.loader').show();
 			$('#collapse-spout').off('hidden.bs.collapse');
 			$('#collapse-spout').off('shown.bs.collapse');
 			$('#collapse-bolt').off('hidden.bs.collapse');
@@ -122,7 +121,6 @@ define([
 			if(this.refs.barChart){
 				ReactDOM.findDOMNode(document.getElementById('lag-graph')).appendChild(this.refs.barChart.legendsEl)
 			}
-			$('.loader').hide();
 		},
 		initializeData: function(){
 			this.model.getData({
@@ -147,6 +145,7 @@ define([
 			this.initializeWorkerData();
 		},
 		initializeGraphData: function(){
+			$('#graphLoader').show();
 			this.model.getGraphData({
 				id: this.model.get('id'),
 				window: this.windowSize,
@@ -159,6 +158,7 @@ define([
 						}
 						this.setState({graphData: model});
 					}
+					$('#graphLoader').hide();
 				}.bind(this),
 				error: function(model, response, options){
 					Utils.notifyError("Error occured in fetching topology visualization data.");
@@ -184,23 +184,40 @@ define([
 		},
 
 		initializeLagData: function(){
+			$('#kafkaLoader').show();
 			this.model.getTopologyLag({
 				id: this.model.get('id'),
 				success: function(model, response){
 					if(response.error || model.error){
 						Utils.notifyError(response.error || model.error+'('+model.errorMessage.split('(')[0]+')');
 					} else {
-						if(model && model.length){
-							var result = JSON.parse(model[0].spoutLagResult);
-							for(var i = 0; i < result.length; i++){
-								result[i]['spoutId'] = model[0].spoutId;
-								result[i]['spoutType'] = model[0].spoutType;
+						if(model && _.keys(model).length > 0){
+							var keys = _.keys(model);
+							var arr = [];
+							for(var i = 0; i < keys.length; i++){
+								var data = model[keys[i]];
+								var topicKeys = _.keys(data.spoutLagResult);
+								for(var j = 0; j < topicKeys.length; j++){
+									var topicName = topicKeys[j];
+									var partitionData = data.spoutLagResult[topicName];
+									var id = _.keys(partitionData);
+									for(var k = 0; k < id.length; k++){
+										var partitionId = id[k];
+										var obj = partitionData[partitionId];
+										obj['spoutId'] = data.spoutId;
+										obj['spoutType'] = data.spoutType;
+										obj['partition'] = partitionId;
+										obj['topic'] = topicName;
+										arr.push(obj);
+									}
+								}
 							}
-							this.resetLagCollection(result);
+							this.resetLagCollection(arr);
 						} else {
 							this.setState({hideKafkaLagBox : true});
 						}
 					}
+					$('#kafkaLoader').hide();
 				}.bind(this)
 			})
 		},
@@ -788,6 +805,7 @@ define([
 					</div>
 					<div className="row">
 						<div className="col-sm-12">
+							<div className="inner-loader" id="graphLoader" />
 							<TopologyDetailGraph model={this.state.model} graphData={this.state.graphData}/>
 						</div>
 					</div>
@@ -811,7 +829,8 @@ define([
 									<div className="box-body">
 										<div className="row">
 											<div className="col-sm-12">
-												<div id="lag-graph" className="displayNone">
+												<div className="inner-loader" id="kafkaLoader" />
+												<div id="lag-graph">
 													{this.lagCollection.length > 0 ? 
 													<BarChart
 														ref="barChart"

http://git-wip-us.apache.org/repos/asf/ambari/blob/7e00f585/contrib/views/storm/src/main/resources/styles/style.css
----------------------------------------------------------------------
diff --git a/contrib/views/storm/src/main/resources/styles/style.css b/contrib/views/storm/src/main/resources/styles/style.css
index 4c51233..f6b1685 100644
--- a/contrib/views/storm/src/main/resources/styles/style.css
+++ b/contrib/views/storm/src/main/resources/styles/style.css
@@ -425,6 +425,18 @@ REACT
     position: absolute;
     text-align: center;
 }
+.node ellipse {
+  stroke: #333;
+  fill: #fff;
+  stroke-width: 1px;
+}
+.edgePath path {
+  stroke: grey;
+  fill: none;
+  cursor: default;
+  stroke-width: 2;
+  stroke-dasharray: 5, 5;
+}
 
 /* Style northward tooltips differently */
 .d3-tip.n:after {
@@ -533,6 +545,14 @@ ul.legends li.legend{
   background: url('../images/loader.gif') rgba(255,255,255,0.75) no-repeat center center;
   z-index: 9;
 }
+.inner-loader{
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  bottom: 0px;
+  right: 0px;
+  background: url('../images/loader.gif') rgba(255,255,255,0.75) no-repeat center center;
+}
 .searchbar{
   margin-top: 15px;
 }


Mime
View raw message