mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-12 15:52:57 +00:00
fix: trace
This commit is contained in:
parent
7d24e065e9
commit
1fde7188f2
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import type { LayoutConfig } from "@/types/dashboard";
|
import type { LayoutConfig, DashboardItem } from "@/types/dashboard";
|
||||||
import { ConfigFieldTypes } from "@/views/dashboard/data";
|
import { ConfigFieldTypes } from "@/views/dashboard/data";
|
||||||
|
|
||||||
export default function getDashboard(param?: { name?: string; layer: string; entity: string }, t?: string) {
|
export default function getDashboard(param?: { name?: string; layer: string; entity: string }, t?: string) {
|
||||||
@ -24,7 +24,7 @@ export default function getDashboard(param?: { name?: string; layer: string; ent
|
|||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const opt = param || dashboardStore.currentDashboard;
|
const opt = param || dashboardStore.currentDashboard;
|
||||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
let dashboard;
|
let dashboard: Nullable<DashboardItem>;
|
||||||
if (type === ConfigFieldTypes.NAME) {
|
if (type === ConfigFieldTypes.NAME) {
|
||||||
dashboard = list.find(
|
dashboard = list.find(
|
||||||
(d: { name: string; layer: string; entity: string }) =>
|
(d: { name: string; layer: string; entity: string }) =>
|
||||||
@ -62,6 +62,9 @@ export default function getDashboard(param?: { name?: string; layer: string; ent
|
|||||||
filters,
|
filters,
|
||||||
};
|
};
|
||||||
dashboardStore.setWidget(item);
|
dashboardStore.setWidget(item);
|
||||||
|
if (widget.id === sourceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const targetTabIndex = (widget.id || "").split("-");
|
const targetTabIndex = (widget.id || "").split("-");
|
||||||
const sourceTabindex = (sourceId || "").split("-") || [];
|
const sourceTabindex = (sourceId || "").split("-") || [];
|
||||||
let container: Nullable<Element>;
|
let container: Nullable<Element>;
|
||||||
|
@ -167,7 +167,144 @@ export const traceStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
const data = res.data.data.trace.spans;
|
const resp = {
|
||||||
|
data: {
|
||||||
|
trace: {
|
||||||
|
spans: [
|
||||||
|
{
|
||||||
|
traceId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540001",
|
||||||
|
segmentId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540000",
|
||||||
|
spanId: 0,
|
||||||
|
parentSpanId: -1,
|
||||||
|
refs: [],
|
||||||
|
serviceCode: "rmq5-grpc-A-scenario",
|
||||||
|
serviceInstanceName: "3d4a5d93c2af47838948691e07c502e6@198.18.0.1",
|
||||||
|
startTime: 1705671679055,
|
||||||
|
endTime: 1705671679135,
|
||||||
|
endpointName: "GET:/case/rocketmq-5-grpc-scenario",
|
||||||
|
type: "Entry",
|
||||||
|
peer: "",
|
||||||
|
component: "SpringMVC",
|
||||||
|
isError: false,
|
||||||
|
layer: "Http",
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
key: "url",
|
||||||
|
value: "http://127.0.0.1:8080/rocketmq-5-grpc-scenario/case/rocketmq-5-grpc-scenario",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "http.method",
|
||||||
|
value: "GET",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "http.status_code",
|
||||||
|
value: "200",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
logs: [],
|
||||||
|
attachedEvents: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
traceId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540001",
|
||||||
|
segmentId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540000",
|
||||||
|
spanId: 1,
|
||||||
|
parentSpanId: 0,
|
||||||
|
refs: [],
|
||||||
|
serviceCode: "rmq5-grpc-A-scenario",
|
||||||
|
serviceInstanceName: "3d4a5d93c2af47838948691e07c502e6@198.18.0.1",
|
||||||
|
startTime: 1705671679057,
|
||||||
|
endTime: 1705671679133,
|
||||||
|
endpointName: "RocketMQ/ConsumerAsyncTopicTest/Producer",
|
||||||
|
type: "Exit",
|
||||||
|
peer: "123.56.194.74:8081",
|
||||||
|
component: "rocketMQ-producer",
|
||||||
|
isError: false,
|
||||||
|
layer: "MQ",
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
key: "mq.broker",
|
||||||
|
value: "123.56.194.74:8081",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mq.topic",
|
||||||
|
value: "ConsumerAsyncTopicTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mq.message.keys",
|
||||||
|
value: "e8029111-fa26-4738-a59f-2d4dab0b2ffe",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mq.message.tags",
|
||||||
|
value: "Tag:async:consumer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mq.message.id",
|
||||||
|
value: "01ACDE480011221E0005BC15FF00000003",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
logs: [],
|
||||||
|
attachedEvents: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
traceId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540001",
|
||||||
|
segmentId: "1c116740e8dd41f9af3577a03c969a4b.53.17056716950020000",
|
||||||
|
spanId: 0,
|
||||||
|
parentSpanId: -1,
|
||||||
|
refs: [
|
||||||
|
{
|
||||||
|
traceId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540001",
|
||||||
|
parentSegmentId: "d013fdb11b56417a9997db9d56722ce2.57.17056716790540000",
|
||||||
|
parentSpanId: 1,
|
||||||
|
type: "CROSS_PROCESS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
traceId: "d013fdb11b56417a9997db9d56722ce2.55.17056716721260001",
|
||||||
|
parentSegmentId: "d013fdb11b56417a9997db9d56722ce2.55.17056716721250000",
|
||||||
|
parentSpanId: 1,
|
||||||
|
type: "CROSS_PROCESS",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
serviceCode: "rmq5-grpc-B-scenario",
|
||||||
|
serviceInstanceName: "88429d7fb3434b928dc39f41c0b7c4c6@198.18.0.1",
|
||||||
|
startTime: 1705671695004,
|
||||||
|
endTime: 1705671696483,
|
||||||
|
endpointName: "RocketMQ/ConsumerAsyncTopicTest/Consumer",
|
||||||
|
type: "Entry",
|
||||||
|
peer: "123.56.194.74:8081",
|
||||||
|
component: "rocketMQ-consumer",
|
||||||
|
isError: false,
|
||||||
|
layer: "MQ",
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
key: "mq.topic",
|
||||||
|
value: "ConsumerAsyncTopicTest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mq.broker",
|
||||||
|
value: "123.56.194.74:8081",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "transmission.latency",
|
||||||
|
value: "17345",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "transmission.latency",
|
||||||
|
value: "24263",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "http.status_code",
|
||||||
|
value: "200",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
logs: [],
|
||||||
|
attachedEvents: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// const data = res.data.data.trace.spans;
|
||||||
|
const data = resp.data.trace.spans;
|
||||||
this.setTraceSpans(data || []);
|
this.setTraceSpans(data || []);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
@ -71,6 +71,7 @@ limitations under the License. -->
|
|||||||
emit("select", props.data);
|
emit("select", props.data);
|
||||||
}
|
}
|
||||||
function linkTrace(id: string) {
|
function linkTrace(id: string) {
|
||||||
|
console.log(options);
|
||||||
const { associationWidget } = getDashboard(dashboardStore.currentDashboard);
|
const { associationWidget } = getDashboard(dashboardStore.currentDashboard);
|
||||||
associationWidget(
|
associationWidget(
|
||||||
(options.id as any) || "",
|
(options.id as any) || "",
|
||||||
|
@ -227,7 +227,8 @@ limitations under the License. -->
|
|||||||
|
|
||||||
.no-data {
|
.no-data {
|
||||||
padding-top: 50px;
|
padding-top: 50px;
|
||||||
width: 100%;
|
width: 280px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
height: 100px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -139,28 +139,61 @@ limitations under the License. -->
|
|||||||
}
|
}
|
||||||
segmentHeaders.forEach((span: Span) => {
|
segmentHeaders.forEach((span: Span) => {
|
||||||
if (span.refs.length) {
|
if (span.refs.length) {
|
||||||
|
let exit = 0;
|
||||||
span.refs.forEach((ref) => {
|
span.refs.forEach((ref) => {
|
||||||
const index = props.data.findIndex(
|
const i = props.data.findIndex(
|
||||||
(i: Recordable) => ref.parentSegmentId === i.segmentId && ref.parentSpanId === i.spanId,
|
(i: Recordable) => ref.parentSegmentId === i.segmentId && ref.parentSpanId === i.spanId,
|
||||||
);
|
);
|
||||||
if (index === -1) {
|
if (i > -1) {
|
||||||
// create a known broken node.
|
exit = 1;
|
||||||
const i = ref.parentSpanId;
|
}
|
||||||
const fixSpanKeyContent = {
|
});
|
||||||
|
|
||||||
|
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,
|
traceId: ref.traceId,
|
||||||
segmentId: ref.parentSegmentId,
|
segmentId: ref.parentSegmentId,
|
||||||
spanId: i,
|
spanId: 0,
|
||||||
parentSpanId: i > -1 ? 0 : -1,
|
parentSpanId: -1,
|
||||||
};
|
};
|
||||||
if (!_.find(fixSpans, fixSpanKeyContent)) {
|
if (!_.find(fixSpans, fixRootSpanKeyContent)) {
|
||||||
fixSpans.push({
|
fixSpans.push({
|
||||||
...fixSpanKeyContent,
|
...fixRootSpanKeyContent,
|
||||||
refs: [],
|
refs: [],
|
||||||
endpointName: `VNode: ${ref.parentSegmentId}`,
|
endpointName: `VNode: ${ref.parentSegmentId}`,
|
||||||
serviceCode: "VirtualNode",
|
serviceCode: "VirtualNode",
|
||||||
type: `[Broken] ${ref.type}`,
|
type: `[Broken] ${ref.type}`,
|
||||||
peer: "",
|
peer: "",
|
||||||
component: `VirtualNode: #${i}`,
|
component: `VirtualNode: #0`,
|
||||||
isError: true,
|
isError: true,
|
||||||
isBroken: true,
|
isBroken: true,
|
||||||
layer: "Broken",
|
layer: "Broken",
|
||||||
@ -170,44 +203,27 @@ limitations under the License. -->
|
|||||||
endTime: 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: 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) => {
|
[...fixSpans, ...props.data].forEach((i) => {
|
||||||
|
if (i.refs.length) {
|
||||||
|
const item = i.refs.find((d) => d.traceId === i.traceId);
|
||||||
|
if (item) {
|
||||||
|
i = {
|
||||||
|
...i,
|
||||||
|
...item,
|
||||||
|
segmentId: item.parentSegmentId,
|
||||||
|
spanId: -2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
i.label = i.endpointName || "no operation name";
|
i.label = i.endpointName || "no operation name";
|
||||||
i.children = [];
|
i.children = [];
|
||||||
if (segmentGroup[i.segmentId] === undefined) {
|
if (!segmentGroup[i.segmentId]) {
|
||||||
segmentIdGroup.push(i.segmentId);
|
segmentIdGroup.push(i.segmentId);
|
||||||
segmentGroup[i.segmentId] = [];
|
segmentGroup[i.segmentId] = [i];
|
||||||
segmentGroup[i.segmentId].push(i);
|
|
||||||
} else {
|
} else {
|
||||||
segmentGroup[i.segmentId].push(i);
|
segmentGroup[i.segmentId].push(i);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,13 @@ limitations under the License. -->
|
|||||||
<span class="g-sm-4 grey">{{ t("isError") }}:</span>
|
<span class="g-sm-4 grey">{{ t("isError") }}:</span>
|
||||||
<span class="g-sm-8 wba">{{ currentSpan.isError }}</span>
|
<span class="g-sm-8 wba">{{ currentSpan.isError }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<h5 class="mb-10" v-if="diffRefs.length"> {{ t("traceID") }}. </h5>
|
||||||
|
<div class="mb-10 clear item" v-for="(item, index) in diffRefs" :key="item.traceId">
|
||||||
|
<span class="g-sm-4 grey">No.{{ index + 1 }}</span>
|
||||||
|
<span class="g-sm-8 wba link cp" @click="viewRelateTrace(item)">
|
||||||
|
{{ item.traceId }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<h5 class="mb-10" v-if="currentSpan.tags && currentSpan.tags.length"> {{ t("tags") }}. </h5>
|
<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">
|
<div class="mb-10 clear item" v-for="i in currentSpan.tags" :key="i.key">
|
||||||
<span class="g-sm-4 grey">{{ i.key }}:</span>
|
<span class="g-sm-4 grey">{{ i.key }}:</span>
|
||||||
@ -127,7 +134,7 @@ limitations under the License. -->
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted, inject } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@ -138,14 +145,20 @@ limitations under the License. -->
|
|||||||
import { useTraceStore } from "@/store/modules/trace";
|
import { useTraceStore } from "@/store/modules/trace";
|
||||||
import LogTable from "@/views/dashboard/related/log/LogTable/Index.vue";
|
import LogTable from "@/views/dashboard/related/log/LogTable/Index.vue";
|
||||||
import type { SpanAttachedEvent } from "@/types/trace";
|
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 */
|
/*global defineProps, Nullable, Recordable */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentSpan: { type: Object as PropType<Recordable>, default: () => ({}) },
|
currentSpan: { type: Object as PropType<Recordable>, default: () => ({}) },
|
||||||
traceId: { type: String, default: "" },
|
traceId: { type: String, default: "" },
|
||||||
});
|
});
|
||||||
|
const options: Recordable<LayoutConfig> = inject("options") || {};
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const traceStore = useTraceStore();
|
const traceStore = useTraceStore();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
const pageNum = ref<number>(1);
|
const pageNum = ref<number>(1);
|
||||||
const showRelatedLogs = ref<boolean>(false);
|
const showRelatedLogs = ref<boolean>(false);
|
||||||
const showEventDetail = ref<boolean>(false);
|
const showEventDetail = ref<boolean>(false);
|
||||||
@ -154,6 +167,9 @@ limitations under the License. -->
|
|||||||
const total = computed(() =>
|
const total = computed(() =>
|
||||||
traceStore.traceList.length === pageSize ? pageSize * pageNum.value + 1 : pageSize * pageNum.value,
|
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 tree = ref<any>(null);
|
||||||
const eventGraph = ref<Nullable<HTMLDivElement>>(null);
|
const eventGraph = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") => dayjs(date).format(pattern);
|
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss:SSS") => dayjs(date).format(pattern);
|
||||||
@ -217,6 +233,18 @@ limitations under the License. -->
|
|||||||
tree.value.draw();
|
tree.value.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function viewRelateTrace(item: Recordable) {
|
||||||
|
const { associationWidget } = getDashboard(dashboardStore.currentDashboard);
|
||||||
|
associationWidget(
|
||||||
|
(options.id as any) || "",
|
||||||
|
{
|
||||||
|
sourceId: options.id || "",
|
||||||
|
traceId: item.traceId,
|
||||||
|
},
|
||||||
|
WidgetType.Trace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function selectEvent(i: any) {
|
function selectEvent(i: any) {
|
||||||
currentEvent.value = i.data;
|
currentEvent.value = i.data;
|
||||||
showEventDetail.value = true;
|
showEventDetail.value = true;
|
||||||
@ -259,7 +287,13 @@ limitations under the License. -->
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link,
|
||||||
.link-hover:hover {
|
.link-hover:hover {
|
||||||
color: #448dfe;
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user