@@ -24,6 +24,8 @@ import {
2424 Platform ,
2525 Promotion
2626} from ' @element-plus/icons-vue' ;
27+ import * as echarts from ' echarts' ;
28+ import { isDark } from ' @/composables/theme' ;
2729import Content from ' @/components/threaddump/Content.vue' ;
2830import Thread from ' @/components/threaddump/Thread.vue' ;
2931import Monitor from ' @/components/threaddump/Monitor.vue' ;
@@ -32,7 +34,6 @@ import Diagnose from '@/components/threaddump/Diagnose.vue';
3234import CpuConsumingThreads from ' @/components/threaddump/CpuConsumingThreads.vue' ;
3335import BlockedThreads from ' @/components/threaddump/BlockedThreads.vue' ;
3436import ThreadDumpSearch from ' @/components/threaddump/ThreadDumpSearch.vue' ;
35- import ThreadDumpOverview from ' @/components/threaddump/ThreadDumpOverview.vue' ;
3637
3738const { request } = useAnalysisApiRequester ();
3839
@@ -46,7 +47,6 @@ const activeNames = ref<string[]>([
4647 ' javaMonitors' ,
4748 ' callSiteTree' ,
4849 ' threadSearch' ,
49- ' dumpOverview'
5050]);
5151
5252const deadLockCount = ref (0 );
@@ -72,6 +72,43 @@ const tableDataOfThreadGroupStats = computed(() => {
7272
7373const loading = ref (false );
7474
75+ // ---- State Distribution Chart ----
76+ const COLOR_PALETTE = [
77+ ' #003f5c' , ' #2f4b7c' , ' #665191' , ' #a05195' , ' #d45087' ,
78+ ' #f95d6a' , ' #ff7c43' , ' #ffa600' , ' #488f31' , ' #8aa1b4'
79+ ];
80+ const stateChartRef = ref <HTMLElement | null >(null );
81+ let stateChart: echarts .ECharts | null = null ;
82+ const stateChartData = ref <{ name: string ; value: number }[]>([]);
83+
84+ function renderStateChart() {
85+ if (! stateChartRef .value || stateChartData .value .length === 0 ) return ;
86+ stateChart ?.dispose ();
87+ stateChart = echarts .init (stateChartRef .value , isDark .value ? ' dark' : null );
88+ stateChart .setOption ({
89+ color: COLOR_PALETTE ,
90+ tooltip: { trigger: ' item' , formatter: ' {b}: {c} ({d}%)' },
91+ legend: {
92+ orient: ' vertical' ,
93+ right: ' 5%' ,
94+ top: ' middle' ,
95+ textStyle: { fontSize: 11 },
96+ formatter : (name : string ) => name .length > 24 ? name .slice (0 , 23 ) + ' …' : name
97+ },
98+ series: [{
99+ type: ' pie' ,
100+ radius: [' 40%' , ' 68%' ],
101+ center: [' 30%' , ' 50%' ],
102+ data: stateChartData .value ,
103+ label: { show: false },
104+ emphasis: { itemStyle: { shadowBlur: 10 , shadowOffsetX: 0 , shadowColor: ' rgba(0,0,0,0.5)' } }
105+ }]
106+ });
107+ }
108+
109+ watch (isDark , () => renderStateChart ());
110+ window .addEventListener (' resize' , () => stateChart ?.resize ());
111+
75112const threadDialogVisible = ref (false );
76113const selectedThreadType = ref ();
77114const selectedThreadGroup = ref ();
@@ -229,6 +266,12 @@ function buildThreadStat(key, states, counts, icon, threadType?) {
229266
230267 threadStats .value = _threadStats ;
231268 threadGroupStats .value = _threadGroupStats ;
269+
270+ stateChartData .value = overview .javaStates
271+ .map ((name : string , i : number ) => ({ name , value: overview .javaThreadStat .javaCounts [i ] }))
272+ .filter ((d : { name: string ; value: number }) => d .value > 0 );
273+ nextTick ().then (renderStateChart );
274+
232275 loading .value = false ;
233276 });
234277});
@@ -248,19 +291,29 @@ function buildThreadStat(key, states, counts, icon, threadType?) {
248291 <div style =" width : 100% ; max-width : 1200px " >
249292 <el-collapse v-model =" activeNames" >
250293 <el-collapse-item name =" basicInfo" :title =" tdt('basicInfo')" >
251- <el-table stripe :show-header =" false" :data =" basicInfo" v-loading =" loading" >
252- <el-table-column >
253- <template #default =" { row } " >
254- <div style =" display : flex ; align-items : center " >
255- <el-icon >
256- <component :is =" row.icon" />
257- </el-icon >
258- <span style =" margin-left : 10px " >{{ tdt(row.key) }}</span >
259- </div >
260- </template >
261- </el-table-column >
262- <el-table-column prop =" value" > </el-table-column >
263- </el-table >
294+ <el-row :gutter =" 16" align =" top" >
295+ <el-col :span =" 12" >
296+ <el-table stripe :show-header =" false" :data =" basicInfo" v-loading =" loading" >
297+ <el-table-column >
298+ <template #default =" { row } " >
299+ <div style =" display : flex ; align-items : center " >
300+ <el-icon >
301+ <component :is =" row.icon" />
302+ </el-icon >
303+ <span style =" margin-left : 10px " >{{ tdt(row.key) }}</span >
304+ </div >
305+ </template >
306+ </el-table-column >
307+ <el-table-column prop =" value" > </el-table-column >
308+ </el-table >
309+ </el-col >
310+ <el-col :span =" 12" >
311+ <div style =" font-weight : 600 ; margin-bottom : 8px ; color : var (--el-text-color-regular )" >
312+ {{ tdt('stateDistributionTitle') }}
313+ </div >
314+ <div ref =" stateChartRef" style =" height : 180px " />
315+ </el-col >
316+ </el-row >
264317 </el-collapse-item >
265318
266319 <el-collapse-item name =" diagnosis" :title =" tdt('diagnosis.title')" >
@@ -370,10 +423,6 @@ function buildThreadStat(key, states, counts, icon, threadType?) {
370423 <ThreadDumpSearch />
371424 </el-collapse-item >
372425
373- <el-collapse-item name =" dumpOverview" :title =" tdt('threadDumpOverview.label')" >
374- <ThreadDumpOverview />
375- </el-collapse-item >
376-
377426 <el-collapse-item name =" callSiteTree" :title =" tdt('callSiteTree')" >
378427 <CallSiteTree />
379428 </el-collapse-item >
0 commit comments