From 55e4828adcfbf51352c571900cc468b5563ad212 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Thu, 30 Mar 2023 09:50:14 +0800 Subject: [PATCH] feat: update trace profiling protocol (#250) --- src/assets/icons/cross.svg | 15 ++++ src/assets/icons/entry.svg | 15 ++++ src/assets/icons/exit.svg | 15 ++++ src/assets/img/tools/ENTRY.png | Bin 0 -> 262 bytes src/assets/img/tools/EXIT.png | Bin 0 -> 269 bytes src/assets/img/tools/STREAM.png | Bin 0 -> 373 bytes src/graphql/fragments/profile.ts | 79 ++++++++--------- src/graphql/query/profile.ts | 3 - src/store/modules/profile.ts | 71 +++++++-------- src/styles/lib.scss | 28 ++++++ src/types/trace.d.ts | 1 + .../profile/components/SegmentList.vue | 24 +++--- .../related/profile/components/SpanTree.vue | 44 ++++------ .../related/profile/components/TaskList.vue | 28 +++--- .../trace/components/Table/TableItem.vue | 81 +++++++++++++++--- .../related/trace/utils/d3-trace-list.ts | 58 +++++++++++++ 16 files changed, 320 insertions(+), 142 deletions(-) create mode 100644 src/assets/icons/cross.svg create mode 100644 src/assets/icons/entry.svg create mode 100644 src/assets/icons/exit.svg create mode 100644 src/assets/img/tools/ENTRY.png create mode 100644 src/assets/img/tools/EXIT.png create mode 100644 src/assets/img/tools/STREAM.png diff --git a/src/assets/icons/cross.svg b/src/assets/icons/cross.svg new file mode 100644 index 00000000..3f531cd6 --- /dev/null +++ b/src/assets/icons/cross.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/assets/icons/entry.svg b/src/assets/icons/entry.svg new file mode 100644 index 00000000..4a85fcfc --- /dev/null +++ b/src/assets/icons/entry.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/assets/icons/exit.svg b/src/assets/icons/exit.svg new file mode 100644 index 00000000..5eb99adf --- /dev/null +++ b/src/assets/icons/exit.svg @@ -0,0 +1,15 @@ + + \ No newline at end of file diff --git a/src/assets/img/tools/ENTRY.png b/src/assets/img/tools/ENTRY.png new file mode 100644 index 0000000000000000000000000000000000000000..52a33a0c1d1bff69d80bbf7f6899e03c0dd1448d GIT binary patch literal 262 zcmV+h0r~!kP)Px#z)3_wR5(wilgkalFc3t?4RD|W=!CRF1tU=aa7IeT6>z5sxKjjFz<~yg9NCc* z;z)`2vXbR}yR#pILNjSR$qj%b0Pn}_4d5)v`__hl7l1E-PX@3Cu#&X>1CZPSxJ&9m zhai#;KqcwXs~`sm?}!1j03=VLCtXI8H|N~NTKk-=AO;&__D$1VbHnQNrV^6Ot>a*$Ndk`O-^H8Fws{a7}}v9hy!5OgnJ*8l(j literal 0 HcmV?d00001 diff --git a/src/assets/img/tools/EXIT.png b/src/assets/img/tools/EXIT.png new file mode 100644 index 0000000000000000000000000000000000000000..88aca4957b26997803afc985b0821b694dd25e2e GIT binary patch literal 269 zcmV+o0rLKdP)Px#$4Nv%R5(wqlR*l?Fc3xa)7y9oZ_q@vf?Jn*2)%>1kdk!eMo@6&zIdE`i7-+{ z+oqcB%zyd(nSuK8p{X~6>A*@843^2xw0qjBuMK1@@E`Z`a3jkArv}Vu(SSY0? z&bc}%#0b<{pGeLJjWLEuax3EG5M_je#~6iei&T@`_gQ7F^-}KPf5+7I^SAmPXS#$D Tgw`w>00000NkvXXu0mjfYL0Y| literal 0 HcmV?d00001 diff --git a/src/assets/img/tools/STREAM.png b/src/assets/img/tools/STREAM.png new file mode 100644 index 0000000000000000000000000000000000000000..8e1c57f93c3a21f0f5948a494bbb01bdd4abadad GIT binary patch literal 373 zcmV-*0gC>KP)Px$FG)l}R5(wqlP^mIQ540`onb$NqS0*z7Yu5#FE&5JqF{MvM?*NBRkB1uf6-{$9w0VD<~aRJpr%-;FRQUIbXg@F%U)3 zQkG>mBo|fnz13=M4u`|nD##STIX5RF9{>gb_RVbGd;d8GsA?BLTSTtXG<}&srvT%i zb8byU?#yi6dw-udZveOjaBgN_-uvE6K;B>^f8qUpf6vTT#+s<=6Uk0fK-; segmentList: Trace[]; currentSegment: Recordable; segmentSpans: Array>; @@ -51,6 +52,7 @@ export const profileStore = defineStore({ condition: { serviceId: "", endpointName: "" }, taskList: [], segmentList: [], + currentTask: {}, currentSegment: {}, segmentSpans: [], currentSpan: {}, @@ -65,11 +67,27 @@ export const profileStore = defineStore({ ...data, }; }, + setCurrentTask(task: TaskListItem) { + this.currentTask = task || {}; + this.analyzeTrees = []; + }, + setSegmentSpans(spans: Recordable[]) { + this.currentSpan = spans[0] || {}; + this.segmentSpans = spans; + }, setCurrentSpan(span: Recordable) { this.currentSpan = span; + this.analyzeTrees = []; }, - setCurrentSegment(s: Recordable) { - this.currentSegment = s; + setCurrentSegment(segment: Trace) { + this.currentSegment = segment; + this.segmentSpans = segment.spans || []; + if (segment.spans) { + this.currentSpan = segment.spans[0] || {}; + } else { + this.currentSpan = {}; + } + this.analyzeTrees = []; }, setHighlightTop() { this.highlightTop = !this.highlightTop; @@ -104,8 +122,9 @@ export const profileStore = defineStore({ if (res.data.errors) { return res.data; } - const list = res.data.data.taskList; + const list = res.data.data.taskList || []; this.taskList = list; + this.currentTask = list[0] || {}; if (!list.length) { this.segmentList = []; this.segmentSpans = []; @@ -128,7 +147,7 @@ export const profileStore = defineStore({ } const { segmentList } = res.data.data; - this.segmentList = segmentList; + this.segmentList = segmentList || []; if (!segmentList.length) { this.segmentSpans = []; this.analyzeTrees = []; @@ -137,50 +156,22 @@ export const profileStore = defineStore({ } if (segmentList[0]) { this.currentSegment = segmentList[0]; - this.getSegmentSpans({ segmentId: segmentList[0].segmentId }); + this.getSegmentSpans(segmentList[0].segmentId); } else { this.currentSegment = {}; } return res.data; }, - async getSegmentSpans(params: { segmentId: string }) { - if (!params.segmentId) { - return new Promise((resolve) => resolve({})); - } - const res: AxiosResponse = await graphql.query("queryProfileSegment").params(params); - if (res.data.errors) { - this.segmentSpans = []; - return res.data; - } - const { segment } = res.data.data; - if (!segment) { - this.segmentSpans = []; - this.analyzeTrees = []; - return res.data; - } - this.segmentSpans = segment.spans.map((d: SegmentSpan) => { - return { - ...d, - segmentId: this.currentSegment?.segmentId, - traceId: (this.currentSegment.traceIds as any)[0], - }; - }); - if (!(segment.spans && segment.spans.length)) { - this.analyzeTrees = []; - return res.data; - } - const index = segment.spans.length - 1 || 0; - this.currentSpan = segment.spans[index]; - return res.data; + async getSegmentSpans() { + this.analyzeTrees = []; + this.segmentSpans = this.currentSegment.spans; + this.currentSpan = this.currentSegment.spans[0] || {}; }, - async getProfileAnalyze(params: { segmentId: string; timeRanges: Array<{ start: number; end: number }> }) { - if (!params.segmentId) { + async getProfileAnalyze(params: Array<{ segmentId: string; timeRange: { start: number; end: number } }>) { + if (!params.length) { return new Promise((resolve) => resolve({})); } - if (!params.timeRanges.length) { - return new Promise((resolve) => resolve({})); - } - const res: AxiosResponse = await graphql.query("getProfileAnalyze").params(params); + const res: AxiosResponse = await graphql.query("getProfileAnalyze").params({ queries: params }); if (res.data.errors) { this.analyzeTrees = []; diff --git a/src/styles/lib.scss b/src/styles/lib.scss index d0c1ecbe..9ea6b3d2 100644 --- a/src/styles/lib.scss +++ b/src/styles/lib.scss @@ -215,3 +215,31 @@ box-shadow: inset 0 0 6px #888; background-color: #999; } +.d3-tip { + line-height: 1; + padding: 8px; + color: #eee; + border-radius: 4px; + font-size: 12px; +} +.d3-tip { + background: #252a2f; +} + +.d3-tip:after { + box-sizing: border-box; + display: block; + font-size: 10px; + width: 100%; + line-height: 0.8; + color: #252a2f; + content: "\25BC"; + position: absolute; + text-align: center; +} + +.d3-tip.n:after { + margin: -2px 0 0 0; + top: 100%; + left: 0; +} diff --git a/src/types/trace.d.ts b/src/types/trace.d.ts index 9055e8a8..b71be5bb 100644 --- a/src/types/trace.d.ts +++ b/src/types/trace.d.ts @@ -22,6 +22,7 @@ export interface Trace { start: string; traceIds: Array; segmentId: string; + spans: Span[]; } export interface Span { diff --git a/src/views/dashboard/related/profile/components/SegmentList.vue b/src/views/dashboard/related/profile/components/SegmentList.vue index e19aeba1..23be2152 100644 --- a/src/views/dashboard/related/profile/components/SegmentList.vue +++ b/src/views/dashboard/related/profile/components/SegmentList.vue @@ -20,11 +20,11 @@ limitations under the License. --> {{ t("noData") }} - +
diff --git a/src/views/dashboard/related/profile/components/TaskList.vue b/src/views/dashboard/related/profile/components/TaskList.vue index 55c7f145..a3854227 100644 --- a/src/views/dashboard/related/profile/components/TaskList.vue +++ b/src/views/dashboard/related/profile/components/TaskList.vue @@ -25,7 +25,7 @@ limitations under the License. -->
@@ -49,7 +49,7 @@ limitations under the License. -->
-
+
{{ t("task") }}.
@@ -58,33 +58,35 @@ limitations under the License. -->
{{ t("endpoint") }}: - {{ selectedTask.endpointName }} + {{ profileStore.currentTask.endpointName }}
{{ t("monitorTime") }}: - {{ dateFormat(selectedTask.startTime) }} + {{ dateFormat(profileStore.currentTask.startTime) }}
{{ t("monitorDuration") }}:{{ selectedTask.duration }} min + >{{ profileStore.currentTask.duration }} min
{{ t("minThreshold") }}: - {{ selectedTask.minDurationThreshold }} ms + {{ profileStore.currentTask.minDurationThreshold }} ms
{{ t("dumpPeriod") }}: - {{ selectedTask.dumpPeriod }} + {{ profileStore.currentTask.dumpPeriod }}
{{ t("maxSamplingCount") }}: - {{ selectedTask.maxSamplingCount }} + {{ profileStore.currentTask.maxSamplingCount }}
-
{{ t("logs") }}.
+
+ {{ t("logs") }}. +
{{ t("instance") }}: @@ -115,12 +117,12 @@ limitations under the License. --> const selectorStore = useSelectorStore(); const viewDetail = ref(false); const service = ref(""); - const selectedTask = ref>({}); + // const selectedTask = ref>({}); const instanceLogs = ref({}); async function changeTask(item: TaskListItem) { profileStore.setCurrentSegment({}); - selectedTask.value = item; + profileStore.setCurrentTask(item); const res = await profileStore.getSegmentList({ taskID: item.id }); if (res.errors) { ElMessage.error(res.errors); @@ -130,7 +132,7 @@ limitations under the License. --> async function viewTask(e: Event, item: TaskListItem) { window.event ? (window.event.cancelBubble = true) : e.stopPropagation(); viewDetail.value = true; - selectedTask.value = item; + profileStore.setCurrentTask(item); service.value = (selectorStore.services.filter((s: any) => s.id === item.serviceId)[0] || {}).label; const res = await profileStore.getTaskLogs({ taskID: item.id }); @@ -150,7 +152,7 @@ limitations under the License. --> instanceLogs.value[d.instanceName] = [{ operationType: d.operationType, operationTime: d.operationTime }]; } } - selectedTask.value = item; + profileStore.setCurrentTask(item); }