feat: update trace list

This commit is contained in:
Fine 2023-11-13 11:25:36 +08:00
parent b56a503c66
commit 6b38ff6b2f
9 changed files with 64 additions and 34 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 B

After

Width:  |  Height:  |  Size: 259 B

View File

@ -26,3 +26,8 @@ export const Languages = [
{ label: "Chinese", value: "zh" }, { label: "Chinese", value: "zh" },
{ label: "Spanish", value: "es" }, { label: "Spanish", value: "es" },
]; ];
export enum Themes {
Dark = "dark",
Light = "light",
}

View File

@ -31,6 +31,7 @@ import { useEventListener } from "./useEventListener";
import { useBreakpoint } from "./useBreakpoint"; import { useBreakpoint } from "./useBreakpoint";
import echarts from "@/utils/echarts"; import echarts from "@/utils/echarts";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
export type ECOption = echarts.ComposeOption< export type ECOption = echarts.ComposeOption<
| BarSeriesOption | BarSeriesOption
@ -47,7 +48,7 @@ export type ECOption = echarts.ComposeOption<
export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" | "default" = "default"): Indexable { export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" | "default" = "default"): Indexable {
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const getDarkMode = computed(() => { const getDarkMode = computed(() => {
return appStore.theme === "default" ? "light" : theme; return appStore.theme === "default" ? Themes.Light : theme;
}); });
let chartInstance: Nullable<echarts.ECharts> = null; let chartInstance: Nullable<echarts.ECharts> = null;
let resizeFn: Fn = resize; let resizeFn: Fn = resize;
@ -57,7 +58,7 @@ export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" |
resizeFn = useDebounceFn(resize, 200); resizeFn = useDebounceFn(resize, 200);
const getOptions = computed(() => { const getOptions = computed(() => {
if (getDarkMode.value !== "dark") { if (getDarkMode.value !== Themes.Dark) {
return cacheOptions.value as ECOption; return cacheOptions.value as ECOption;
} }
return { return {

View File

@ -78,6 +78,7 @@ limitations under the License. -->
import type { DashboardItem } from "@/types/dashboard"; import type { DashboardItem } from "@/types/dashboard";
import router from "@/router"; import router from "@/router";
import { ArrowRight, Moon, Sunny } from "@element-plus/icons-vue"; import { ArrowRight, Moon, Sunny } from "@element-plus/icons-vue";
import { Themes } from "@/constants/data";
/*global Indexable */ /*global Indexable */
const { t, te } = useI18n(); const { t, te } = useI18n();
@ -98,13 +99,13 @@ limitations under the License. -->
const root = document.documentElement; const root = document.documentElement;
if (theme.value) { if (theme.value) {
root.classList.add("dark"); root.classList.add(Themes.Dark);
root.classList.remove("light"); root.classList.remove(Themes.Light);
appStore.setTheme("dark"); appStore.setTheme(Themes.Dark);
} else { } else {
root.classList.add("light"); root.classList.add(Themes.Light);
root.classList.remove("dark"); root.classList.remove(Themes.Dark);
appStore.setTheme("light"); appStore.setTheme(Themes.Light);
} }
} }

View File

@ -23,6 +23,7 @@ import type { AxiosResponse } from "axios";
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat"; import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
import { TimeType } from "@/constants/data"; import { TimeType } from "@/constants/data";
import type { MenuOptions, SubItem } from "@/types/app"; import type { MenuOptions, SubItem } from "@/types/app";
import { Themes } from "@/constants/data";
/*global Nullable*/ /*global Nullable*/
interface AppState { interface AppState {
durationRow: Recordable; durationRow: Recordable;
@ -57,7 +58,7 @@ export const appStore = defineStore({
isMobile: false, isMobile: false,
reloadTimer: null, reloadTimer: null,
allMenus: [], allMenus: [],
theme: "dark", theme: Themes.Dark,
}), }),
getters: { getters: {
duration(): Duration { duration(): Duration {

View File

@ -25,6 +25,7 @@ limitations under the License. -->
import useLegendProcess from "@/hooks/useLegendProcessor"; import useLegendProcess from "@/hooks/useLegendProcessor";
import Legend from "./components/Legend.vue"; import Legend from "./components/Legend.vue";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
/*global defineProps, defineEmits */ /*global defineProps, defineEmits */
const emits = defineEmits(["click"]); const emits = defineEmits(["click"]);
@ -93,11 +94,11 @@ limitations under the License. -->
top: 0, top: 0,
left: 0, left: 0,
itemWidth: 12, itemWidth: 12,
backgroundColor: appStore.theme === "dark" ? "#333" : "#fff", backgroundColor: appStore.theme === Themes.Dark ? "#333" : "#fff",
borderColor: appStore.theme === "dark" ? "#333" : "#fff", borderColor: appStore.theme === Themes.Dark ? "#333" : "#fff",
textStyle: { textStyle: {
fontSize: 12, fontSize: 12,
color: appStore.theme === "dark" ? "#eee" : "#333", color: appStore.theme === Themes.Dark ? "#eee" : "#333",
}, },
}, },
grid: { grid: {

View File

@ -32,6 +32,7 @@ limitations under the License. -->
import useLegendProcess from "@/hooks/useLegendProcessor"; import useLegendProcess from "@/hooks/useLegendProcessor";
import { isDef } from "@/utils/is"; import { isDef } from "@/utils/is";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
/*global defineProps, defineEmits */ /*global defineProps, defineEmits */
const emits = defineEmits(["click"]); const emits = defineEmits(["click"]);
@ -94,11 +95,11 @@ limitations under the License. -->
const color: string[] = chartColors(keys); const color: string[] = chartColors(keys);
const tooltip = { const tooltip = {
trigger: "axis", trigger: "axis",
backgroundColor: appStore.theme === "dark" ? "#333" : "#fff", backgroundColor: appStore.theme === Themes.Dark ? "#333" : "#fff",
borderColor: appStore.theme === "dark" ? "#333" : "#fff", borderColor: appStore.theme === Themes.Dark ? "#333" : "#fff",
textStyle: { textStyle: {
fontSize: 12, fontSize: 12,
color: appStore.theme === "dark" ? "#eee" : "#333", color: appStore.theme === Themes.Dark ? "#eee" : "#333",
}, },
enterable: true, enterable: true,
confine: true, confine: true,
@ -111,11 +112,11 @@ limitations under the License. -->
confine: true, confine: true,
extraCssText: `height: 20px; padding:0 2px;`, extraCssText: `height: 20px; padding:0 2px;`,
trigger: "axis", trigger: "axis",
backgroundColor: appStore.theme === "dark" ? "#666" : "#eee", backgroundColor: appStore.theme === Themes.Dark ? "#666" : "#eee",
borderColor: appStore.theme === "dark" ? "#666" : "#eee", borderColor: appStore.theme === Themes.Dark ? "#666" : "#eee",
textStyle: { textStyle: {
fontSize: 12, fontSize: 12,
color: appStore.theme === "dark" ? "#eee" : "#333", color: appStore.theme === Themes.Dark ? "#eee" : "#333",
}, },
}; };
@ -130,7 +131,7 @@ limitations under the License. -->
left: 0, left: 0,
itemWidth: 12, itemWidth: 12,
textStyle: { textStyle: {
color: appStore.theme === "dark" ? "#fff" : "#333", color: appStore.theme === Themes.Dark ? "#fff" : "#333",
}, },
}, },
grid: { grid: {

View File

@ -28,6 +28,7 @@ limitations under the License. -->
import TreeGraph from "../../utils/d3-trace-tree"; import TreeGraph from "../../utils/d3-trace-tree";
import type { Span, Ref } from "@/types/trace"; import type { Span, Ref } from "@/types/trace";
import SpanDetail from "./SpanDetail.vue"; import SpanDetail from "./SpanDetail.vue";
import { useAppStoreWithOut } from "@/store/modules/app";
/* global defineProps, Nullable, defineExpose,Recordable*/ /* global defineProps, Nullable, defineExpose,Recordable*/
const props = defineProps({ const props = defineProps({
@ -35,6 +36,7 @@ limitations under the License. -->
traceId: { type: String, default: "" }, traceId: { type: String, default: "" },
type: { type: String, default: "List" }, type: { type: String, default: "List" },
}); });
const appStore = useAppStoreWithOut();
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const showDetail = ref<boolean>(false); const showDetail = ref<boolean>(false);
const fixSpansSize = ref<number>(0); const fixSpansSize = ref<number>(0);
@ -289,6 +291,17 @@ limitations under the License. -->
}); });
}, },
); );
watch(
() => appStore.theme,
() => {
tree.value.init({ label: "TRACE_ROOT", children: segmentId.value }, props.data, fixSpansSize.value);
tree.value.draw(() => {
setTimeout(() => {
loading.value = false;
}, 200);
});
},
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.d3-graph { .d3-graph {
@ -301,12 +314,12 @@ limitations under the License. -->
} }
.trace-node-container { .trace-node-container {
fill: rgba(0, 0, 0, 0); fill: rgb(0 0 0 / 0%);
stroke-width: 5px; stroke-width: 5px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
fill: rgba(0, 0, 0, 0.05); fill: rgb(0 0 0 / 5%);
} }
} }

