feat: Implement Trace page (#500)

This commit is contained in:
Fine0830
2025-09-29 17:36:31 +08:00
committed by GitHub
parent dd90ab5ea7
commit a834cdb2eb
19 changed files with 386 additions and 79 deletions

View File

@@ -0,0 +1,42 @@
<!-- 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. -->
<template>
<div style="padding: 20px">
<TraceContent v-if="traceStore.currentTrace" :trace="traceStore.currentTrace" />
<div style="text-align: center; padding: 20px" v-if="!traceStore.loading && !traceStore.currentTrace"
>No trace found</div
>
</div>
</template>
<script lang="ts" setup>
import { useRoute } from "vue-router";
import { computed, onMounted, provide } from "vue";
import { useTraceStore } from "@/store/modules/trace";
import TraceContent from "@/views/dashboard/related/trace/components/TraceQuery/TraceContent.vue";
const route = useRoute();
const traceStore = useTraceStore();
const traceId = computed(() => route.params.traceId as string);
provide("options", {});
onMounted(() => {
if (traceId.value) {
traceStore.setTraceCondition({
traceId: traceId.value,
});
traceStore.fetchV2Traces();
}
});
</script>

View File

@@ -100,7 +100,7 @@ limitations under the License. -->
</el-tooltip>
</div>
<div class="start-time">
{{ dateFormat(data.startTime) }}
{{ data.startTime ? dateFormat(data.startTime) : "" }}
</div>
<div class="exec-ms">
{{ data.endTime - data.startTime ? data.endTime - data.startTime : "0" }}

View File

@@ -16,7 +16,7 @@ limitations under the License. -->
<div class="timeline-tool flex-h">
<div class="flex-h trace-type item">
<el-radio-group v-model="spansGraphType" size="small">
<el-radio-button v-for="option in GraphTypeOptions" :key="option.value" :value="option.value">
<el-radio-button v-for="option in reorderedOptions" :key="option.value" :value="option.value">
<Icon :iconName="option.icon" />
{{ t(option.label) }}
</el-radio-button>
@@ -39,7 +39,13 @@ limitations under the License. -->
(e: "updateSpansGraphType", value: string): void;
}>();
const { t } = useI18n();
const spansGraphType = ref<string>(GraphTypeOptions[2].value);
const reorderedOptions = [
GraphTypeOptions[2], // Table
GraphTypeOptions[0], // List
GraphTypeOptions[1], // Tree
GraphTypeOptions[3], // Statistics
];
const spansGraphType = ref<string>(reorderedOptions[0].value);
function onToggleMinTimeline() {
emit("toggleMinTimeline");

View File

@@ -17,7 +17,13 @@ limitations under the License. -->
<div class="trace-info">
<div class="flex-h" style="justify-content: space-between">
<h3>{{ trace.label }}</h3>
<div>
<div class="flex-h">
<div class="mr-5 cp">
<el-button size="small" @click="viewTrace">
{{ t("shareTrace") }}
<Icon class="ml-5" size="small" iconName="link" />
</el-button>
</div>
<el-dropdown @command="handleDownload" trigger="click">
<el-button size="small">
{{ t("download") }}
@@ -44,9 +50,12 @@ limitations under the License. -->
<span class="grey mr-5">{{ t("totalSpans") }}</span>
<span class="value">{{ trace.spans?.length || 0 }}</span>
</div>
<div>
<div class="trace-id-container flex-h" style="align-items: center">
<span class="grey mr-5">{{ t("traceID") }}</span>
<span class="value">{{ trace.traceId }}</span>
<span class="value ml-5 cp" @click="handleCopyTraceId">
<Icon size="middle" iconName="copy" />
</span>
</div>
</div>
</div>
@@ -91,6 +100,8 @@ limitations under the License. -->
import graphs from "../VisGraph/index";
import { WidgetType } from "@/views/dashboard/data";
import { GraphTypeOptions } from "../VisGraph/constant";
import copy from "@/utils/copy";
import router from "@/router";
interface Props {
trace: Trace;
@@ -148,6 +159,17 @@ limitations under the License. -->
ElMessage.error("Failed to download file");
}
}
function viewTrace() {
if (!traceStore.currentTrace?.traceId) return;
const traceUrl = `/traces/${traceStore.currentTrace.traceId}`;
const routeUrl = router.resolve({ path: traceUrl });
window.open(routeUrl.href, "_blank");
}
function handleCopyTraceId() {
if (!traceStore.currentTrace?.traceId) return;
copy(traceStore.currentTrace?.traceId);
}
</script>
<style lang="scss" scoped>