view ref children

This commit is contained in:
Fine 2025-03-11 17:34:48 +08:00
parent 883cec9264
commit c4504b7423
6 changed files with 84 additions and 18 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

View File

@ -48,6 +48,7 @@ export interface Span {
logs?: log[];
parentSegmentId?: string;
refs?: Ref[];
refChildren?: Recordable;
}
export type Ref = {
type: string;

View File

@ -18,6 +18,9 @@ limitations under the License. -->
<el-dialog v-model="showDetail" :destroy-on-close="true" @closed="showDetail = false">
<SpanDetail :currentSpan="currentSpan" />
</el-dialog>
<el-dialog v-model="showRefsChildren" :destroy-on-close="true" @closed="showRefsChildren = false" width="850">
<div ref="refsChildrenTree" class="refs-children-tree"></div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, watch, onBeforeUnmount, onMounted } from "vue";
@ -30,6 +33,7 @@ limitations under the License. -->
import { useAppStoreWithOut } from "@/store/modules/app";
import { debounce } from "@/utils/debounce";
import { mutationObserver } from "@/utils/mutation";
import { ViewSpanType } from "../data";
/* global defineProps, Nullable, defineExpose, Recordable */
const props = defineProps({
@ -42,10 +46,12 @@ limitations under the License. -->
const showDetail = ref<boolean>(false);
const fixSpansSize = ref<number>(0);
const segmentId = ref<Recordable[]>([]);
const currentSpan = ref<Array<Span>>([]);
const currentSpan = ref<Span | Recordable>({});
const refSpans = ref<Array<Ref>>([]);
const tree = ref<Nullable<any>>(null);
const showRefsChildren = ref<boolean>(false);
const traceGraph = ref<Nullable<HTMLDivElement>>(null);
const refsChildrenTree = ref<Nullable<HTMLDivElement>>(null);
const debounceFunc = debounce(draw, 500);
defineExpose({
@ -84,20 +90,30 @@ limitations under the License. -->
tree.value.init({ label: `${props.traceId}`, children: segmentId.value }, props.data);
}
}
function handleSelectSpan(i: Recordable) {
currentSpan.value = i.data;
showDetail.value = true;
function drawRefsChildren() {
if (!refsChildrenTree.value) {
return;
}
d3.selectAll(".d3-tip").remove();
if (props.type === "List") {
tree.value = new ListGraph(refsChildrenTree.value, handleSelectSpan);
tree.value.init({ label: "", children: currentSpan.value.refChildren }, props.data, fixSpansSize.value);
tree.value.draw();
} else {
tree.value = new TreeGraph(refsChildrenTree.value, handleSelectSpan);
tree.value.init({ label: `${props.traceId}`, children: currentSpan.value.refChildren }, props.data);
}
}
function traverseTree(node: Recordable, spanId: string, segmentId: string, data: Recordable) {
if (!node || node.isBroken) {
return;
}
if (node.spanId === spanId && node.segmentId === segmentId) {
node.refChildren.push(data);
return;
}
for (const nodeItem of node.children || []) {
traverseTree(nodeItem, spanId, segmentId, data);
function handleSelectSpan(i: Recordable, type?: ViewSpanType) {
currentSpan.value = i.data;
if (type === ViewSpanType.REFS) {
showRefsChildren.value = true;
setTimeout(() => {
drawRefsChildren();
}, 300);
} else {
showDetail.value = true;
}
}
function changeTree() {
@ -317,6 +333,18 @@ limitations under the License. -->
return a - b;
};
}
function traverseTree(node: Recordable, spanId: string, segmentId: string, data: Recordable) {
if (!node || node.isBroken) {
return;
}
if (node.spanId === spanId && node.segmentId === segmentId) {
node.refChildren.push(data);
return;
}
for (const nodeItem of node.children || []) {
traverseTree(nodeItem, spanId, segmentId, data);
}
}
onBeforeUnmount(() => {
d3.selectAll(".d3-tip").remove();
window.removeEventListener("resize", debounceFunc);
@ -388,4 +416,9 @@ limitations under the License. -->
overflow: auto;
font-family: monospace;
}
.refs-children-tree {
height: 500px;
width: 800px;
}
</style>

View File

@ -27,7 +27,7 @@ limitations under the License. -->
</div>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import { computed, ref } from "vue";
import type { PropType } from "vue";
import { useI18n } from "vue-i18n";
import * as d3 from "d3";

View File

@ -0,0 +1,20 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export enum ViewSpanType {
REFS = "refs",
DETAILS = "details",
}

View File

@ -22,10 +22,11 @@ import dayjs from "dayjs";
import icons from "@/assets/img/icons";
import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
import { ViewSpanType } from "../components/data";
export default class ListGraph {
private barHeight = 48;
private handleSelectSpan: Nullable<(i: Trace) => void> = null;
private handleSelectSpan: Nullable<(i: Trace, type?: ViewSpanType) => void> = null;
private el: Nullable<HTMLDivElement> = null;
private i = 0;
private width = 0;
@ -223,7 +224,7 @@ export default class ListGraph {
nodeEnter
.append("text")
.attr("class", "node-text")
.attr("x", 35)
.attr("x", 48)
.attr("y", -6)
.attr("fill", (d: Recordable) => (d.data.isError ? `#e54c17` : appStore.theme === Themes.Dark ? "#eee" : "#333"))
.html((d: Recordable) => {
@ -233,6 +234,17 @@ export default class ListGraph {
const label = d.data.label.length > 30 ? `${d.data.label.slice(0, 30)}...` : `${d.data.label}`;
return label;
});
nodeEnter
.append("image")
.attr("width", 16)
.attr("height", 16)
.attr("x", 23)
.attr("y", -8)
.attr("xlink:href", (d: any) => (d.data.refChildren?.length ? icons.REFER : ``))
.on("click", (event: any, d: Trace) => {
event.stopPropagation();
this.handleSelectSpan && this.handleSelectSpan(d, ViewSpanType.REFS);
});
nodeEnter
.append("circle")
.attr("r", 10)
@ -272,7 +284,7 @@ export default class ListGraph {
nodeEnter
.append("text")
.attr("class", "node-text")
.attr("x", 35)
.attr("x", 48)
.attr("y", 12)
.attr("fill", appStore.theme === Themes.Dark ? "#777" : "#ccc")
.style("font-size", "11px")