View File

@ -20,6 +20,8 @@ import d3tip from "d3-tip";
import type { Trace } from "@/types/trace"; import type { Trace } from "@/types/trace";
import dayjs from "dayjs"; import dayjs from "dayjs";
import icons from "@/assets/img/icons"; import icons from "@/assets/img/icons";
import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
export default class ListGraph { export default class ListGraph {
private barHeight = 48; private barHeight = 48;
@ -127,6 +129,7 @@ export default class ListGraph {
} }
update(source: Recordable, callback: Function) { update(source: Recordable, callback: Function) {
const t = this; const t = this;
const appStore = useAppStoreWithOut();
const nodes = this.root.descendants(); const nodes = this.root.descendants();
let index = -1; let index = -1;
this.root.eachBefore((n: Recordable) => { this.root.eachBefore((n: Recordable) => {
@ -166,7 +169,7 @@ export default class ListGraph {
.attr("width", 16) .attr("width", 16)
.attr("height", 16) .attr("height", 16)
.attr("x", 6) .attr("x", 6)
.attr("y", -10) .attr("y", -8)
.attr("xlink:href", (d: any) => .attr("xlink:href", (d: any) =>
d.data.type === "Entry" ? icons.ENTRY : d.data.type === "Exit" ? icons.EXIT : "", d.data.type === "Entry" ? icons.ENTRY : d.data.type === "Exit" ? icons.EXIT : "",
) )
@ -186,7 +189,7 @@ export default class ListGraph {
.attr("width", 16) .attr("width", 16)
.attr("height", 16) .attr("height", 16)
.attr("x", 6) .attr("x", 6)
.attr("y", -10) .attr("y", -8)
.attr("xlink:href", (d: any) => { .attr("xlink:href", (d: any) => {
const key = (d.data.refs || []).findIndex((d: { type: string }) => d.type === "CROSS_THREAD"); const key = (d.data.refs || []).findIndex((d: { type: string }) => d.type === "CROSS_THREAD");
return key > -1 ? icons.STREAM : ""; return key > -1 ? icons.STREAM : "";
@ -214,14 +217,14 @@ export default class ListGraph {
.append("text") .append("text")
.attr("x", 13) .attr("x", 13)
.attr("y", 5) .attr("y", 5)
.attr("fill", "#E54C17") .attr("fill", appStore.theme === Themes.Dark ? "#666" : "#E54C17")
.html((d: Recordable) => (d.data.isError ? "◉" : "")); .html((d: Recordable) => (d.data.isError ? "◉" : ""));
nodeEnter nodeEnter
.append("text") .append("text")
.attr("class", "node-text") .attr("class", "node-text")
.attr("x", 35) .attr("x", 35)
.attr("y", -6) .attr("y", -6)
.attr("fill", "#333") .attr("fill", appStore.theme === Themes.Dark ? "#eee" : "#333")
.html((d: Recordable) => { .html((d: Recordable) => {
if (d.data.label === "TRACE_ROOT") { if (d.data.label === "TRACE_ROOT") {
return ""; return "";
@ -242,7 +245,7 @@ export default class ListGraph {
}) })
.attr("cy", -5) .attr("cy", -5)
.attr("fill", "none") .attr("fill", "none")
.attr("stroke", "#e66") .attr("stroke", appStore.theme === Themes.Dark ? "#666" : "#e66")
.style("opacity", (d: Recordable) => { .style("opacity", (d: Recordable) => {
const events = d.data.attachedEvents; const events = d.data.attachedEvents;
if (events && events.length) { if (events && events.length) {
@ -255,7 +258,7 @@ export default class ListGraph {
.append("text") .append("text")
.attr("x", 267) .attr("x", 267)
.attr("y", -1) .attr("y", -1)
.attr("fill", "#e66") .attr("fill", appStore.theme === Themes.Dark ? "#666" : "#e66")
.style("font-size", "10px") .style("font-size", "10px")
.text((d: Recordable) => { .text((d: Recordable) => {
const events = d.data.attachedEvents; const events = d.data.attachedEvents;
@ -270,7 +273,7 @@ export default class ListGraph {
.attr("class", "node-text") .attr("class", "node-text")
.attr("x", 35) .attr("x", 35)
.attr("y", 12) .attr("y", 12)
.attr("fill", "#ccc") .attr("fill", appStore.theme === Themes.Dark ? "#777" : "#ccc")
.style("font-size", "11px") .style("font-size", "11px")
.text( .text(
(d: Recordable) => (d: Recordable) =>
@ -305,11 +308,15 @@ export default class ListGraph {
.style("opacity", 1); .style("opacity", 1);
nodeEnter nodeEnter
.append("circle") .append("circle")
.attr("r", 3) .attr("r", appStore.theme === Themes.Dark ? 4 : 3)
.style("cursor", "pointer") .style("cursor", "pointer")
.attr("stroke-width", 2.5) .attr("stroke-width", appStore.theme === Themes.Dark ? 3 : 2.5)
.attr("fill", (d: Recordable) => .attr("fill", (d: Recordable) =>
d._children ? `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}` : "rbga(0,0,0,0)", d._children
? `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`
: appStore.theme === Themes.Dark
? "#eee"
: "rbga(0,0,0,0)",
) )
.style("stroke", (d: Recordable) => .style("stroke", (d: Recordable) =>
d.data.label === "TRACE_ROOT" ? "" : `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`, d.data.label === "TRACE_ROOT" ? "" : `${this.sequentialScale(this.list.indexOf(d.data.serviceCode))}`,
@ -320,7 +327,7 @@ export default class ListGraph {
node node
.transition() .transition()
.duration(400) .duration(400)
.attr("transform", (d: Recordable) => `translate(${d.y + 5},${d.x})`) .attr("transform", (d: Recordable) => `translate(${d.y + 3},${d.x})`)
.style("opacity", 1) .style("opacity", 1)
.select("circle") .select("circle")
.attr("fill", (d: Recordable) => .attr("fill", (d: Recordable) =>
@ -343,8 +350,8 @@ export default class ListGraph {
.enter() .enter()
.insert("path", "g") .insert("path", "g")
.attr("class", "trace-link") .attr("class", "trace-link")
.attr("fill", "rgba(0,0,0,0)") .attr("fill", appStore.theme === Themes.Dark ? "rgba(244,244,244,0)" : "rgba(0,0,0,0)")
.attr("stroke", "rgba(0, 0, 0, 0.1)") .attr("stroke", appStore.theme === Themes.Dark ? "rgba(244,244,244,0.4)" : "rgba(0, 0, 0, 0.1)")
.attr("stroke-width", 2) .attr("stroke-width", 2)
.attr("transform", `translate(5, 0)`) .attr("transform", `translate(5, 0)`)
.attr("d", () => { .attr("d", () => {