• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../../../../base-ui/BaseElement.js';
17import { LitTable } from '../../../../../base-ui/table/lit-table.js';
18import { LitChartPie } from '../../../../../base-ui/chart/pie/LitChartPie.js';
19import '../../../../../base-ui/chart/pie/LitChartPie.js';
20import { SelectionParam } from '../../../../bean/BoxSelection.js';
21import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
22import { Utils } from '../../base/Utils.js';
23import { procedurePool } from '../../../../database/Procedure.js';
24
25@element('tabpane-tb-vm-statistics')
26export class TabPaneIOTierStatisticsAnalysis extends BaseElement {
27  private iOTierStatisticsAnalysisPie: LitChartPie | null | undefined;
28  private currentSelection: SelectionParam | null | undefined;
29  private processData: any;
30  private pidData!: any[];
31  private threadData!: any[];
32  private soData!: any[];
33  private functionData!: any[];
34  private typeData!: any[];
35  private ioTierTableProcess: LitTable | null | undefined;
36  private ioTierTableThread: LitTable | null | undefined;
37  private tableType: LitTable | null | undefined;
38  private ioTierTableSo: LitTable | null | undefined;
39  private tableFunction: LitTable | null | undefined;
40  private sumDur: number = 0;
41  private range: HTMLLabelElement | null | undefined;
42  private iOTierStatisticsAnalysisBack: HTMLDivElement | null | undefined;
43  private tabName: HTMLDivElement | null | undefined;
44  private progressEL: LitProgressBar | null | undefined;
45  private processName: string = '';
46  private threadName: string = '';
47  private sortColumn: string = '';
48  private sortType: number = 0;
49  private typeName: string = '';
50  private currentLevel = -1;
51  private currentLevelData!: Array<any>;
52  private processStatisticsData!: {};
53  private typeStatisticsData!: {};
54  private threadStatisticsData!: {};
55  private libStatisticsData!: {};
56  private functionStatisticsData!: {};
57  set data(ioTierStatisticsAnalysisSelection: SelectionParam) {
58    if (ioTierStatisticsAnalysisSelection === this.currentSelection) {
59      this.pidData.unshift(this.processStatisticsData);
60      this.ioTierTableProcess!.recycleDataSource = this.pidData;
61      // @ts-ignore
62      this.pidData.shift(this.processStatisticsData);
63      return;
64    }
65    this.clearData();
66    this.currentSelection = ioTierStatisticsAnalysisSelection;
67    this.ioTierTableProcess!.style.display = 'grid';
68    this.tableType!.style.display = 'none';
69    this.ioTierTableThread!.style.display = 'none';
70    this.ioTierTableSo!.style.display = 'none';
71    this.tableFunction!.style.display = 'none';
72    this.iOTierStatisticsAnalysisBack!.style.visibility = 'hidden';
73    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = '';
74    this.tabName!.textContent = '';
75    this.range!.textContent =
76      'Selected range: ' +
77      parseFloat(
78        ((ioTierStatisticsAnalysisSelection.rightNs - ioTierStatisticsAnalysisSelection.leftNs) / 1000000.0).toFixed(5)
79      ) +
80      '  ms';
81    this.progressEL!.loading = true;
82    this.getIoTierDataByWorker(
83      [
84        {
85          funcName: 'setSearchValue',
86          funcArgs: [''],
87        },
88        {
89          funcName: 'getCurrentDataFromDb',
90          funcArgs: [{ queryFuncName: 'io', ...ioTierStatisticsAnalysisSelection }],
91        },
92      ],
93      (results: any[]) => {
94        this.getIOTierProcess(results);
95      }
96    );
97  }
98  initElements(): void {
99    this.range = this.shadowRoot?.querySelector('#time-range');
100    this.iOTierStatisticsAnalysisPie = this.shadowRoot!.querySelector<LitChartPie>('#io-tier-chart-pie');
101    this.ioTierTableProcess = this.shadowRoot!.querySelector<LitTable>('#tb-process-usage');
102    this.ioTierTableThread = this.shadowRoot!.querySelector<LitTable>('#tb-thread-usage');
103    this.ioTierTableSo = this.shadowRoot!.querySelector<LitTable>('#tb-so-usage');
104    this.tableFunction = this.shadowRoot!.querySelector<LitTable>('#tb-function-usage');
105    this.tableType = this.shadowRoot!.querySelector<LitTable>('#tb-type-usage');
106    this.iOTierStatisticsAnalysisBack = this.shadowRoot!.querySelector<HTMLDivElement>('.io-tier-go-back');
107    this.tabName = this.shadowRoot!.querySelector<HTMLDivElement>('.io-tier-subheading');
108    this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar;
109    this.goBack();
110  }
111  clearData(): void {
112    this.iOTierStatisticsAnalysisPie!.dataSource = [];
113    this.ioTierTableProcess!.recycleDataSource = [];
114    this.tableType!.recycleDataSource = [];
115    this.ioTierTableThread!.recycleDataSource = [];
116    this.ioTierTableSo!.recycleDataSource = [];
117    this.tableFunction!.recycleDataSource = [];
118  }
119  goBack(): void {
120    this.iOTierStatisticsAnalysisBack!.addEventListener('click', () => {
121      if (this.tabName!.textContent === 'Statistic By type AllDuration') {
122        this.ioTierTableProcess!.style.display = 'grid';
123        this.tableType!.style.display = 'none';
124        this.iOTierStatisticsAnalysisBack!.style.visibility = 'hidden';
125        this.tableType!.setAttribute('hideDownload', '');
126        this.ioTierTableProcess?.removeAttribute('hideDownload');
127        this.currentLevel = 0;
128        this.processPieChart();
129      } else if (this.tabName!.textContent === 'Statistic By Thread AllDuration') {
130        this.tableType!.style.display = 'grid';
131        this.ioTierTableThread!.style.display = 'none';
132        this.ioTierTableThread!.setAttribute('hideDownload', '');
133        this.tableType?.removeAttribute('hideDownload');
134        this.currentLevel = 1;
135        this.typePieChart();
136      } else if (this.tabName!.textContent === 'Statistic By Library AllDuration') {
137        this.ioTierTableThread!.style.display = 'grid';
138        this.ioTierTableSo!.style.display = 'none';
139        this.ioTierTableSo!.setAttribute('hideDownload', '');
140        this.ioTierTableThread?.removeAttribute('hideDownload');
141        this.currentLevel = 2;
142        this.threadPieChart();
143      } else if (this.tabName!.textContent === 'Statistic By Function AllDuration') {
144        this.ioTierTableSo!.style.display = 'grid';
145        this.tableFunction!.style.display = 'none';
146        this.tableFunction!.setAttribute('hideDownload', '');
147        this.ioTierTableSo?.removeAttribute('hideDownload');
148        this.currentLevel = 3;
149        this.libraryPieChart();
150      }
151    });
152  }
153  processPieChart(): void {
154    // @ts-ignore
155    this.sumDur = this.processStatisticsData.allDuration;
156    this.iOTierStatisticsAnalysisPie!.config = {
157      appendPadding: 0,
158      data: this.getIOTierPieChartData(this.pidData),
159      angleField: 'duration',
160      colorField: 'tableName',
161      radius: 1,
162      label: {
163        type: 'outer',
164      },
165      tip: this.getTip(),
166      angleClick: (ioTierPieItem): void => {
167        // @ts-ignore
168        if (ioTierPieItem.tableName != 'other') {
169          this.ioTierProcessLevelClickEvent(ioTierPieItem);
170        }
171      },
172      hoverHandler: (ioTierPieData): void => {
173        if (ioTierPieData) {
174          this.ioTierTableProcess!.setCurrentHover(ioTierPieData);
175        } else {
176          this.ioTierTableProcess!.mouseOut();
177        }
178      },
179      interactions: [
180        {
181          type: 'element-active',
182        },
183      ],
184    };
185    this.ioTierTableProcess!.addEventListener('row-hover', (event) => {
186      // @ts-ignore
187      let ioTierProcessData = event.detail;
188      if (ioTierProcessData.data) {
189        let processData = ioTierProcessData.data;
190        processData.isHover = true;
191        if (ioTierProcessData.callBack) {
192          ioTierProcessData.callBack(true);
193        }
194      }
195      this.iOTierStatisticsAnalysisPie?.showHover();
196      this.iOTierStatisticsAnalysisPie?.hideTip();
197    });
198    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = '';
199    this.tabName!.textContent = 'Statistic By Process AllDuration';
200    this.pidData.unshift(this.processStatisticsData);
201    this.ioTierTableProcess!.recycleDataSource = this.pidData;
202    // @ts-ignore
203    this.pidData.shift(this.processStatisticsData);
204    this.currentLevelData = this.pidData;
205    this.ioTierTableProcess?.reMeauseHeight();
206    this.ioTierTableProcess!.addEventListener('column-click', (evt) => {
207      // @ts-ignore
208      this.sortByColumn(evt.detail.key, evt.detail.sort);
209    });
210    this.ioTierTableProcess!.addEventListener('row-click', (evt) => {
211      // @ts-ignore
212      let data = evt.detail.data;
213      if (data.tableName !== '' && data.duration !== 0) {
214        this.ioTierProcessLevelClickEvent(data);
215      }
216    });
217  }
218  ioTierProcessLevelClickEvent(it: any): void {
219    this.clearData();
220    this.iOTierStatisticsAnalysisBack!.style.visibility = 'visible';
221    this.ioTierTableProcess!.style.display = 'none';
222    this.tableType!.style.display = 'grid';
223    this.ioTierTableProcess!.setAttribute('hideDownload', '');
224    this.tableType?.removeAttribute('hideDownload');
225    this.getIOTierType(it);
226    this.processName = it.tableName;
227    this.iOTierStatisticsAnalysisPie?.hideTip();
228    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = this.processName;
229  }
230  typePieChart(): void {
231    this.iOTierStatisticsAnalysisPie!.config = {
232      appendPadding: 0,
233      data: this.typeData,
234      angleField: 'duration',
235      colorField: 'tableName',
236      radius: 1,
237      label: {
238        type: 'outer',
239      },
240      tip: (obj): string => {
241        return this.getIoTierTip(obj);
242      },
243      angleClick: (it): void => {
244        this.ioTierTypeLevelClickEvent(it);
245      },
246      hoverHandler: (ioTierData): void => {
247        if (ioTierData) {
248          this.tableType!.setCurrentHover(ioTierData);
249        } else {
250          this.tableType!.mouseOut();
251        }
252      },
253      interactions: [
254        {
255          type: 'element-active',
256        },
257      ],
258    };
259    this.tableType!.addEventListener('row-hover', (evt) => {
260      // @ts-ignore
261      let ioTypeData = evt.detail;
262      if (ioTypeData.data) {
263        let tableData = ioTypeData.data;
264        tableData.isHover = true;
265        if (ioTypeData.callBack) {
266          ioTypeData.callBack(true);
267        }
268      }
269      this.iOTierStatisticsAnalysisPie?.showHover();
270      this.iOTierStatisticsAnalysisPie?.hideTip();
271    });
272    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = this.processName;
273    this.tabName!.textContent = 'Statistic By type AllDuration';
274    this.typeData.unshift(this.typeStatisticsData);
275    this.tableType!.recycleDataSource = this.typeData;
276    // @ts-ignore
277    this.typeData.shift(this.typeStatisticsData);
278    this.currentLevelData = this.typeData;
279    this.tableType?.reMeauseHeight();
280    this.tableType!.addEventListener('column-click', (evt) => {
281      // @ts-ignore
282      this.sortByColumn(evt.detail.key, evt.detail.sort);
283    });
284    this.tableType!.addEventListener('row-click', (evt) => {
285      // @ts-ignore
286      let data = evt.detail.data;
287      if (data.tableName !== '' && data.duration !== 0) {
288        this.ioTierTypeLevelClickEvent(data);
289      }
290    });
291  }
292  ioTierTypeLevelClickEvent(it: any): void {
293    this.clearData();
294    this.tableType!.style.display = 'none';
295    this.ioTierTableThread!.style.display = 'grid';
296    this.tableType!.setAttribute('hideDownload', '');
297    this.ioTierTableThread?.removeAttribute('hideDownload');
298    this.getIOTierThread(it);
299    this.typeName = it.tableName;
300    this.iOTierStatisticsAnalysisPie?.hideTip();
301    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = this.processName + ' / ' + this.typeName;
302  }
303  threadPieChart(): void {
304    // @ts-ignore
305    this.sumDur = this.threadStatisticsData.allDuration;
306    this.iOTierStatisticsAnalysisPie!.config = {
307      appendPadding: 0,
308      data: this.getIOTierPieChartData(this.threadData),
309      angleField: 'duration',
310      colorField: 'tableName',
311      radius: 1,
312      label: {
313        type: 'outer',
314      },
315      tip: (obj): string => {
316        return this.getIoTierTip(obj);
317      },
318      angleClick: (it): void => {
319        // @ts-ignore
320        if (it.tableName != 'other') {
321          this.ioTierThreadLevelClickEvent(it);
322        }
323      },
324      hoverHandler: (data): void => {
325        if (data) {
326          this.ioTierTableThread!.setCurrentHover(data);
327        } else {
328          this.ioTierTableThread!.mouseOut();
329        }
330      },
331      interactions: [
332        {
333          type: 'element-active',
334        },
335      ],
336    };
337    this.ioTierTableThread!.addEventListener('row-hover', (evt) => {
338      // @ts-ignore
339      let ioThreadData = evt.detail;
340      if (ioThreadData.data) {
341        let threadData = ioThreadData.data;
342        threadData.isHover = true;
343        if (ioThreadData.callBack) {
344          ioThreadData.callBack(true);
345        }
346      }
347      this.iOTierStatisticsAnalysisPie?.showHover();
348      this.iOTierStatisticsAnalysisPie?.hideTip();
349    });
350    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent = this.processName + ' / ' + this.typeName;
351    this.tabName!.textContent = 'Statistic By Thread AllDuration';
352    this.threadData.unshift(this.threadStatisticsData);
353    this.ioTierTableThread!.recycleDataSource = this.threadData;
354    // @ts-ignore
355    this.threadData.shift(this.threadStatisticsData);
356    this.currentLevelData = this.threadData;
357    this.ioTierTableThread?.reMeauseHeight();
358    this.ioTierTableThread!.addEventListener('column-click', (evt) => {
359      // @ts-ignore
360      this.sortByColumn(evt.detail.key, evt.detail.sort);
361    });
362    this.ioTierTableThread!.addEventListener('row-click', (evt) => {
363      // @ts-ignore
364      let data = evt.detail.data;
365      if (data.tableName !== '' && data.duration !== 0) {
366        this.ioTierThreadLevelClickEvent(data);
367      }
368    });
369  }
370  private getIoTierTip(obj: { obj: { tableName: any; durFormat: any; percent: any; }; }) {
371    return `<div>
372                                <div>ThreadName:${ obj.obj.tableName }</div>
373                                <div>Duration:${ obj.obj.durFormat }</div>
374                                <div>Percent:${ obj.obj.percent }%</div>
375                            </div>
376                                `;
377  }
378  ioTierThreadLevelClickEvent(it: any): void {
379    this.clearData();
380    this.iOTierStatisticsAnalysisBack!.style.visibility = 'visible';
381    this.ioTierTableThread!.style.display = 'none';
382    this.ioTierTableSo!.style.display = 'grid';
383    this.ioTierTableThread!.setAttribute('hideDownload', '');
384    this.ioTierTableSo?.removeAttribute('hideDownload');
385    this.getIOTierSo(it);
386    this.threadName = it.tableName;
387    this.iOTierStatisticsAnalysisPie?.hideTip();
388    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent =
389      this.processName + ' / ' + this.typeName + ' / ' + this.threadName;
390  }
391  libraryPieChart(): void {
392    // @ts-ignore
393    this.sumDur = this.libStatisticsData.allDuration;
394    this.iOTierStatisticsAnalysisPie!.config = {
395      appendPadding: 0,
396      data: this.getIOTierPieChartData(this.soData),
397      angleField: 'duration',
398      colorField: 'tableName',
399      radius: 1,
400      label: {
401        type: 'outer',
402      },
403      tip: (ioTierObj): string => {
404        return `<div>
405                                <div>Library:${ ioTierObj.obj.tableName }</div>
406                                <div>Duration:${ ioTierObj.obj.durFormat }</div>
407                                <div>Percent:${ ioTierObj.obj.percent }%</div>
408                            </div>
409                                `;
410      },
411      angleClick: (ioTierBean): void => {
412        // @ts-ignore
413        if (ioTierBean.tableName != 'other') {
414          this.ioTierSoLevelClickEvent(ioTierBean);
415        }
416      },
417      hoverHandler: (data): void => {
418        if (data) {
419          this.ioTierTableSo!.setCurrentHover(data);
420        } else {
421          this.ioTierTableSo!.mouseOut();
422        }
423      },
424      interactions: [
425        {
426          type: 'element-active',
427        },
428      ],
429    };
430    this.ioTierTableSo!.addEventListener('row-hover', (evt) => {
431      // @ts-ignore
432      let ioTierSoData = evt.detail;
433      if (ioTierSoData.data) {
434        let soData = ioTierSoData.data;
435        soData.isHover = true;
436        if (ioTierSoData.callBack) {
437          ioTierSoData.callBack(true);
438        }
439      }
440      this.iOTierStatisticsAnalysisPie?.showHover();
441      this.iOTierStatisticsAnalysisPie?.hideTip();
442    });
443    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent =
444      this.processName + ' / ' + this.typeName + ' / ' + this.threadName;
445    this.tabName!.textContent = 'Statistic By Library AllDuration';
446    this.soData.unshift(this.libStatisticsData);
447    this.ioTierTableSo!.recycleDataSource = this.soData;
448    // @ts-ignore
449    this.soData.shift(this.libStatisticsData);
450    this.currentLevelData = this.soData;
451    this.ioTierTableSo?.reMeauseHeight();
452    this.ioTierTableSo!.addEventListener('column-click', (evt) => {
453      // @ts-ignore
454      this.sortByColumn(evt.detail.key, evt.detail.sort);
455    });
456    this.ioTierTableSo!.addEventListener('row-click', (evt) => {
457      // @ts-ignore
458      let data = evt.detail.data;
459      if (data.tableName !== '' && data.duration !== 0) {
460        this.ioTierSoLevelClickEvent(data);
461      }
462    });
463  }
464  ioTierSoLevelClickEvent(it: any): void {
465    this.clearData();
466    this.iOTierStatisticsAnalysisBack!.style.visibility = 'visible';
467    this.ioTierTableSo!.style.display = 'none';
468    this.tableFunction!.style.display = 'grid';
469    this.ioTierTableSo!.setAttribute('hideDownload', '');
470    this.tableFunction?.removeAttribute('hideDownload');
471    this.getIOTierFunction(it);
472    this.iOTierStatisticsAnalysisPie?.hideTip();
473    this.shadowRoot!.querySelector<HTMLDivElement>('.title')!.textContent =
474      this.processName + ' / ' + this.typeName + ' / ' + this.threadName + ' / ' + it.tableName;
475  }
476  sortByColumn(column: string, ioSort: number): void {
477    this.sortColumn = column;
478    this.sortType = ioSort;
479    let ioTierCurrentTable: LitTable | null | undefined;
480    switch (this.currentLevel) {
481      case 0:
482        ioTierCurrentTable = this.ioTierTableProcess;
483        break;
484      case 1:
485        ioTierCurrentTable = this.tableType;
486        break;
487      case 2:
488        ioTierCurrentTable = this.ioTierTableThread;
489        break;
490      case 3:
491        ioTierCurrentTable = this.ioTierTableSo;
492        break;
493      case 4:
494        ioTierCurrentTable = this.tableFunction;
495        break;
496    }
497    if (!ioTierCurrentTable) {
498      return;
499    }
500    if (ioSort === 0) {
501      let sortZeroIoArr = [...this.currentLevelData];
502      switch (this.currentLevel) {
503        case 0:
504          sortZeroIoArr.unshift(this.processStatisticsData);
505          break;
506        case 1:
507          sortZeroIoArr.unshift(this.typeStatisticsData);
508          break;
509        case 2:
510          sortZeroIoArr.unshift(this.threadStatisticsData);
511          break;
512        case 3:
513          sortZeroIoArr.unshift(this.libStatisticsData);
514          break;
515        case 4:
516          sortZeroIoArr.unshift(this.functionStatisticsData);
517          break;
518      }
519      ioTierCurrentTable!.recycleDataSource = sortZeroIoArr;
520    } else {
521      let sortIoArr = [...this.currentLevelData];
522      if (column === 'tableName') {
523          ioTierCurrentTable!.recycleDataSource = sortIoArr.sort((firstIOElement, secondIOElement) => {
524          if (ioSort === 1) {
525            if (firstIOElement.tableName > secondIOElement.tableName) {
526              return 1;
527            } else if (firstIOElement.tableName === secondIOElement.tableName) {
528              return 0;
529            } else {
530              return -1;
531            }
532          } else {
533            if (secondIOElement.tableName > firstIOElement.tableName) {
534              return 1;
535            } else if (firstIOElement.tableName === secondIOElement.tableName) {
536              return 0;
537            } else {
538              return -1;
539            }
540          }
541        });
542      } else if (column === 'durFormat' || column === 'percent') {
543        ioTierCurrentTable!.recycleDataSource = sortIoArr.sort((a, b) => {
544          return ioSort === 1 ? a.duration - b.duration : b.duration - a.duration;
545        });
546      }
547      switch (this.currentLevel) {
548        case 0:
549          sortIoArr.unshift(this.processStatisticsData);
550          break;
551        case 1:
552          sortIoArr.unshift(this.typeStatisticsData);
553          break;
554        case 2:
555          sortIoArr.unshift(this.threadStatisticsData);
556          break;
557        case 3:
558          sortIoArr.unshift(this.libStatisticsData);
559          break;
560        case 4:
561          sortIoArr.unshift(this.functionStatisticsData);
562          break;
563      }
564      ioTierCurrentTable!.recycleDataSource = sortIoArr;
565    }
566  }
567  getIOTierProcess(result: Array<any>): void {
568    this.processData = JSON.parse(JSON.stringify(result));
569    if (!this.processData || this.processData.length === 0) {
570      this.pidData = [];
571      this.processStatisticsData = [];
572      this.processPieChart();
573      return;
574    }
575    let allDur = 0;
576    let ioMap = new Map<string, Array<number | string>>();
577    for (let itemData of result) {
578      allDur += itemData.dur;
579      if (ioMap.has(itemData.pid)) {
580        ioMap.get(itemData.pid)?.push(itemData);
581      } else {
582        let itemArray = new Array<number | string>();
583        itemArray.push(itemData);
584        ioMap.set(itemData.pid, itemArray);
585      }
586    }
587    this.pidData = [];
588    ioMap.forEach((value: Array<any>, key: string) => {
589      let ioPidDataDur = 0;
590      let pName = '';
591      for (let item of value) {
592        pName = item.processName =
593          item.processName === null || item.processName === undefined
594            ? `Process(${ item.pid })`
595            : `${ item.processName }(${ item.pid })`;
596        ioPidDataDur += item.dur;
597      }
598      this.pidData.push({
599        tableName: pName,
600        pid: key,
601        percent: ((ioPidDataDur / allDur) * 100).toFixed(2),
602        durFormat: Utils.getProbablyTime(ioPidDataDur),
603        duration: ioPidDataDur,
604      });
605    });
606    this.pidData.sort((a, b) => b.duration - a.duration);
607    this.processStatisticsData = this.totalDurationData(allDur);
608    this.currentLevel = 0;
609    this.progressEL!.loading = false;
610    this.processPieChart();
611    new ResizeObserver(() => {
612      if (this.parentElement?.clientHeight != 0) {
613        this.ioTierTableProcess!.style.height = this.parentElement!.clientHeight - 50 + 'px';
614        this.ioTierTableProcess?.reMeauseHeight();
615        this.ioTierTableThread!.style.height = this.parentElement!.clientHeight - 50 + 'px';
616        this.ioTierTableThread?.reMeauseHeight();
617        this.ioTierTableSo!.style.height = this.parentElement!.clientHeight - 50 + 'px';
618        this.ioTierTableSo?.reMeauseHeight();
619        this.tableFunction!.style.height = this.parentElement!.clientHeight - 50 + 'px';
620        this.tableFunction?.reMeauseHeight();
621        this.tableType!.style.height = this.parentElement!.clientHeight - 50 + 'px';
622        this.tableType?.reMeauseHeight();
623      }
624    }).observe(this.parentElement!);
625  }
626  getIOTierType(item: any): void {
627    this.progressEL!.loading = true;
628    let ioTypeMap = new Map<number, Array<number | string>>();
629    let pid = item.pid;
630    let allDur = 0;
631    if (!this.processData || this.processData.length === 0) {
632      return;
633    }
634    for (let processItem of this.processData) {
635      if (processItem.pid !== pid) {
636        continue;
637      }
638      allDur += processItem.dur;
639      if (ioTypeMap.has(processItem.type)) {
640        ioTypeMap.get(processItem.type)?.push(processItem);
641      } else {
642        let itemArray = new Array<number | string>();
643        itemArray.push(processItem);
644        ioTypeMap.set(processItem.type, itemArray);
645      }
646    }
647    this.typeData = [];
648    ioTypeMap.forEach((value: Array<any>, key: number) => {
649      let dur = 0;
650      for (let ioItem of value) {
651        dur += ioItem.dur;
652      }
653      const ioTypeData = {
654        tableName: this.typeIdToString(key),
655        pid: item.pid,
656        type: key,
657        percent: ((dur / allDur) * 100).toFixed(2),
658        durFormat: Utils.getProbablyTime(dur),
659        duration: dur,
660      };
661      this.typeData.push(ioTypeData);
662    });
663    this.typeData.sort((a, b) => b.duration - a.duration);
664    this.typeStatisticsData = this.totalDurationData(allDur);
665    this.currentLevel = 1;
666    this.typePieChart();
667    this.progressEL!.loading = false;
668  }
669  getIOTierThread(item: any): void {
670    this.progressEL!.loading = true;
671    let threadMap = new Map<string, Array<number | string>>();
672    let pid = item.pid;
673    let type = item.type;
674    let allDur = 0;
675    if (!this.processData || this.processData.length === 0) {
676      return;
677    }
678    for (let itemData of this.processData) {
679      if (itemData.pid !== pid || itemData.type !== type) {
680        continue;
681      }
682      allDur += itemData.dur;
683      if (threadMap.has(itemData.tid)) {
684        threadMap.get(itemData.tid)?.push(itemData);
685      } else {
686        let itemArray = new Array<number | string>();
687        itemArray.push(itemData);
688        threadMap.set(itemData.tid, itemArray);
689      }
690    }
691    this.threadData = [];
692    threadMap.forEach((value: Array<any>, key: string) => {
693      let dur = 0;
694      let tName = '';
695      for (let item of value) {
696        dur += item.dur;
697        tName = item.threadName =
698          item.threadName === null || item.threadName === undefined ? `Thread(${ item.tid })` : `${ item.threadName }`;
699      }
700      const threadData = {
701        tableName: tName,
702        pid: item.pid,
703        type: item.type,
704        tid: key,
705        percent: ((dur / allDur) * 100).toFixed(2),
706        durFormat: Utils.getProbablyTime(dur),
707        duration: dur,
708      };
709      this.threadData.push(threadData);
710    });
711    this.threadData.sort((a, b) => b.duration - a.duration);
712    this.threadStatisticsData = this.totalDurationData(allDur);
713    this.currentLevel = 2;
714    this.progressEL!.loading = false;
715    this.threadPieChart();
716  }
717  getIOTierSo(item: any): void {
718    this.progressEL!.loading = true;
719    let tid = item.tid;
720    let pid = item.pid;
721    let type = item.type;
722    let allDur = 0;
723    let libMap = new Map<number, Array<number | string>>();
724    if (!this.processData || this.processData.length === 0) {
725      return;
726    }
727    for (let processItemData of this.processData) {
728      if (processItemData.pid !== pid || processItemData.tid !== tid || processItemData.type !== type) {
729        continue;
730      }
731      allDur += processItemData.dur;
732      if (libMap.has(processItemData.libId)) {
733        libMap.get(processItemData.libId)?.push(processItemData);
734      } else {
735        let dataArray = new Array<number | string>();
736        dataArray.push(processItemData);
737        libMap.set(processItemData.libId, dataArray);
738      }
739    }
740    this.soData = [];
741    libMap.forEach((value: any[], key: number) => {
742      let dur = 0;
743      let libName = '';
744      for (let item of value) {
745        dur += item.dur;
746        if (key === null) {
747          item.libName = 'unknown';
748        }
749        libName = item.libName;
750      }
751      let libPath = libName?.split('/');
752      if (libPath) {
753        libName = libPath[libPath.length - 1];
754      }
755      const soData = {
756        tableName: libName,
757        pid: item.pid,
758        type: item.type,
759        tid: item.tid,
760        libId: key,
761        percent: ((dur / allDur) * 100).toFixed(2),
762        durFormat: Utils.getProbablyTime(dur),
763        duration: dur,
764      };
765      this.soData.push(soData);
766    });
767    this.soData.sort((a, b) => b.duration - a.duration);
768    this.libStatisticsData = this.totalDurationData(allDur);
769    this.currentLevel = 3;
770    this.progressEL!.loading = false;
771    this.libraryPieChart();
772  }
773  getIOTierFunction(item: any): void {
774    this.progressEL!.loading = true;
775    this.shadowRoot!.querySelector<HTMLDivElement>('.io-tier-subheading')!.textContent = 'Statistic By Function AllDuration';
776    let tid = item.tid;
777    let pid = item.pid;
778    let type = item.type;
779    let libId = item.libId;
780    let allDur = 0;
781    let symbolMap = new Map<number, Array<any>>();
782    if (!this.processData || this.processData.length === 0) {
783      return;
784    }
785    for (let processData of this.processData) {
786      if (
787        processData.pid !== pid ||
788        processData.tid !== tid ||
789        processData.type !== type ||
790        processData.libId !== libId
791      ) {
792        continue;
793      }
794      allDur += processData.dur;
795      if (symbolMap.has(processData.symbolId)) {
796        symbolMap.get(processData.symbolId)?.push(processData);
797      } else {
798        let dataArray = new Array<number | string>();
799        dataArray.push(processData);
800        symbolMap.set(processData.symbolId, dataArray);
801      }
802    }
803    this.functionData = [];
804    symbolMap.forEach((symbolItems, key) => {
805      let dur = 0;
806      let funSymbolName = '';
807      for (let symbolItem of symbolItems) {
808        funSymbolName = symbolItem.symbolName;
809        dur += symbolItem.dur;
810      }
811      let symbolPath = funSymbolName?.split('/');
812      if (symbolPath) {
813        funSymbolName = symbolPath[symbolPath.length - 1];
814      }
815      const symbolData = {
816        pid: item.pid,
817        tid: item.tid,
818        percent: ((dur / allDur) * 100).toFixed(2),
819        tableName: funSymbolName,
820        durFormat: Utils.getProbablyTime(dur),
821        duration: dur,
822      };
823      this.functionData.push(symbolData);
824    });
825    this.functionData.sort((a, b) => b.duration - a.duration);
826    this.functionStatisticsData = this.totalDurationData(allDur);
827    this.currentLevel = 4;
828    this.progressEL!.loading = false;
829    // @ts-ignore
830    this.sumDur = this.functionStatisticsData.allDuration;
831    this.iOTierStatisticsAnalysisPie!.config = {
832      appendPadding: 0,
833      data: this.getIOTierPieChartData(this.functionData),
834      angleField: 'duration',
835      colorField: 'tableName',
836      radius: 1,
837      label: {
838        type: 'outer',
839      },
840      tip: this.getTip(),
841      hoverHandler: (data): void => {
842        if (data) {
843          this.tableFunction!.setCurrentHover(data);
844        } else {
845          this.tableFunction!.mouseOut();
846        }
847      },
848      interactions: [
849        {
850          type: 'element-active',
851        },
852      ],
853    };
854    this.tableFunction!.addEventListener('row-hover', (evt) => {
855      // @ts-ignore
856      let ioFunctionData = evt.detail;
857      if (ioFunctionData.data) {
858        let funData = ioFunctionData.data;
859        funData.isHover = true;
860        if (ioFunctionData.callBack) {
861          ioFunctionData.callBack(true);
862        }
863      }
864      this.iOTierStatisticsAnalysisPie?.showHover();
865      this.iOTierStatisticsAnalysisPie?.hideTip();
866    });
867    this.functionData.unshift(this.functionStatisticsData);
868    this.tableFunction!.recycleDataSource = this.functionData;
869    this.tableFunction?.reMeauseHeight();
870    // @ts-ignore
871    this.functionData.shift(this.functionStatisticsData);
872    this.currentLevelData = this.functionData;
873    this.tableFunction!.addEventListener('column-click', (evt) => {
874      // @ts-ignore
875      this.sortByColumn(evt.detail.key, evt.detail.sort);
876    });
877  }
878
879  private getTip() {
880    return (obj: { obj: { tableName: any; durFormat: any; percent: any; }; }): string => {
881      return `<div>
882                                    <div>Function:${obj.obj.tableName}</div>
883                                    <div>Duration:${obj.obj.durFormat}</div>
884                                    <div>percent:${obj.obj.percent}</div>
885                                        </div>
886                                                `;
887    };
888  }
889
890  typeIdToString(type: number): string {
891    let ioTierReleaseType: string;
892    if (type === 1) {
893      ioTierReleaseType = 'DATA_READ';
894    } else if (type === 2) {
895      ioTierReleaseType = 'DATA_WRITE';
896    } else if (type === 3) {
897      ioTierReleaseType = 'METADATA_READ';
898    } else if (type === 4) {
899      ioTierReleaseType = 'METADATA_WRITE';
900    }
901    // @ts-ignore
902    return ioTierReleaseType;
903  }
904  totalDurationData(duration: number): {
905    durFormat: string; percent: string; tableName: string;
906    duration: number; allDuration: number;
907  } {
908    let allDuration;
909    allDuration = {
910      durFormat: Utils.getProbablyTime(duration),
911      percent: ((duration / duration) * 100).toFixed(2),
912      tableName: '',
913      duration: 0,
914      allDuration: duration,
915    };
916    return allDuration;
917  }
918  getIOTierPieChartData(res: any[]): unknown[] {
919    if (res.length > 20) {
920      let IOTierPieChartArr: string[] = [];
921      let other: any = {
922        tableName: 'other',
923        duration: 0,
924        percent: 0,
925        durFormat: 0,
926      };
927      for (let i = 0 ; i < res.length ; i++) {
928        if (i < 19) {
929          IOTierPieChartArr.push(res[i]);
930        } else {
931          other.duration += res[i].duration;
932          other.durFormat = Utils.getProbablyTime(other.duration);
933          other.percent = ((other.duration / this.sumDur) * 100).toFixed(2);
934        }
935      }
936      IOTierPieChartArr.push(other);
937      return IOTierPieChartArr;
938    }
939    return res;
940  }
941
942  getIoTierDataByWorker(args: any[], handler: Function): void {
943    procedurePool.submitWithName(
944      'logic0',
945      'fileSystem-action',
946      { args, callType: 'io', isAnalysis: true },
947      undefined,
948      (results: any) => {
949        handler(results);
950        this.progressEL!.loading = false;
951      }
952    );
953  }
954
955  initHtml(): string {
956    return `
957        <style>
958        :host {
959            display: flex;
960            flex-direction: column;
961        }
962        #io-tier-chart-pie{
963            height: 300px;
964        }
965        .io-tier-table-box{
966            width: 60%;
967            border-left: solid 1px var(--dark-border1,#e0e0e0);
968            border-radius: 5px;
969            padding: 10px;
970        }
971        .io-tier-go-back{
972            display:flex;
973            align-items: center;
974            cursor: pointer;
975            margin-left: 20px;
976            visibility: hidden;
977        }
978        .io-tier-back-box{
979            background-color: var(--bark-expansion,#0C65D1);
980            border-radius: 5px;
981            color: #fff;
982            display: flex;
983            margin-right: 10px;
984            width: 40px;
985            height: 20px;
986            justify-content: center;
987            align-items: center;
988        }
989        .io-tier-subheading{
990            font-weight: bold;
991            text-align: center;
992        }
993        .progress{
994            position: absolute;
995            height: 1px;
996            left: 0;
997            right: 0;
998        }
999        </style>
1000        <label id="time-range" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;margin-bottom: 5px">Selected range:0.0 ms</label>
1001        <div style="display: flex;flex-direction: row;"class="d-box">
1002            <lit-progress-bar class="progress"></lit-progress-bar>
1003                     <div id="left_table" style="width: 40%;height:auto;">
1004                         <div style="display: flex;margin-bottom: 10px">
1005                           <div class="io-tier-go-back">
1006                              <div class="io-tier-back-box">
1007                                  <lit-icon name="arrowleft"></lit-icon>
1008                              </div>
1009                           </div>
1010                         <div class="title"></div>
1011                        </div>
1012                         <div class="io-tier-subheading"></div>
1013                         <lit-chart-pie  id="io-tier-chart-pie"></lit-chart-pie>
1014                     </div>
1015                     <div class="io-tier-table-box" style="height:auto;overflow: auto">
1016                    <lit-table id="tb-process-usage" style="max-height:565px;min-height: 350px">
1017                        <lit-table-column width="1fr" title="ProcessName" data-index="tableName" key="tableName" align="flex-start"order></lit-table-column>
1018                        <lit-table-column width="1fr" title="Duration" data-index="durFormat" key="durFormat" align="flex-start" order></lit-table-column>
1019                        <lit-table-column width="1fr" title="%" data-index="percent" key="percent" align="flex-start"order></lit-table-column>
1020                    </lit-table>
1021                    <lit-table id="tb-type-usage" class="io-analysis" style="max-height:565px;min-height: 350px"hideDownload>
1022                        <lit-table-column width="1fr" title="Type" data-index="tableName" key="tableName" align="flex-start"order></lit-table-column>
1023                        <lit-table-column width="1fr" title="Duration" data-index="durFormat" key="durFormat" align="flex-start" order></lit-table-column>
1024                        <lit-table-column width="1fr" title="%" data-index="percent" key="percent" align="flex-start"order></lit-table-column>
1025                    </lit-table>
1026                    <lit-table id="tb-thread-usage" class="io-analysis" style="max-height:565px;display: none;min-height: 350px"hideDownload>
1027                        <lit-table-column width="1fr" title="ThreadName" data-index="tableName" key="tableName" align="flex-start"order></lit-table-column>
1028                        <lit-table-column width="1fr" title="Duration" data-index="durFormat" key="durFormat" align="flex-start" order></lit-table-column>
1029                        <lit-table-column width="1fr" title="%" data-index="percent" key="percent" align="flex-start"order></lit-table-column>
1030                    </lit-table>
1031                     <lit-table id="tb-so-usage" class="io-analysis" style="max-height:565px;display: none;min-height: 350px"hideDownload>
1032                        <lit-table-column width="1fr" title="Library" data-index="tableName" key="tableName" align="flex-start"order></lit-table-column>
1033                        <lit-table-column width="1fr" title="Duration" data-index="durFormat" key="durFormat" align="flex-start" order></lit-table-column>
1034                        <lit-table-column width="1fr" title="%" data-index="percent" key="percent" align="flex-start"order></lit-table-column>
1035                    </lit-table>
1036                    <lit-table id="tb-function-usage" class="io-analysis" style="max-height:565px;display: none;min-height: 350px"hideDownload>
1037                        <lit-table-column width="1fr" title="Function" data-index="tableName" key="tableName" align="flex-start"order></lit-table-column>
1038                        <lit-table-column width="1fr" title="Duration" data-index="durFormat" key="durFormat" align="flex-start" order></lit-table-column>
1039                        <lit-table-column width="1fr" title="%" data-index="percent" key="percent" align="flex-start"order></lit-table-column>
1040                    </lit-table>
1041                    </div>
1042
1043        </div>
1044`;
1045  }
1046}
1047