From 74cb089271faad911d1e724ff655b8b75a73bfe8 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Thu, 26 May 2022 13:04:43 +0800 Subject: [PATCH] feat: sort spans with `startTime` or `spanId` in a segment (#100) --- src/store/modules/ebpf.ts | 3 ++ src/types/trace.d.ts | 9 ++++- src/views/dashboard/graphs/TopList.vue | 14 ++++++-- .../graphs/components/ColumnGraph.vue | 2 +- src/views/dashboard/related/ebpf/Content.vue | 2 +- .../related/ebpf/components/EBPFSchedules.vue | 7 ---- .../related/ebpf/components/EBPFStack.vue | 12 ++++--- .../dashboard/related/profile/Content.vue | 2 +- src/views/dashboard/related/trace/Detail.vue | 13 ++----- .../trace/components/D3Graph/Index.vue | 36 +++++++++++++++---- .../trace/components/D3Graph/SpanDetail.vue | 2 +- 11 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/store/modules/ebpf.ts b/src/store/modules/ebpf.ts index f43c649f..987422b8 100644 --- a/src/store/modules/ebpf.ts +++ b/src/store/modules/ebpf.ts @@ -35,6 +35,7 @@ interface EbpfStore { couldProfiling: boolean; tip: string; selectedTask: Recordable; + aggregateType: string; } export const ebpfStore = defineStore({ @@ -48,6 +49,7 @@ export const ebpfStore = defineStore({ couldProfiling: false, tip: "", selectedTask: {}, + aggregateType: "COUNT", }), actions: { setSelectedTask(task: EBPFTaskList) { @@ -131,6 +133,7 @@ export const ebpfStore = defineStore({ timeRanges: Array<{ start: number; end: number }>; aggregateType: string; }) { + this.aggregateType = params.aggregateType; if (!params.scheduleIdList.length) { return new Promise((resolve) => resolve({})); } diff --git a/src/types/trace.d.ts b/src/types/trace.d.ts index 82e0f669..569e7173 100644 --- a/src/types/trace.d.ts +++ b/src/types/trace.d.ts @@ -46,8 +46,15 @@ export interface Span { children?: Span[]; tags?: Array>; logs?: log[]; + parentSegmentId?: string; + refs?: Ref[]; } - +export type Ref = { + type: string; + parentSegmentId: string; + parentSpanId: number; + traceId: string; +}; export interface log { time: number; data: Map; diff --git a/src/views/dashboard/graphs/TopList.vue b/src/views/dashboard/graphs/TopList.vue index 8fe0f72f..dcfcab29 100644 --- a/src/views/dashboard/graphs/TopList.vue +++ b/src/views/dashboard/graphs/TopList.vue @@ -17,13 +17,13 @@ limitations under the License. -->
-
+
{{ i.value }} {{ i.name }}
-
+
diff --git a/src/views/dashboard/related/ebpf/Content.vue b/src/views/dashboard/related/ebpf/Content.vue index 019a20c4..f308004e 100644 --- a/src/views/dashboard/related/ebpf/Content.vue +++ b/src/views/dashboard/related/ebpf/Content.vue @@ -38,7 +38,7 @@ import EBPFStack from "./components/EBPFStack.vue"; .vis-graph { height: 100%; - width: calc(100% - 300px); + flex-grow: 2; min-width: 700px; overflow: auto; } diff --git a/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue b/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue index 191b0097..7609aba8 100644 --- a/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue +++ b/src/views/dashboard/related/ebpf/components/EBPFSchedules.vue @@ -252,13 +252,6 @@ watch( min-width: 560px; } -.schedules { - width: calc(100% - 5px); - margin: 0 5px 5px 0; - height: calc(100% - 60px); - min-height: 150px; -} - .inputs { width: 350px; } diff --git a/src/views/dashboard/related/ebpf/components/EBPFStack.vue b/src/views/dashboard/related/ebpf/components/EBPFStack.vue index adccea90..b69d62f6 100644 --- a/src/views/dashboard/related/ebpf/components/EBPFStack.vue +++ b/src/views/dashboard/related/ebpf/components/EBPFStack.vue @@ -24,6 +24,7 @@ import d3tip from "d3-tip"; import { flamegraph } from "d3-flame-graph"; import { useEbpfStore } from "@/store/modules/ebpf"; import { StackElement } from "@/types/ebpf"; +import { AggregateTypes } from "./data"; import "d3-flame-graph/dist/d3-flamegraph.css"; /*global Nullable*/ @@ -86,10 +87,13 @@ function drawGraph() { const tip = (d3tip as any)() .attr("class", "d3-tip") .direction("w") - .html( - (d: { data: StackElement }) => - `
Symbol: ${d.data.name}
Dump Count: ${d.data.dumpCount}
` - ) + .html((d: { data: StackElement }) => { + const valStr = + ebpfStore.aggregateType === AggregateTypes[0].value + ? `
Dump Count: ${d.data.dumpCount}
` + : `
Duration: ${d.data.dumpCount} ns
`; + return `
Symbol: ${d.data.name}
${valStr}`; + }) .style("max-width", "500px"); flameChart.value.tooltip(tip); d3.select("#graph-stack").datum(stackTree.value).call(flameChart.value); diff --git a/src/views/dashboard/related/profile/Content.vue b/src/views/dashboard/related/profile/Content.vue index de5cc6ce..c5260ba7 100644 --- a/src/views/dashboard/related/profile/Content.vue +++ b/src/views/dashboard/related/profile/Content.vue @@ -56,7 +56,7 @@ function loadTrees(l: boolean) { .item { height: 100%; - width: calc(100% - 300px); + flex-grow: 2; overflow: auto; } diff --git a/src/views/dashboard/related/trace/Detail.vue b/src/views/dashboard/related/trace/Detail.vue index 4b2cda82..4d217ce1 100644 --- a/src/views/dashboard/related/trace/Detail.vue +++ b/src/views/dashboard/related/trace/Detail.vue @@ -153,7 +153,6 @@ import { useI18n } from "vue-i18n"; import { useTraceStore } from "@/store/modules/trace"; import { Option } from "@/types/app"; import copy from "@/utils/copy"; -import List from "./components/List.vue"; import graphs from "./components/index"; import LogTable from "@/views/dashboard/related/components/LogTable/Index.vue"; import { ElMessage } from "element-plus"; @@ -162,7 +161,6 @@ export default defineComponent({ name: "TraceDetail", components: { ...graphs, - List, LogTable, }, setup() { @@ -182,14 +180,8 @@ export default defineComponent({ dayjs(date).format(pattern); const showTraceLogs = ref(false); - function handleClick(ids: string[] | any) { - let copyValue = null; - if (ids.length === 1) { - copyValue = ids[0]; - } else { - copyValue = ids.join(","); - } - copy(copyValue); + function handleClick() { + copy(traceId.value || traceStore.currentTrace.traceIds[0].value); } async function changeTraceId(opt: Option[] | any) { @@ -235,6 +227,7 @@ export default defineComponent({ pageNum, loading, total, + traceId, }; }, }); diff --git a/src/views/dashboard/related/trace/components/D3Graph/Index.vue b/src/views/dashboard/related/trace/components/D3Graph/Index.vue index 893a45fb..35f3db68 100644 --- a/src/views/dashboard/related/trace/components/D3Graph/Index.vue +++ b/src/views/dashboard/related/trace/components/D3Graph/Index.vue @@ -31,7 +31,7 @@ import _ from "lodash"; import * as d3 from "d3"; import ListGraph from "../../utils/d3-trace-list"; import TreeGraph from "../../utils/d3-trace-tree"; -import { Span } from "@/types/trace"; +import { Span, Ref } from "@/types/trace"; import SpanDetail from "./SpanDetail.vue"; /* global defineProps, Nullable, defineExpose*/ @@ -45,6 +45,7 @@ const showDetail = ref(false); const fixSpansSize = ref(0); const segmentId = ref([]); const currentSpan = ref>([]); +const refSpans = ref>([]); const tree = ref(null); const traceGraph = ref>(null); defineExpose({ @@ -103,14 +104,17 @@ function changeTree() { segmentId.value = []; const segmentGroup: any = {}; const segmentIdGroup: any = []; - const fixSpans: any[] = []; - const segmentHeaders: any = []; + const fixSpans: Span[] = []; + const segmentHeaders: Span[] = []; for (const span of props.data) { + if (span.refs.length) { + refSpans.value.push(...span.refs); + } if (span.parentSpanId === -1) { segmentHeaders.push(span); } else { - const index = props.data.findIndex( - (i: any) => + const item = props.data.find( + (i: Span) => i.segmentId === span.segmentId && i.spanId === span.spanId - 1 ); const fixSpanKeyContent = { @@ -119,7 +123,7 @@ function changeTree() { spanId: span.spanId - 1, parentSpanId: span.spanId - 2, }; - if (index === -1 && !_.find(fixSpans, fixSpanKeyContent)) { + if (!item && !_.find(fixSpans, fixSpanKeyContent)) { fixSpans.push({ ...fixSpanKeyContent, refs: [], @@ -133,6 +137,8 @@ function changeTree() { layer: "Broken", tags: [], logs: [], + startTime: 0, + endTime: 0, }); } } @@ -167,6 +173,8 @@ function changeTree() { layer: "Broken", tags: [], logs: [], + startTime: 0, + endTime: 0, }); } // if root broken node is not exist, create a root broken node. @@ -191,6 +199,8 @@ function changeTree() { layer: "Broken", tags: [], logs: [], + startTime: 0, + endTime: 0, }); } } @@ -268,14 +278,28 @@ function changeTree() { } function collapse(d: Span) { if (d.children) { + const item = refSpans.value.find( + (s: Ref) => + s.parentSpanId === d.spanId && s.parentSegmentId === d.segmentId + ); let dur = d.endTime - d.startTime; d.children.forEach((i: Span) => { dur -= i.endTime - i.startTime; }); d.dur = dur < 0 ? 0 : dur; + if (item) { + d.children = d.children.sort(compare("startTime")); + } d.children.forEach((i: Span) => collapse(i)); } } +function compare(p: string) { + return (m: any, n: any) => { + const a = m[p]; + const b = n[p]; + return a - b; + }; +} onBeforeUnmount(() => { d3.selectAll(".d3-tip").remove(); window.removeEventListener("resize", resize); diff --git a/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue b/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue index 89a1046d..6aee1770 100644 --- a/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue +++ b/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue @@ -52,7 +52,7 @@ limitations under the License. --> class="grey link-hover cp ml-5" @click="copy(i.value)" > - +