This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-booster-ui.git
The following commit(s) were added to refs/heads/main by this push:
new 860af150 fix: enhance VNode logic and support multiple Trace IDs in
span's ref (#369)
860af150 is described below
commit 860af150f71f8dd0a2cbf555c8f7bd97954c5e53
Author: Fine0830 <[email protected]>
AuthorDate: Mon Jan 29 23:09:00 2024 +0800
fix: enhance VNode logic and support multiple Trace IDs in span's ref (#369)
---
src/hooks/useDashboardsSession.ts | 5 +-
src/store/modules/dashboard.ts | 1 -
src/views/dashboard/related/trace/Filter.vue | 10 ++-
src/views/dashboard/related/trace/TraceList.vue | 3 +-
.../related/trace/components/D3Graph/Index.vue | 87 ++++++++++++----------
.../trace/components/D3Graph/SpanDetail.vue | 37 ++++++++-
6 files changed, 95 insertions(+), 48 deletions(-)
diff --git a/src/hooks/useDashboardsSession.ts
b/src/hooks/useDashboardsSession.ts
index a97d7c33..3fc9d1af 100644
--- a/src/hooks/useDashboardsSession.ts
+++ b/src/hooks/useDashboardsSession.ts
@@ -24,7 +24,7 @@ export default function getDashboard(param?: { name?: string;
layer: string; ent
const dashboardStore = useDashboardStore();
const opt = param || dashboardStore.currentDashboard;
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
- let dashboard;
+ let dashboard: Recordable;
if (type === ConfigFieldTypes.NAME) {
dashboard = list.find(
(d: { name: string; layer: string; entity: string }) =>
@@ -62,6 +62,9 @@ export default function getDashboard(param?: { name?: string;
layer: string; ent
filters,
};
dashboardStore.setWidget(item);
+ if (widget.id === sourceId) {
+ return;
+ }
const targetTabIndex = (widget.id || "").split("-");
const sourceTabindex = (sourceId || "").split("-") || [];
let container: Nullable<Element>;
diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts
index c784acee..46f6cac3 100644
--- a/src/store/modules/dashboard.ts
+++ b/src/store/modules/dashboard.ts
@@ -24,7 +24,6 @@ import { useSelectorStore } from "@/store/modules/selectors";
import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from
"../data";
import type { AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
-import { useI18n } from "vue-i18n";
import { EntityType, MetricModes, WidgetType } from "@/views/dashboard/data";
interface DashboardState {
showConfig: boolean;
diff --git a/src/views/dashboard/related/trace/Filter.vue
b/src/views/dashboard/related/trace/Filter.vue
index b9eeb38f..0ca285a1 100644
--- a/src/views/dashboard/related/trace/Filter.vue
+++ b/src/views/dashboard/related/trace/Filter.vue
@@ -150,7 +150,13 @@ limitations under the License. -->
ElMessage.error(resp.errors);
return;
}
- state.service = getCurrentNode(traceStore.services) ||
traceStore.services[0];
+ if (props.data.filters && props.data.filters.id === "0") {
+ state.service = { value: "", label: "" };
+ return;
+ } else {
+ state.service = getCurrentNode(traceStore.services) ||
traceStore.services[0];
+ }
+
emits("get", state.service.id);
getEndpoints(state.service.id);
@@ -198,7 +204,7 @@ limitations under the License. -->
if (props.data.filters && props.data.filters.id) {
param = {
...param,
- serviceId: props.data.filters.id || undefined,
+ serviceId: props.data.filters.id && props.data.filters.id !== "0" ?
props.data.filters.id : undefined,
endpointId: state.endpoint.id || undefined,
serviceInstanceId: state.instance.id || undefined,
};
diff --git a/src/views/dashboard/related/trace/TraceList.vue
b/src/views/dashboard/related/trace/TraceList.vue
index 6b2ca76a..ba2991a8 100644
--- a/src/views/dashboard/related/trace/TraceList.vue
+++ b/src/views/dashboard/related/trace/TraceList.vue
@@ -227,7 +227,8 @@ limitations under the License. -->
.no-data {
padding-top: 50px;
- width: 100%;
+ width: 280px;
text-align: center;
+ height: 100px;
}
</style>
diff --git a/src/views/dashboard/related/trace/components/D3Graph/Index.vue
b/src/views/dashboard/related/trace/components/D3Graph/Index.vue
index c96c04b7..ff4705e7 100644
--- a/src/views/dashboard/related/trace/components/D3Graph/Index.vue
+++ b/src/views/dashboard/related/trace/components/D3Graph/Index.vue
@@ -139,28 +139,61 @@ limitations under the License. -->
}
segmentHeaders.forEach((span: Span) => {
if (span.refs.length) {
+ let exit = 0;
span.refs.forEach((ref) => {
- const index = props.data.findIndex(
+ const i = props.data.findIndex(
(i: Recordable) => ref.parentSegmentId === i.segmentId &&
ref.parentSpanId === i.spanId,
);
- if (index === -1) {
- // create a known broken node.
- const i = ref.parentSpanId;
- const fixSpanKeyContent = {
+ if (i > -1) {
+ exit = 1;
+ }
+ });
+
+ if (!exit) {
+ const ref = span.refs[0];
+ // create a known broken node.
+ const i = ref.parentSpanId;
+ const fixSpanKeyContent = {
+ traceId: ref.traceId,
+ segmentId: ref.parentSegmentId,
+ spanId: i,
+ parentSpanId: i > -1 ? 0 : -1,
+ };
+ if (!_.find(fixSpans, fixSpanKeyContent)) {
+ fixSpans.push({
+ ...fixSpanKeyContent,
+ refs: [],
+ endpointName: `VNode: ${ref.parentSegmentId}`,
+ serviceCode: "VirtualNode",
+ type: `[Broken] ${ref.type}`,
+ peer: "",
+ component: `VirtualNode: #${i}`,
+ isError: true,
+ isBroken: true,
+ layer: "Broken",
+ tags: [],
+ logs: [],
+ startTime: 0,
+ endTime: 0,
+ });
+ }
+ // if root broken node is not exist, create a root broken node.
+ if (fixSpanKeyContent.parentSpanId > -1) {
+ const fixRootSpanKeyContent = {
traceId: ref.traceId,
segmentId: ref.parentSegmentId,
- spanId: i,
- parentSpanId: i > -1 ? 0 : -1,
+ spanId: 0,
+ parentSpanId: -1,
};
- if (!_.find(fixSpans, fixSpanKeyContent)) {
+ if (!_.find(fixSpans, fixRootSpanKeyContent)) {
fixSpans.push({
- ...fixSpanKeyContent,
+ ...fixRootSpanKeyContent,
refs: [],
endpointName: `VNode: ${ref.parentSegmentId}`,
serviceCode: "VirtualNode",
type: `[Broken] ${ref.type}`,
peer: "",
- component: `VirtualNode: #${i}`,
+ component: `VirtualNode: #0`,
isError: true,
isBroken: true,
layer: "Broken",
@@ -170,44 +203,16 @@ limitations under the License. -->
endTime: 0,
});
}
- // if root broken node is not exist, create a root broken node.
- if (fixSpanKeyContent.parentSpanId > -1) {
- const fixRootSpanKeyContent = {
- traceId: ref.traceId,
- segmentId: ref.parentSegmentId,
- spanId: 0,
- parentSpanId: -1,
- };
- if (!_.find(fixSpans, fixRootSpanKeyContent)) {
- fixSpans.push({
- ...fixRootSpanKeyContent,
- refs: [],
- endpointName: `VNode: ${ref.parentSegmentId}`,
- serviceCode: "VirtualNode",
- type: `[Broken] ${ref.type}`,
- peer: "",
- component: `VirtualNode: #0`,
- isError: true,
- isBroken: true,
- layer: "Broken",
- tags: [],
- logs: [],
- startTime: 0,
- endTime: 0,
- });
- }
- }
}
- });
+ }
}
});
[...fixSpans, ...props.data].forEach((i) => {
i.label = i.endpointName || "no operation name";
i.children = [];
- if (segmentGroup[i.segmentId] === undefined) {
+ if (!segmentGroup[i.segmentId]) {
segmentIdGroup.push(i.segmentId);
- segmentGroup[i.segmentId] = [];
- segmentGroup[i.segmentId].push(i);
+ segmentGroup[i.segmentId] = [i];
} else {
segmentGroup[i.segmentId].push(i);
}
diff --git
a/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue
b/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue
index a9d54711..eebdd416 100644
--- a/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue
+++ b/src/views/dashboard/related/trace/components/D3Graph/SpanDetail.vue
@@ -42,6 +42,12 @@ limitations under the License. -->
<span class="g-sm-4 grey">{{ t("isError") }}:</span>
<span class="g-sm-8 wba">{{ currentSpan.isError }}</span>
</div>
+ <h5 class="mb-10" v-if="diffRefs.length"> {{ t("traceID") }}. </h5>
+ <div class="mb-10 clear item" v-for="item in diffRefs" :key="item.traceId">
+ <span class="g-sm-12 wba cp link" @click="viewRelateTrace(item)">
+ {{ item.traceId }}
+ </span>
+ </div>
<h5 class="mb-10" v-if="currentSpan.tags && currentSpan.tags.length"> {{
t("tags") }}. </h5>
<div class="mb-10 clear item" v-for="i in currentSpan.tags" :key="i.key">
<span class="g-sm-4 grey">{{ i.key }}:</span>
@@ -127,7 +133,7 @@ limitations under the License. -->
</el-dialog>
</template>
<script lang="ts" setup>
- import { ref, computed, onMounted } from "vue";
+ import { ref, computed, onMounted, inject } from "vue";
import { useI18n } from "vue-i18n";
import type { PropType } from "vue";
import dayjs from "dayjs";
@@ -138,14 +144,20 @@ limitations under the License. -->
import { useTraceStore } from "@/store/modules/trace";
import LogTable from "@/views/dashboard/related/log/LogTable/Index.vue";
import type { SpanAttachedEvent } from "@/types/trace";
+ import getDashboard from "@/hooks/useDashboardsSession";
+ import { useDashboardStore } from "@/store/modules/dashboard";
+ import { WidgetType } from "@/views/dashboard/data";
+ import type { LayoutConfig } from "@/types/dashboard";
/*global defineProps, Nullable, Recordable */
const props = defineProps({
currentSpan: { type: Object as PropType<Recordable>, default: () => ({}) },
traceId: { type: String, default: "" },
});
+ const options: Recordable<LayoutConfig> = inject("options") || {};
const { t } = useI18n();
const traceStore = useTraceStore();
+ const dashboardStore = useDashboardStore();
const pageNum = ref<number>(1);
const showRelatedLogs = ref<boolean>(false);
const showEventDetail = ref<boolean>(false);
@@ -154,6 +166,9 @@ limitations under the License. -->
const total = computed(() =>
traceStore.traceList.length === pageSize ? pageSize * pageNum.value + 1 :
pageSize * pageNum.value,
);
+ const diffRefs = computed(() =>
+ props.currentSpan.refs.filter((d: Recordable) => d.traceId !==
props.currentSpan.traceId),
+ );
const tree = ref<any>(null);
const eventGraph = ref<Nullable<HTMLDivElement>>(null);
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") =>
dayjs(date).format(pattern);
@@ -217,6 +232,19 @@ limitations under the License. -->
tree.value.draw();
}
+ function viewRelateTrace(item: Recordable) {
+ const { associationWidget } =
getDashboard(dashboardStore.currentDashboard);
+ associationWidget(
+ (options.id as any) || "",
+ {
+ sourceId: options.id || "",
+ traceId: item.traceId || "",
+ id: "0",
+ },
+ WidgetType.Trace,
+ );
+ }
+
function selectEvent(i: any) {
currentEvent.value = i.data;
showEventDetail.value = true;
@@ -259,7 +287,12 @@ limitations under the License. -->
cursor: pointer;
}
+ .link,
.link-hover:hover {
- color: #448dfe;
+ color: var(--el-color-primary);
+ }
+
+ .link {
+ text-decoration: underline;
}
</style>