You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2018/12/24 16:28:21 UTC
[incubator-skywalking-ui] branch master updated: Update: update
traceTree (#212)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git
The following commit(s) were added to refs/heads/master by this push:
new 2675c06 Update: update traceTree (#212)
2675c06 is described below
commit 2675c06033e1bc9b046461e0337c029e7d4292da
Author: Allen Wang <Al...@outlook.com>
AuthorDate: Tue Dec 25 00:28:17 2018 +0800
Update: update traceTree (#212)
1. Add tooltip plugin.
2. Add the connection between timeline span & tree span.
3. remove unnessory event bind and nodes.
4. update the tree display.
---
package.json | 1 +
src/components/TraceTree/d3-trace.js | 282 ++++++++++++++++++-----------------
src/components/TraceTree/style.less | 89 ++++++++---
3 files changed, 215 insertions(+), 157 deletions(-)
diff --git a/package.json b/package.json
index d080282..ea3d263 100755
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"cytoscape-cose-bilkent": "^4.0.0",
"cytoscape-dagre": "^2.2.1",
"d3": "^5.7.0",
+ "d3-tip": "^0.9.1",
"dva": "^2.2.3",
"dva-loading": "^2.0.3",
"enquire-js": "^0.2.1",
diff --git a/src/components/TraceTree/d3-trace.js b/src/components/TraceTree/d3-trace.js
index 3d8a709..1645581 100644
--- a/src/components/TraceTree/d3-trace.js
+++ b/src/components/TraceTree/d3-trace.js
@@ -17,7 +17,7 @@
/* eslint-disable */
import * as d3 from 'd3';
-
+import d3tip from 'd3-tip';
export default class TraceMap {
constructor(el) {
this.type = {
@@ -44,7 +44,7 @@ export default class TraceMap {
.remove();
this.width = this.el.clientWidth;
this.height = this.el.clientHeight;
- this.draw(this.data,this.row,this.showSpanModal);
+ this.draw(this.data, this.row);
}
draw(data, row, showSpanModal) {
this.showSpanModal = showSpanModal;
@@ -72,7 +72,9 @@ export default class TraceMap {
.append('svg')
.attr('width', this.width)
.attr('height', this.height);
- this.timeGroup = this.body.append('g').attr('transform', d => 'translate(5,30)');
+ this.timeGroup = this.body
+ .append('g')
+ .attr('transform', d => 'translate(5,30)');
const main = this.body
.append('g')
.attr('transform', d => 'translate(0,' + this.row.length * 9 + ')');
@@ -84,155 +86,188 @@ export default class TraceMap {
.append('g')
.attr('transform', `translate(5,20)`)
.call(this.xAxis);
+
+ this.updatexAxis(this.root);
this.update(this.root);
}
- update(source) {
+ updatexAxis(source) {
const treeData = this.treemap(this.root);
const nodes = treeData.descendants(),
links = treeData.descendants().slice(1);
let index = -1;
nodes.forEach(function(d) {
d.y = d.depth * 200;
- d.timeX = ++index * 7;
- });
-
- this.body.call(this.getZoomBehavior(this.svg));
-
- const node = this.svg.selectAll('g.node').data(nodes, d => {
- return d.id || (d.id = ++this.i);
+ d.timeX = ++index * 12;
});
+ // time
const timeNode = this.timeGroup.selectAll('g.time').data(nodes, d => {
- return d.id || (d.id = ++this.j);
+ return d.id;
});
+ this.timeTip = d3tip()
+ .attr('class', 'd3-tip')
+ .offset([-10, 0])
+ .html(function(d) {
+ return d.data.label;
+ });
+ this.body.call(this.timeTip);
- // time
+ const that = this;
const timeEnter = timeNode
.enter()
.append('g')
.attr('class', 'time')
- .attr('transform', d => 'translate(' + 0 + ',' + d.timeX + ')');
+ .attr('transform', d => 'translate(' + 0 + ',' + d.timeX + ')')
+ .on('mouseover', function(d, i) {
+ that.timeTip.show(d, that.timeUpdate._groups[0][i].children[1]);
+ that.tip.show(d, that.nodeUpdate._groups[0][i]);
+ })
+ .on('mouseout', function(d, i) {
+ that.timeTip.hide(d, that.timeUpdate._groups[0][i].children[1]);
+ that.tip.hide(d, that.nodeUpdate._groups[0][i]);
+ })
+ .on('click', (d, i) => {
+ this.showSpanModal(
+ d.data,
+ { width: '100%', top: -10, left: '0' },
+ d3.select(that.timeUpdate._groups[0][i]).append('rect')
+ );
+ d3.event.stopPropagation();
+ });
+ this.timeEnter = timeEnter;
timeEnter
.append('rect')
- .attr('height', 5)
+ .attr('height', 10)
+ .attr('width', this.width)
+ .attr('y', -4)
+ .attr('class', 'time-bg');
+ timeEnter
+ .append('rect')
+ .attr('class', 'time-inner')
+ .attr('height', 8)
.attr('width', d => {
if (!d.data.endTime || !d.data.startTime) return 0;
return this.xScale(d.data.endTime - d.data.startTime) + 1;
})
.attr('rx', 2)
.attr('ry', 2)
- .attr(
- 'x',
- d => (!d.data.endTime || !d.data.startTime ? 0 : this.xScale(d.data.startTime - this.min))
+ .attr('x', d =>
+ !d.data.endTime || !d.data.startTime
+ ? 0
+ : this.xScale(d.data.startTime - this.min)
)
.attr('y', -3)
- .style('fill', d => `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`);
- var timeUpdate = timeEnter.merge(timeNode);
-
- timeUpdate
+ .style(
+ 'fill',
+ d =>
+ `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
+ );
+ this.timeUpdate = timeEnter.merge(timeNode);
+ this.timeUpdate
.transition()
.duration(600)
.attr('transform', function(d) {
return 'translate(' + 0 + ',' + d.timeX + ')';
});
+
const timeExit = timeNode
.exit()
.transition()
.duration(600)
.attr('transform', function(d) {
- return 'translate(' + 0 + ',' + 8 + ')';
+ return 'translate(' + 0 + ',' + 10 + ')';
})
.remove();
+ }
+ update(source) {
+ const treeData = this.treemap(this.root);
+ const nodes = treeData.descendants(),
+ links = treeData.descendants().slice(1);
+ let index = -1;
+ nodes.forEach(function(d) {
+ d.y = d.depth * 200;
+ d.timeX = ++index * 10;
+ });
+ this.tip = d3tip()
+ .attr('class', 'd3-tip')
+ .offset([-10, 0])
+ .html(function(d) {
+ return d.data.label;
+ });
+
+ this.body.call(this.getZoomBehavior(this.svg));
+ this.body.call(this.tip);
+ const node = this.svg.selectAll('g.node').data(nodes, d => {
+ return d.id || (d.id = ++this.i);
+ });
// node
+ const that = this;
const nodeEnter = node
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', function(d) {
return 'translate(' + source.y0 + ',' + source.x0 + ')';
- });
+ })
+ .on('mouseover', function(d, i) {
+ that.tip.show(d, this);
+ that.timeTip.show(d, that.timeUpdate._groups[0][i].children[1]);
+ })
+ .on('mouseout', function(d, i) {
+ that.tip.hide(d, this);
+ that.timeTip.hide(d, that.timeUpdate._groups[0][i].children[1]);
+ })
+ .on('click', (d, i) => {
+ this.showSpanModal(
+ d.data,
+ { width: '100%', top: -10, left: '0' },
+ d3.select(nodeEnter._groups[0][i]).append('rect')
+ );
+ d3.event.stopPropagation();
+ });
nodeEnter
.append('rect')
.attr('class', 'block')
.attr('x', '0')
- .attr('y', '-16')
- .attr('rx', 4)
- .attr('ry', 4)
+ .attr('y', '-20')
.attr('fill', d => (d.data.isError ? '#ff57221a' : '#f7f7f7'))
- .attr('stroke', d => (d.data.isError ? '#ff5722aa' : '#e4e4e4'))
- .on('click', (d, i) => {
- this.showSpanModal(
- d.data,
- { width: '100%', top: -10, left: '0' },
- d3.select(nodeEnter._groups[0][i]).append('rect')
- );
- })
- .on('mouseenter', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 1);
- })
- .on('mouseleave', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 0);
- });
-
- const tooltip = nodeEnter
- .append('g')
- .attr('opacity', 0)
- .attr('transform', function(d) {
- return 'translate(0,-40)';
- });
+ .attr('stroke', d => (d.data.isError ? '#ff5722aa' : '#e4e4e4'));
- tooltip
+ nodeEnter
.append('rect')
- .attr('class', 'tooltip-box')
- .attr('rx', 4)
- .attr('ry', 4)
- .attr('width', function(d) {
- return d.data.label.length * 6 + 20;
- });
- tooltip
- .append('text')
- .attr('dy', 14)
- .attr('fill', '#fafafa')
- .attr('dx', 10)
- .text(function(d) {
- return d.data.label;
+ .attr('class', 'content')
+ .style('fill', '#fff')
+ .attr('stroke', d => {
+ console.log(d);
+ return d.data.isError ? '#ff5722aa' : '#e4e4e4';
});
nodeEnter
+ .append('rect')
+ .attr('class', 'service')
+ .attr('x', '-0.5')
+ .attr('y', '-20.5')
+ .style(
+ 'fill',
+ d =>
+ `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
+ );
+ nodeEnter
.append('text')
- .attr('dy', -4)
- .attr('x', 5)
+ .attr('dy', 13)
+ .attr('dx', 10)
+ .attr('stroke', '#333')
.attr('text-anchor', function(d) {
return 'start';
})
.text(function(d) {
- return d.data.label.length > 23 ? d.data.label.slice(0, 23) : d.data.label;
- })
- .on('click', (d, i) => {
- this.showSpanModal(
- d.data,
- { width: '100%', top: -10, left: '0' },
- d3.select(nodeEnter._groups[0][i]).append('rect')
- );
- d3.event.stopPropagation();
- })
- .on('mouseenter', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 1);
- })
- .on('mouseleave', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 0);
+ return d.data.label.length > 19
+ ? d.data.label.slice(0, 19)
+ : d.data.label;
});
nodeEnter
.append('text')
- .attr('dy', 12)
- .attr('x', 8)
+ .attr('dy', -7)
+ .attr('dx', 12)
.attr('text-anchor', function(d) {
return 'start';
})
@@ -244,78 +279,45 @@ export default class TraceMap {
})
.text(function(d) {
return d.data.layer;
- })
- .on('click', (d, i) => {
- this.showSpanModal(
- d.data,
- { width: '100%', top: -10, left: '0' },
- d3.select(nodeEnter._groups[0][i]).append('rect')
- );
- d3.event.stopPropagation();
- })
- .on('mouseenter', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 1);
- })
- .on('mouseleave', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 0);
});
nodeEnter
.append('text')
- .attr('dy', 12)
- .attr('x', 70)
+ .attr('dy', -7)
+ .attr('x', 95)
+ .attr('stroke', '#333')
.attr('text-anchor', function(d) {
return 'start';
})
.text(function(d) {
- return d.data.endTime ? d.data.endTime - d.data.startTime + ' ms' : d.data.traceId;
- })
- .on('click', (d, i) => {
- this.showSpanModal(
- d.data,
- { width: '100%', top: -10, left: '0' },
- d3.select(nodeEnter._groups[0][i]).append('rect')
- );
- d3.event.stopPropagation();
- })
- .on('mouseenter', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 1);
- })
- .on('mouseleave', function(currNode, i) {
- d3.select(nodeEnter._groups[0][i])
- .select('g')
- .attr('opacity', 0);
+ return d.data.endTime
+ ? d.data.endTime - d.data.startTime + ' ms'
+ : d.data.traceId;
});
nodeEnter
.append('circle')
.attr('class', 'node')
.attr('r', 4)
- .attr('cx', '150')
+ .attr('cx', '158')
.style('fill', function(d) {
return d._children ? '#8543e0aa' : '#fff';
})
.on('click', click);
- var nodeUpdate = nodeEnter.merge(node);
+ this.nodeUpdate = nodeEnter.merge(node);
- nodeUpdate
+ this.nodeUpdate
.transition()
.duration(600)
.attr('transform', function(d) {
return 'translate(' + d.y + ',' + d.x + ')';
});
- nodeUpdate
+ this.nodeUpdate
.select('circle.node')
.attr('r', 4)
- .attr('cx', '156')
+ .attr('cx', '158')
.style('fill', function(d) {
return d._children ? '#8543e0aa' : '#fff';
})
@@ -373,10 +375,12 @@ export default class TraceMap {
function diagonal(s, d) {
return `M ${s.y} ${s.x}
- L ${d.y + 158} ${d.x}`;
+ C ${s.y - 30} ${s.x}, ${d.y + 188} ${d.x},
+ ${d.y + 158} ${d.x}`;
}
- const that = this;
- function click(d) {
+ function click(d, i) {
+ that.tip.hide(d, this);
+ that.timeTip.hide(d, that.timeUpdate._groups[0][i]);
if (d.children) {
d._children = d.children;
d.children = null;
@@ -384,7 +388,9 @@ export default class TraceMap {
d.children = d._children;
d._children = null;
}
+ that.updatexAxis(d);
that.update(d);
+ d3.event.stopPropagation();
}
}
getZoomBehavior(g) {
@@ -394,7 +400,9 @@ export default class TraceMap {
.on('zoom', () => {
g.attr(
'transform',
- `translate(${d3.event.transform.x},${d3.event.transform.y})scale(${d3.event.transform.k})`
+ `translate(${d3.event.transform.x},${d3.event.transform.y})scale(${
+ d3.event.transform.k
+ })`
);
});
}
diff --git a/src/components/TraceTree/style.less b/src/components/TraceTree/style.less
index 28f95a8..90093ff 100644
--- a/src/components/TraceTree/style.less
+++ b/src/components/TraceTree/style.less
@@ -14,30 +14,79 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- :global(.trace-tree .node) {
+
+:global(.trace-tree) {
+ height: 1000px;
+}
+:global(.trace-tree .node) {
+ cursor: pointer;
+}
+:global(.trace-tree .node circle) {
+ stroke: #ddd;
+ stroke-width: 1.5px;
+}
+:global(.trace-tree .time-inner) {
+ cursor: pointer;
+}
+:global(.trace-tree .time-bg) {
+ fill: #fff;
cursor: pointer;
}
- :global(.trace-tree .node circle) {
- stroke: #8543e0aa;
- stroke-width: 1.5px;
+:global(.trace-tree .time:hover) {
+ :global(.time-bg){
+ fill: rgba(0, 0, 0, 0.1);
}
+}
:global(.trace-tree .node text) {
- font: 12px sans-serif;
- stroke-width: 0.5;
- }
+ font-size: 12px;
+ font-family: 'Courier New', Courier, monospace;
+ stroke-width: 0.5;
+}
:global(.trace-tree .node .block) {
- width: 150px;
- height: 34px;
- }
+ width: 158px;
+ height: 40px;
+}
+:global(.trace-tree .node .content) {
+ width: 158px;
+ height: 20px;
+}
+:global(.trace-tree .node .service) {
+ width: 7px;
+ height: 41px;
+}
:global(.trace-tree .link) {
- fill: none;
- stroke: #8543e055;
- stroke-width: 2px;
- }
+ fill: none;
+ stroke: #ddd;
+ stroke-width: 1.5px;
+}
:global(.trace-tree .domain) {
- opacity: 0;
- }
-:global(.trace-tree .tooltip-box) {
- fill: #333;
- height: 20px !important;
- }
+ opacity: 0;
+}
+:global(.d3-tip) {
+ line-height: 1;
+ padding: 6px;
+ background: rgba(0, 0, 0, 0.8);
+ color: #fff;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+/* Creates a small triangle extender for the tooltip */
+:global(.d3-tip:after) {
+ box-sizing: border-box;
+ display: inline;
+ font-size: 10px;
+ width: 100%;
+ line-height: 1;
+ color: rgba(0, 0, 0, 0.8);
+ content: '\25BC';
+ position: absolute;
+ text-align: center;
+}
+
+/* Style northward tooltips specifically */
+:global(.d3-tip.n:after) {
+ margin: -2px 0 0 0;
+ top: 100%;
+ left: 0;
+}