highlighted parents

This commit is contained in:
Fine 2025-03-27 11:27:18 +08:00
parent ee1f2f586f
commit 9f9bf8b20a
2 changed files with 66 additions and 10 deletions

View File

@ -17,7 +17,9 @@ limitations under the License. -->
<div ref="traceGraph" class="d3-graph"></div> <div ref="traceGraph" class="d3-graph"></div>
<div id="action-box"> <div id="action-box">
<div @click="showDetail = true">Span Details</div> <div @click="showDetail = true">Span Details</div>
<div v-for="span in parentSpans" :key="span.parentSegmentId">{{ `Parent Span: ${span.parentSegmentId}` }}</div> <div v-for="span in parentSpans" :key="span.parentSegmentId" @click="viewParentSpan">{{
`Parent Span: ${span.parentSegmentId}`
}}</div>
</div> </div>
<el-dialog v-model="showDetail" :destroy-on-close="true" @closed="showDetail = false" v-if="currentSpan?.segmentId"> <el-dialog v-model="showDetail" :destroy-on-close="true" @closed="showDetail = false" v-if="currentSpan?.segmentId">
<SpanDetail :currentSpan="currentSpan" /> <SpanDetail :currentSpan="currentSpan" />
@ -97,16 +99,26 @@ limitations under the License. -->
} }
} }
function handleSelectSpan(i: Recordable) { function handleSelectSpan(i: Recordable) {
parentSpans.value = [];
currentSpan.value = i.data; currentSpan.value = i.data;
parentSpans.value = currentSpan.value?.refs?.filter((d) => d) || []; parentSpans.value = [];
if (currentSpan.value?.parentSpanId !== -1) { if (!currentSpan.value) {
return;
}
for (const ref of currentSpan.value.refs || []) {
parentSpans.value.push(ref);
}
if ((currentSpan.value.parentSpanId ?? -1) > -1) {
parentSpans.value.push({ parentSpans.value.push({
parentSegmentId: currentSpan.value?.segmentId || "", parentSegmentId: currentSpan.value.segmentId,
parentSpanId: currentSpan.value?.parentSpanId || NaN, parentSpanId: currentSpan.value.parentSpanId,
traceId: currentSpan.value?.traceId || "", traceId: currentSpan.value.traceId,
}); });
} }
} }
function viewParentSpan() {
tree.value.highlightParents();
}
function traverseTree(node: Recordable, spanId: string, segmentId: string, data: Recordable) { function traverseTree(node: Recordable, spanId: string, segmentId: string, data: Recordable) {
if (!node || node.isBroken) { if (!node || node.isBroken) {
return; return;
@ -409,6 +421,11 @@ limitations under the License. -->
fill: #409eff; fill: #409eff;
} }
.trace-node.highlightedParent .node-text {
font-weight: bold;
fill: #4caf50;
}
#action-box { #action-box {
position: absolute; position: absolute;
color: $font-color; color: $font-color;

View File

@ -87,6 +87,7 @@ export default class ListGraph {
} }
init(data: Recordable, row: Recordable[], fixSpansSize: number) { init(data: Recordable, row: Recordable[], fixSpansSize: number) {
d3.select(`.${this.el?.className} .trace-xaxis`).remove(); d3.select(`.${this.el?.className} .trace-xaxis`).remove();
d3.select("#action-box").style("display", "none");
this.row = row; this.row = row;
this.data = data; this.data = data;
this.min = d3.min(this.row.map((i) => i.startTime)); this.min = d3.min(this.row.map((i) => i.startTime));
@ -117,10 +118,10 @@ export default class ListGraph {
} }
draw(callback: Function) { draw(callback: Function) {
this.update(this.root, callback); this.update(this.root, callback);
d3.select("body").on("click", function (event) { // d3.select("body").on("click", function (event) {
if (event.target.closest("#action-box")) return; // if (event.target.closest("#action-box")) return;
d3.select("#action-box").style("display", "none"); // d3.select("#action-box").style("display", "none");
}); // });
} }
click(d: Recordable, scope: Recordable) { click(d: Recordable, scope: Recordable) {
if (!d.data.type) return; if (!d.data.type) return;
@ -147,6 +148,7 @@ export default class ListGraph {
.enter() .enter()
.append("g") .append("g")
.attr("transform", `translate(${source.y0},${source.x0})`) .attr("transform", `translate(${source.y0},${source.x0})`)
.attr("id", (d: Recordable) => `list-node-${d.id}`)
.attr("class", "trace-node") .attr("class", "trace-node")
.attr("style", "cursor: pointer") .attr("style", "cursor: pointer")
.on("mouseover", function (event: MouseEvent, d: Trace) { .on("mouseover", function (event: MouseEvent, d: Trace) {
@ -175,6 +177,10 @@ export default class ListGraph {
if (t.handleSelectSpan) { if (t.handleSelectSpan) {
t.handleSelectSpan(d); t.handleSelectSpan(d);
} }
t.root.descendants().map((node: { id: number }) => {
d3.select(`#list-node-${node.id}`).classed("highlightedParent", false);
return node;
});
}); });
nodeEnter nodeEnter
.append("rect") .append("rect")
@ -401,6 +407,39 @@ export default class ListGraph {
callback(); callback();
} }
} }
highlightParents() {
if (!this.selectedNode) {
return;
}
const nodes = this.root.descendants().map((node: { id: number }) => {
d3.select(`#list-node-${node.id}`).classed("highlightedParent", false);
return node;
});
const selectedNode = this.selectedNode.datum();
const parentSpans = selectedNode.data.refs.map((d: Recordable) => d);
if (selectedNode.data?.parentSpanId !== -1) {
parentSpans.push({
parentSegmentId: selectedNode.data.segmentId,
parentSpanId: selectedNode.data.parentSpanId,
traceId: selectedNode.data.traceId,
});
}
const parents = parentSpans.map((d: Recordable) => {
return nodes.find(
(node: Recordable) =>
d.parentSpanId === node.data.spanId &&
d.parentSegmentId === node.data.segmentId &&
d.traceId === node.data.traceId,
);
});
for (const node of parents) {
if (node) {
d3.select(`#list-node-${node.id}`).classed("highlightedParent", true);
}
}
d3.select("#action-box").style("display", "none");
this.selectedNode.classed("highlighted", false);
}
visDate(date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") { visDate(date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") {
return dayjs(date).format(pattern); return dayjs(date).format(pattern);
} }