refactor(web ui):refactor echarts component

This commit is contained in:
辗转反侧的咸鱼 2022-11-17 00:29:12 +08:00 committed by hengyunabc
parent be27d0e51d
commit f74167bfdb
10 changed files with 518 additions and 605 deletions

View File

@ -0,0 +1,20 @@
<script setup lang="ts">
import Chart from "./Base.vue"
import * as echarts from 'echarts/core';
import { DatasetComponentOption, DataZoomComponent, DataZoomComponentOption, GridComponent, GridComponentOption, LegendComponent, LegendComponentOption, TitleComponentOption, ToolboxComponentOption, TooltipComponentOption } from 'echarts/components';
import { BarChart, BarSeriesOption, } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { BarChartOption } from "@/echart";
let useList = ([
// LegendComponent,
BarChart,
LabelLayout,
GridComponent,
DataZoomComponent
]);
const props = defineProps<{ option: BarChartOption }>()
</script>
<template>
<Chart :use-list="useList" :option="props.option"></Chart>
</template>

View File

@ -0,0 +1,73 @@
<script setup lang="ts">
import * as echarts from 'echarts/core';
import { SVGRenderer } from 'echarts/renderers';
import { TitleComponent, TitleComponentOption, TooltipComponent, TooltipComponentOption, ToolboxComponent, LegendComponent} from 'echarts/components'
import { onBeforeUnmount, onMounted, Ref, ref, watch } from 'vue';
// option && myChart.setOption(option);
type GetTuple<T extends unknown> = T extends T
? T extends [...infer E]
? T
: never
: never
type UseType = GetTuple<Parameters<typeof echarts.use>[0]>
// echarts.ECharts
type OptionType = Parameters<echarts.ECharts["setOption"]>[0]
const props = defineProps<{
useList: UseType,
option: OptionType,
}>()
// type EChartsOption = echarts.ComposeOption<TooltipComponentOption | TitleComponentOption | DatasetComponentOption | PieSeriesOption>;
const container = ref(null)
let myChart: echarts.ECharts
echarts.use([
...props.useList,
SVGRenderer,
TitleComponent,
TooltipComponent,
ToolboxComponent,
LegendComponent
])
// 使resize
const resizeDom = () => {
myChart && myChart.resize()
}
onMounted(() => {
// container.value.el.id = chartId.toString()
let dom = container.value
myChart = echarts.init(dom as unknown as HTMLElement)
myChart && myChart.setOption<OptionType>({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
...props.option
})
window.addEventListener("resize", resizeDom)
})
watch(props.option, (newData: any) => {
myChart && newData && myChart.setOption(newData, true)
console.log(newData)
},
{
immediate: true,
deep: true
})
onBeforeUnmount(() => {
myChart && myChart.dispose()
window.removeEventListener("resize", resizeDom)
})
</script>
<template>
<div ref="container" class="w-full h-full"></div>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,20 @@
<script setup lang="ts">
// import Chart from "./Chart.vue"
import * as echarts from 'echarts/core';
import { DatasetComponent, DatasetComponentOption, LegendComponent, TitleComponentOption, TooltipComponentOption } from 'echarts/components';
import { PieChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { CircleChartOption } from "@/echart";
import Base from './Base.vue';
let useList = ([
PieChart,
LabelLayout,
DatasetComponent
]);
// type CircleChartsOption = echarts.ComposeOption<TooltipComponentOption | TitleComponentOption | DatasetComponentOption | PieSeriesOption>;
const props = defineProps<{ option: CircleChartOption }>()
</script>
<template>
<Base :use-list="useList" :option="props.option" />
</template>

View File

@ -0,0 +1,19 @@
<script setup lang="ts">
import Chart from "./Base.vue"
import * as echarts from 'echarts/core';
import { DataZoomComponent, GridComponent } from 'echarts/components';
import { LineChart } from 'echarts/charts';
import { LabelLayout } from 'echarts/features';
import { LineChartOption } from "@/echart";
let useList = ([
LineChart,
LabelLayout,
GridComponent,
DataZoomComponent
]);
const props = defineProps<{ option: LineChartOption }>()
</script>
<template>
<Chart :use-list="useList" :option="props.option"></Chart>
</template>

View File

@ -0,0 +1,47 @@
import * as echarts from "echarts";
import {
DatasetComponentOption,
DataZoomComponentOption,
GridComponentOption,
LegendComponentOption,
TitleComponentOption,
ToolboxComponentOption,
TooltipComponentOption,
} from "echarts/components";
import {
BarSeriesOption,
LineSeriesOption,
PieSeriesOption,
} from "echarts/charts";
type LineChartOption = echarts.ComposeOption<
| TooltipComponentOption
| TitleComponentOption
| DatasetComponentOption
| LineSeriesOption
| TitleComponentOption
| ToolboxComponentOption
| TooltipComponentOption
| GridComponentOption
| LegendComponentOption
| DataZoomComponentOption
| LineSeriesOption
>;
type BarChartOption = echarts.ComposeOption<
| TooltipComponentOption
| TitleComponentOption
| DatasetComponentOption
| BarSeriesOption
| DataZoomComponentOption
| LegendComponentOption
| GridComponentOption
| ToolboxComponentOption
>;
type CircleChartOption = echarts.ComposeOption<
| TooltipComponentOption
| TitleComponentOption
| DatasetComponentOption
| PieSeriesOption
| LegendComponentOption
>;

View File

@ -3,51 +3,17 @@ import machine from '@/machines/consoleMachine';
import { fetchStore } from '@/stores/fetch';
import { publicStore } from '@/stores/public';
import { useInterpret, useMachine } from '@xstate/vue';
import { onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import * as echarts from 'echarts/core';
import {
TooltipComponent,
TooltipComponentOption,
LegendComponent,
LegendComponentOption,
DatasetComponentOption,
GridComponentOption,
ToolboxComponentOption,
GridComponent,
ToolboxComponent
} from 'echarts/components';
import {
BarChart,
BarSeriesOption,
LineChart,
LineSeriesOption,
PieChart,
PieSeriesOption
} from 'echarts/charts';
import {
LabelLayout, UniversalTransition
} from 'echarts/features';
import {
SVGRenderer
} from 'echarts/renderers';
import { dispose, ECharts } from 'echarts/core';
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
import permachine from '@/machines/perRequestMachine';
type EChartsOption = echarts.ComposeOption<
DatasetComponentOption | PieSeriesOption
>
type GcEChartsOption = echarts.ComposeOption<
ToolboxComponentOption | TooltipComponentOption | GridComponentOption | LegendComponentOption | BarSeriesOption | LineSeriesOption
>
import Bar from '@/components/charts/Bar.vue';
import { BarChartOption, CircleChartOption } from '@/echart';
import Circle from '@/components/charts/Circle.vue';
const fetchS = fetchStore()
const { getCommonResEffect } = publicStore()
const dashboadM = useInterpret(permachine)
const dashboadResM = useMachine(machine)
const loop = fetchS.pullResultsLoop(dashboadResM)
const toMb = (b: number) => Math.floor(b / 1024 / 1024)
const gcInfos = reactive(new Map<string, string[]>())
const memoryInfo = reactive(new Map<string, string[]>())
const threads = reactive(new Map<string, string[]>())
const runtimeInfo = reactive(new Map<keyof RuntimeInfo, string>())
const pri = ref(3)
const publiC = publicStore()
@ -66,70 +32,235 @@ const keyList: (keyof ThreadStats)[] = [
]
let dashboardId = -1
let heapChart: ECharts
let nonheapChart: ECharts
let bufferPoolChart: ECharts
let gcChart: ECharts
const clearChart = (...charts: ECharts[]) => {
charts.forEach(chart => {
if (chart !== null && chart !== undefined) chart.dispose()
})
}
const colors = ['#5470C6', '#91CC75'];
const gcChartContext = reactive<{ xData: string[], collectionCount: number[], collectionTime: number[] }>({
xData: [],
collectionCount: [],
collectionTime: []
})
const gcoption = reactive<BarChartOption>({
color: colors,
title:{
text: "GC",
},
grid: {
right: '20%'
},
legend: {
data: ['collectionCount', 'collectionTime']
},
xAxis: [{
type: 'category',
axisTick: {
alignWithLabel: true
},
data: gcChartContext.xData
}],
yAxis: [
{
type: 'value',
name: 'collectionCount',
position: 'left',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[0]
}
},
axisLabel: {
formatter: '{value}'
}
},
{
type: 'value',
name: 'collectionTime',
position: 'right',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[1]
}
},
axisLabel: {
formatter: '{value} ms'
}
},
],
series: [
{
name: 'collectionCount',
type: 'bar',
data: gcChartContext.collectionCount
},
{
name: 'collectionTime',
type: 'bar',
yAxisIndex: 1,
data: gcChartContext.collectionTime
},
]
});
const bufferPoolContext = reactive<{
data: {
value: number, name: string,
}[]
}>({
data: []
})
const heapoptionContext = reactive<{
data: {
value: number, name: string,
}[]
}>({
data: []
})
const nonheapContext = reactive<{
data: {
value: number, name: string,
}[]
}>({
data: []
})
const heapoption = reactive<CircleChartOption>({
title:{
text:"heap"
},
tooltip: {
trigger: 'item',
formatter: '{b}:{c}M {d}'
},
legend: {
top: 'center',
left: 'right',
orient: "vertical"
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
center:['35%','50%'],
avoidLabelOverlap: true,
label: {
show: false,
position: 'center',
},
labelLine: {
show: false
},
data: heapoptionContext.data
}
]
});
const nonheapoption = reactive<CircleChartOption>({
title:{
text:"nonheap"
},
tooltip: {
trigger: 'item',
formatter: '{b}:{c}M'
},
legend: {
top: 'center',
left: 'right',
orient: "vertical"
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
center:['35%','50%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
formatter: '{b}:{c}M'
},
labelLine: {
show: false
},
data: nonheapContext.data
}
]
});
const bufferPooloption = reactive<CircleChartOption>({
title: {
text: "buffer_pool"
},
tooltip: {
trigger: 'item',
formatter: '{c}M'
},
legend: {
top: 'center',
left: 'right',
orient: 'vertical'
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
center:['35%','50%'],
avoidLabelOverlap: true,
label: {
show: false,
position: 'outside',
},
labelLine: {
show: false
},
data: bufferPoolContext.data
}
]
});
const transformMemory = (result: ArthasResResult) => {
if (result.type === "dashboard") {
const heaparr: { value: number, name: string }[] = [
]
// const heaparr: { value: number, name: string }[] = [
// ]
heapoptionContext.data.length = 0
result.memoryInfo.heap.filter(v => v.name !== "heap").forEach(v => {
const arr: string[] = []
arr.push('max : ' + toMb(v.max))
arr.push('total : ' + toMb(v.total))
arr.push('used : ' + toMb(v.used))
// arr.push('max : ' + toMb(v.max))
// arr.push('total : ' + toMb(v.total))
// arr.push('used : ' + toMb(v.used))
const usage: number = (v.max > 0 ? (v.used / v.max) : (v.used / v.total)) * 100
heaparr.push({ value: toMb(v.used), name: `${v.name}(${usage.toFixed(2)}%)` })
heapoptionContext.data.push({ value: toMb(v.used), name: `${v.name}(${usage.toFixed(2)}%)` })
arr.push(usage + '%')
// arr.push(usage + '%')
memoryInfo.set(v.name, arr)
// memoryInfo.set(v.name, arr)
})
heaparr.push({
heapoptionContext.data.push({
value: Math.floor((result.memoryInfo.heap[0].max > 0 ? (result.memoryInfo.heap[0].max - result.memoryInfo.heap[0].used) : (result.memoryInfo.heap[0].total - result.memoryInfo.heap[0].used)) / 1024 / 1024),
name: "free",
})
heapChart && heapChart.setOption({
series: {
data: heaparr
}
} as EChartsOption)
// heapoptionContext.data = heaparr
const nonheaparr: {
value: number, name: string,
}[] = []
nonheapContext.data.length = 0
result.memoryInfo.nonheap.filter(v => v.name !== "nonheap").forEach(v => {
const arr: string[] = []
arr.push('max : ' + toMb(v.max))
arr.push('total : ' + toMb(v.total))
arr.push('used : ' + toMb(v.used))
// arr.push('max : ' + toMb(v.max))
// arr.push('total : ' + toMb(v.total))
// arr.push('used : ' + toMb(v.used))
const usage: number = (v.used / v.total) * 100
nonheaparr.push({ value: toMb(v.used), name: `${v.name}(${usage.toFixed(2)}%)` })
nonheapContext.data.push({ value: toMb(v.used), name: `${v.name}(${usage.toFixed(2)}%)` })
arr.push(usage * 100 + '%')
// arr.push(usage * 100 + '%')
memoryInfo.set(v.name, arr)
// memoryInfo.set(v.name, arr)
})
nonheapChart && nonheapChart.setOption({ series: { data: nonheaparr } } as EChartsOption)
// nonheapChart && nonheapChart.setOption({ series: { data: nonheaparr } } as EChartsOption)
const bufferPoolarr: {
value: number, name: string,
}[] = []
bufferPoolContext.data.length = 0
result.memoryInfo.buffer_pool.filter(v => v.name !== "buffer_pool;").forEach(v => {
bufferPoolarr.push({ value: toMb(v.used), name: `${v.name}` })
bufferPoolContext.data.push({ value: toMb(v.used), name: `${v.name}` })
})
bufferPoolChart && bufferPoolChart.setOption({ series: { data: bufferPoolarr } } as EChartsOption)
}
}
const transformThread = (result: ArthasResResult, end: number) => {
@ -144,34 +275,14 @@ const transformThread = (result: ArthasResResult, end: number) => {
}
const transformGc = (result: ArthasResResult) => {
if (result.type !== "dashboard") return;
const gcCountData: number[] = []
const gcTimeData: number[] = []
const gcxdata: string[] = []
gcChartContext.xData.length = 0
gcChartContext.collectionCount.length = 0
gcChartContext.collectionTime.length = 0
result.gcInfos.forEach(v => {
// gcInfos.set(v.name, [v.collectionCount.toString(), v.collectionTime.toString()])
gcxdata.push(v.name)
gcCountData.push(v.collectionCount)
gcTimeData.push(v.collectionTime)
gcChartContext.xData.push(v.name)
gcChartContext.collectionCount.push(v.collectionCount)
gcChartContext.collectionTime.push(v.collectionTime)
})
gcChart.setOption({
xAxis: {
type: 'category',
axisTick: {
alignWithLabel: true
},
// prettier-ignore
data: gcxdata
}, series: [{
name: "collectionCount",
type: 'bar',
data: gcCountData
}, {
name: "collectionTime",
type: 'bar',
data: gcTimeData
}]
} as GcEChartsOption)
}
const setPri = publiC.inputDialogFactory(
pri,
@ -193,17 +304,14 @@ getCommonResEffect(dashboadResM, body => {
const result = body.results.find(v => v.type === "dashboard" && v.jobId === dashboardId)
if (result && result.type === "dashboard") {
memoryInfo.clear()
transformMemory(result)
runtimeInfo.clear()
transformRuntimeInfo(result)
threads.clear()
tableResults.length = 0
transformThread(result, pri.value)
gcInfos.clear()
transformGc(result)
}
}
@ -231,212 +339,9 @@ onBeforeMount(async () => {
)
})
// dom
onMounted(() => {
// init
const clearDom = (...doms: HTMLElement[]) => {
doms.forEach(dom => {
dispose(dom)
})
}
clearChart(nonheapChart, heapChart, bufferPoolChart, gcChart)
const heapDom = document.getElementById('heapMemory')!
const nonheapDom = document.getElementById('nonheapMemory')!
const bufferPoolDom = document.getElementById('bufferPoolMemory')!
const gcDom = document.getElementById('gc-info')!
clearDom(heapDom, nonheapDom, bufferPoolDom, gcDom)
echarts.use(
[TooltipComponent, LegendComponent, PieChart, SVGRenderer, LabelLayout, ToolboxComponent, GridComponent, BarChart, LineChart, UniversalTransition]
);
const heapoption: EChartsOption = {
tooltip: {
trigger: 'item',
formatter: '{b}:{c}M {d}'
},
legend: {
top: '5%',
left: 'center'
},
series: [
{
name: 'heap memory',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: true,
label: {
show: false,
position: 'center',
},
labelLine: {
show: false
},
data: [
]
}
]
};
const nonheapoption: EChartsOption = {
tooltip: {
trigger: 'item',
formatter: '{b}:{c}M'
},
legend: {
top: '5%',
left: 'center'
},
series: [
{
name: 'nonheap memory',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
formatter: '{b}:{c}M'
},
labelLine: {
show: false
},
data: [
]
}
]
};
const bufferPooloption: EChartsOption = {
tooltip: {
trigger: 'item',
formatter: '{c}M'
},
legend: {
top: '5%',
left: 'center'
},
series: [
{
name: 'buffer_pool memory',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: true,
label: {
show: false,
position: 'outside',
},
labelLine: {
show: false
},
data: [
{
value: 0,
name: '',
}
]
}
]
};
const colors = ['#5470C6', '#91CC75'];
const gcoption: GcEChartsOption = {
color: colors,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: {
right: '20%'
},
legend: {
data: ['collectionCount', 'collectionTime']
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true
},
// prettier-ignore
data: []
}
],
toolbox: {
feature: {
dataView: { show: true, readOnly: true },
}
},
yAxis: [
{
type: 'value',
name: 'collectionCount',
position: 'left',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[0]
}
},
axisLabel: {
formatter: '{value}'
}
},
{
type: 'value',
name: 'collectionTime',
position: 'right',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[1]
}
},
axisLabel: {
formatter: '{value} ms'
}
},
],
series: [
{
name: 'collectionCount',
type: 'bar',
data: [
]
},
{
name: 'collectionTime',
type: 'bar',
yAxisIndex: 1,
data: [
]
},
]
};
heapChart = echarts.init(heapDom);
heapoption && heapChart.setOption(heapoption);
nonheapChart = echarts.init(nonheapDom);
nonheapoption && nonheapChart.setOption(nonheapoption);
bufferPoolChart = echarts.init(bufferPoolDom);
bufferPooloption && bufferPoolChart.setOption(bufferPooloption);
// gcInfosChart
gcChart = echarts.init(gcDom);
gcoption && gcChart.setOption(gcoption);
})
onBeforeUnmount(async () => {
loop.close()
clearChart(nonheapChart, heapChart, bufferPoolChart, gcChart)
})
</script>
@ -453,22 +358,21 @@ onBeforeUnmount(async () => {
</div>
<div class="flex justify-evenly mb-4 flex-1 h-80">
<div class="card border mr-4 flex-1 bg-base-100">
<div id="heapMemory" class="w-80 h-80 card-body "></div>
<Circle class="card-body" :option="heapoption"></Circle>
</div>
<div class="card border mr-4 flex-1 bg-base-100">
<div id="nonheapMemory" class="w-80 h-80 card-body"></div>
<Circle class="card-body" :option="nonheapoption"></Circle>
</div>
<div class="card border flex-1 bg-base-100">
<div id="bufferPoolMemory" class="w-80 h-80 card-body"></div>
<Circle class="card-body" :option="bufferPooloption"></Circle>
</div>
</div>
<div class="w-full flex justify-start items-start flex-1">
<div class="card bg-base-100 border mr-4">
<div id="gc-info" class="w-[40rem] h-80 card-body p-2 "></div>
<div class="card bg-base-100 border mr-4 h-80 w-1/3">
<Bar class="card-body" :option="gcoption" />
</div>
<div class="card flex-1 h-80 overflow-auto w-0 border bg-base-100">
<div class="card-body">

View File

@ -10,45 +10,12 @@ import {
import MethodInput from '@/components/input/MethodInput.vue';
import machine from '@/machines/consoleMachine';
import { fetchStore } from '@/stores/fetch';
import { onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
import Enhancer from '@/components/show/Enhancer.vue';
import { publicStore } from '@/stores/public';
import * as echarts from 'echarts/core';
import {
TitleComponent,
TitleComponentOption,
ToolboxComponent,
ToolboxComponentOption,
TooltipComponent,
TooltipComponentOption,
GridComponent,
GridComponentOption,
LegendComponent,
LegendComponentOption,
DataZoomComponent,
DataZoomComponentOption
} from 'echarts/components';
import {
BarChart,
BarSeriesOption,
LineChart,
LineSeriesOption
} from 'echarts/charts';
import {
UniversalTransition
} from 'echarts/features';
import {
SVGRenderer
} from 'echarts/renderers';
import { ECharts } from 'echarts/core';
echarts.use(
[TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent, DataZoomComponent, BarChart, LineChart, SVGRenderer, UniversalTransition]
);
type EChartsOption = echarts.ComposeOption<
TitleComponentOption | ToolboxComponentOption | TooltipComponentOption | GridComponentOption | LegendComponentOption | DataZoomComponentOption | BarSeriesOption | LineSeriesOption
>
import LineVue from "@/components/charts/Line.vue"
import Bar from '@/components/charts/Bar.vue';
import { BarChartOption, LineChartOption } from '@/echart';
const pollingM = useMachine(machine)
const fetchS = fetchStore()
const { pullResultsLoop, getCommonResEffect } = fetchS
@ -69,29 +36,28 @@ const averageRT = ref({
})
const chartContext: {
count: number,
myChart?: ECharts,
costChart?: ECharts,
categories: string[],
data: number[],
cur: number,
max: number,
successData: number[],
failureData: number[]
} = {
max: 0,
cur: 0,
count: 40,
myChart: undefined,
costChart: undefined,
failureData: number[],
dataZoom: Record<string, unknown>
} = reactive({
categories: [],
data: [],
successData: [],
failureData: [],
}
// for (let i = 0; i < chartContext.count; i++) { chartContext.categories[i] = i + 1 }
dataZoom: {
type: "inside",
minValueSpan: 10,
maxValueSpan: 10,
start: 50,
end: 100,
throttle: 0,
zoomLock: true
}
})
const chartOption = {
const chartOption = reactive<BarChartOption>({
tooltip: {
trigger: 'axis',
axisPointer: {
@ -102,12 +68,7 @@ const chartOption = {
}
},
legend: {},
toolbox: {
show: true,
feature: {
dataView: { readOnly: false },
}
},
dataZoom: chartContext.dataZoom,
xAxis: [
{
type: 'category',
@ -129,20 +90,20 @@ const chartOption = {
name: 'success',
type: 'bar',
stack: 'count',
data: [],
data: chartContext.successData,
},
{
name: 'failure',
type: 'bar',
stack: "count",
data: [],
data: chartContext.failureData,
itemStyle: {
color: "#ff0000",
}
},
]
};
const costOption = {
});
const costOption = reactive<LineChartOption>({
tooltip: {
trigger: 'axis',
axisPointer: {
@ -152,109 +113,50 @@ const costOption = {
}
}
},
legend: {},
toolbox: {
show: true,
feature: {
dataView: { readOnly: false },
}
legend: {
},
xAxis: [
{
type: 'category',
data: chartContext.categories,
axisLabel: {
formatter(value: string) {
return value.split(" ")[1]
}
dataZoom: chartContext.dataZoom,
// toolbox: {
// show: true,
// feature: {
// dataView: { readOnly: false },
// }
// },
xAxis: {
type: 'category',
data: chartContext.categories,
axisLabel: {
formatter(value: string) {
return value.split(" ")[1]
}
}
],
yAxis: [
{
type: 'value',
scale: true,
name: 'rt(ms)',
min: 0,
}
],
series: [
{
name: 'rt',
type: 'line',
data: chartContext.data
}
]
}
const updateChart = (data: MonitorData) => {
while (chartContext.cur > chartContext.count) {
chartContext.data.shift()
chartContext.successData.shift()
chartContext.failureData.shift()
chartContext.categories.shift()
chartContext.cur--
},
yAxis: {
type: 'value',
scale: true,
name: 'rt(ms)',
min: 0,
},
series: {
name: 'rt',
type: 'line',
data: chartContext.data
}
})
const updateChart = (data: MonitorData) => {
chartContext.data.push(data.cost / data.total)
chartContext.failureData.push(data.failed)
chartContext.successData.push(data.success)
chartContext.categories.push(data.timestamp)
chartContext.cur++
chartContext.myChart!.setOption<EChartsOption>({
xAxis: [
{
data: chartContext.categories
}
],
series: [{
data: chartContext.successData
}, {
data: chartContext.failureData
}
]
})
chartContext.costChart!.setOption<EChartsOption>({
xAxis: [
{
data: chartContext.categories
}
],
series: [
{
data: chartContext.data
}
]
})
}
const resetChart = () => {
chartContext.data.length = 0
chartContext.failureData.length = 0
chartContext.successData.length = 0
chartContext.myChart!.setOption<EChartsOption>({
xAxis: [
{
data: chartContext.categories
}
],
series: [{
data: chartContext.successData
}, {
data: chartContext.failureData
}
]
})
chartContext.costChart!.setOption<EChartsOption>({
xAxis: [
{
data: chartContext.categories
}
],
series: [
{
data: chartContext.data
}
]
})
enhancer.value = undefined
averageRT.value.totalCost = 0
averageRT.value.totalCount = 0
}
const transform = (result: ArthasResResult) => {
if (result.type === "monitor") {
@ -286,21 +188,11 @@ onBeforeMount(() => {
fetchS.asyncInit()
pollingM.send("INIT")
})
onMounted(() => {
const chartDom = document.getElementById('monitorchart')!;
chartContext.myChart = echarts.init(chartDom);
chartOption && chartContext.myChart.setOption(chartOption)
chartContext.costChart = echarts.init(document.getElementById('monitorchartcost')!);
chartOption && chartContext.costChart.setOption(costOption)
})
onBeforeUnmount(() => {
loop.close()
})
const submit = async (data: { classItem: Item, methodItem: Item, conditon: string }) => {
enhancer.value = undefined
// tableResults.length = 0
averageRT.value.totalCost =0
averageRT.value.totalCount = 0
resetChart()
let condition = data.conditon.trim() == "" ? "" : `'${data.conditon.trim()}'`
let cycle = `-c ${cycleV.value}`
fetchS.baseSubmit(fetchM, {
@ -321,10 +213,10 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<ListboxButton class="btn btn-sm btn-outline w-40">{{ mode.name }}</ListboxButton>
<ListboxOptions
class="absolute w-40 mt-2 border overflow-hidden rounded-md hover:shadow-xl transition bg-white z-10">
<ListboxOption v-for="(am,i) in modelist" :key="i" :value="am" v-slot="{active, selected}">
<ListboxOption v-for="(am, i) in modelist" :key="i" :value="am" v-slot="{ active, selected }">
<div class=" p-2 transition" :class="{
'bg-neutral text-neutral-content': active,
'bg-neutral-focus text-neutral-content': selected,
'bg-neutral text-neutral-content': active,
'bg-neutral-focus text-neutral-content': selected,
}">
{{ am.name }}
</div>
@ -332,13 +224,14 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
</ListboxOptions>
</div>
</Listbox>
<button class="btn btn-sm btn-outline" @click="changeCycle">cycle time:{{cycleV}}</button>
<button class="btn btn-sm btn-outline" @click="changeCycle">cycle time:{{ cycleV }}</button>
</template>
</MethodInput>
<Enhancer :result="enhancer" v-if="enhancer" class="mb-4">
</Enhancer>
<div id="monitorchart" class="input-btn-style h-60 w-full pointer-events-auto transition mb-2"></div>
<div id="monitorchartcost" class="input-btn-style h-60 w-full pointer-events-auto transition"></div>
<!-- <div id="monitorchart" class="input-btn-style h-60 w-full pointer-events-auto transition mb-2"></div> -->
<Bar class="h-60 pointer-events-auto transition" :option="chartOption" />
<!-- <div id="monitorchartcost" class="input-btn-style h-60 w-full pointer-events-auto transition"></div> -->
<LineVue class="h-60 pointer-events-auto transition" :option="costOption" />
</template>

View File

@ -8,42 +8,12 @@ import { onBeforeMount, onBeforeUnmount, onMounted, reactive, ref, } from 'vue';
import CmdResMenu from '@/components/show/CmdResMenu.vue';
import Enhancer from '@/components/show/Enhancer.vue';
import { publicStore } from '@/stores/public';
import * as echarts from 'echarts/core';
import {
TitleComponent,
TitleComponentOption,
ToolboxComponent,
ToolboxComponentOption,
TooltipComponent,
TooltipComponentOption,
GridComponent,
GridComponentOption,
LegendComponent,
LegendComponentOption,
DataZoomComponent,
DataZoomComponentOption
} from 'echarts/components';
import {
BarChart,
BarSeriesOption,
LineChart,
LineSeriesOption
} from 'echarts/charts';
import {
UniversalTransition
} from 'echarts/features';
import {
SVGRenderer
} from 'echarts/renderers';
import { ECharts, number } from 'echarts/core';
import LineVue from '@/components/charts/Line.vue';
import { LineChartOption } from '@/echart';
echarts.use(
[TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent, DataZoomComponent, BarChart, LineChart, SVGRenderer, UniversalTransition]
);
type EChartsOption = echarts.ComposeOption<
TitleComponentOption | ToolboxComponentOption | TooltipComponentOption | GridComponentOption | LegendComponentOption | DataZoomComponentOption | BarSeriesOption | LineSeriesOption
>
// type EChartsOption = echarts.ComposeOption<
// TitleComponentOption | ToolboxComponentOption | TooltipComponentOption | GridComponentOption | LegendComponentOption | DataZoomComponentOption | BarSeriesOption | LineSeriesOption
// >
const pollingM = useMachine(machine)
const fetchS = fetchStore()
const { pullResultsLoop, getPullResultsEffect } = fetchS
@ -72,21 +42,13 @@ const tableResults = reactive([] as Map<string, string>[])
type tfkey = keyof TimeFragment
const chartContext: {
count: number,
myChart?: ECharts,
categories: number[],
data: number[],
cur: number,
max: number,
} = {
max: 0,
cur: 0,
count: 20,
myChart: undefined,
} = reactive({
categories: [],
data: []
}
const chartOption = {
})
const chartOption = reactive<LineChartOption>({
tooltip: {
trigger: 'axis',
axisPointer: {
@ -96,67 +58,47 @@ const chartOption = {
}
}
},
legend: {},
legend: {
},
dataZoom: {
type: "inside",
minValueSpan:30,
maxValueSpan:30,
start: 50,
end: 100,
throttle:0,
zoomLock: true
},
toolbox: {
show: true,
feature: {
dataView: { readOnly: false },
}
},
xAxis: [
{
type: 'category',
boundaryGap: true,
data: chartContext.categories
}
],
yAxis: [
{
type: 'value',
scale: true,
name: 'cost(ms)',
max: 0,
min: 0,
boundaryGap: [0.2, 0.2]
}
],
series: [
{
name: 'cost',
type: 'bar',
xAxisIndex: 0,
yAxisIndex: 0,
data: chartContext.data
}
]
};
const updateChart = (tf: TimeFragment) => {
while (chartContext.cur > chartContext.count) {
chartContext.data.shift()
chartContext.categories.shift()
chartContext.cur--
xAxis: {
type: 'category',
boundaryGap: true,
data: chartContext.categories
},
yAxis:
{
type: 'value',
scale: true,
name: 'cost(ms)',
min: 0,
boundaryGap: [0.2, 0.2]
},
series: {
name: 'cost',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
data: chartContext.data
}
});
const updateChart = (tf: TimeFragment) => {
chartContext.data.push(tf.cost)
chartContext.categories.push(tf.index)
chartContext.cur++
chartContext.max = Math.max(...chartContext.data)
chartContext.myChart!.setOption<EChartsOption>({
xAxis: [
{
data: chartContext.categories
}
],
yAxis: [
{
max: chartContext.max,
}
],
series: [
{
data: chartContext.data
}
]
});
}
const transform = (tf: TimeFragment) => {
const map = new Map()
@ -200,14 +142,6 @@ onBeforeMount(() => {
pollingM.send("INIT")
fetchS.asyncInit()
})
onMounted(() => {
const chartDom = document.getElementById('ttchart')!;
chartContext.myChart = echarts.init(chartDom);
chartContext.myChart.on("click", e => {
console.dir(e)
})
chartOption && chartContext.myChart.setOption(chartOption)
})
onBeforeUnmount(() => {
loop.close()
})
@ -230,10 +164,13 @@ const alltt = () => fetchS.baseSubmit(fetchM, {
let result = (res as CommonRes).body.results[0]
trigerRes.clear()
tableResults.length = 0
// all
chartContext.categories.length = 0
chartContext.data.length = 0
if (result.type === "tt") {
result.timeFragmentList.forEach(tf => {
tableResults.unshift(transform(tf))
})
}
})
@ -317,7 +254,7 @@ const searchTt = () => {
</button>
</div>
<div class="pointer-events-auto">
<div id="ttchart" class="w-full h-60 input-btn-style mb-4"></div>
<LineVue :option="chartOption" class="w-full h-64 mb-4"></LineVue>
<div class="text-gray-500">
<CmdResMenu title="invoked result" :map="trigerRes" v-if="trigerRes.size > 0">
<template #headerAside>
@ -334,7 +271,7 @@ const searchTt = () => {
<thead>
<tr>
<th></th>
<th class="normal-case" v-for="(v,i) in keyList" :key="i">{{v}}</th>
<th class="normal-case" v-for="(v, i) in keyList" :key="i">{{ v }}</th>
</tr>
</thead>
<tbody class="">
@ -342,14 +279,14 @@ const searchTt = () => {
<th class="">
<button class="btn btn-primary btn-sm btn-outline" @click="reTrigger(map.get('index')!)">invoke</button>
</th>
<td class="" v-for="(key,j) in keyList" :key="j">
<template v-if=" key !== 'params'">
{{map.get(key)}}
<td class="" v-for="(key, j) in keyList" :key="j">
<template v-if="key !== 'params'">
{{ map.get(key) }}
</template>
<div class="flex flex-col" v-else>
<div v-for="(row, k) in map.get(key)" :key="k">
{{row}}
{{ row }}
</div>
</div>
</td>
@ -358,7 +295,7 @@ const searchTt = () => {
<tfoot>
<tr>
<th></th>
<th class="normal-case" v-for="(v,i) in keyList" :key="i">{{v}}</th>
<th class="normal-case" v-for="(v, i) in keyList" :key="i">{{ v }}</th>
</tr>
</tfoot>
</table>

View File

@ -129,14 +129,14 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<div class="overflow-x-auto w-full mt-4">
<table class="table w-full table-compact">
<thead>
<tr>
<tr >
<th></th>
<th class="0" v-for="(v, i) in keyList" :key="i">{{ v }}
<th v-for="(v, i) in keyList" :key="i" class="normal-case">{{ v }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(map, i) in tableResults" :key="i" class="hover">
<tr v-for="(map, i) in tableResults" :key="i" class="hover ">
<th>{{ i + 1 }}</th>
<td class="" v-for="(key, j) in keyList" :key="j">
<div v-if="key !== 'value'">
@ -151,7 +151,7 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<tfoot>
<tr>
<th></th>
<th class="0" v-for="(v, i) in keyList" :key="i">{{ v }}
<th class="normal-case" v-for="(v, i) in keyList" :key="i">{{ v }}
</th>
</tr>
</tfoot>

View File

@ -200,7 +200,7 @@
"@xstate/vue@^2.0.0":
version "2.0.0"
resolved "https://registry.npmmirror.com/@xstate/vue/-/vue-2.0.0.tgz"
resolved "https://registry.npmmirror.com/@xstate/vue/-/vue-2.0.0.tgz#bb95f91600c5fad2e8a72f872cb8f69b3b154e10"
integrity sha512-JlrJ3d+I6rZCcFBuu3O4GP+mGJfd11O9o69wRedzPMqZ+hxcMRBsih9L5kKnJHcU9CTmdJTT172oxTaYF7thzA==
acorn-node@^1.8.2: