• 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';
17import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table';
18import { SelectionParam } from '../../../../bean/BoxSelection';
19import { Utils } from '../../base/Utils';
20import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
21import { SpSystemTrace } from '../../../SpSystemTrace';
22import { getTabPaneIOTierStatisticsData } from '../../../../database/sql/SqlLite.sql';
23
24@element('tabpane-io-tier-statistics')
25export class TabPaneIOTierStatistics extends BaseElement {
26  private ioTierStatisticsTbl: LitTable | null | undefined;
27  private ioTierStatisticsSelectionParam: SelectionParam | null | undefined;
28  private ioTierStatisticsProgressEL: LitProgressBar | null | undefined;
29  private loadingPage: unknown;
30  private loadingList: number[] = [];
31  private ioTierStatisticsSource: Array<unknown> = [];
32  private ioTierStatisticsSortKey: string = '';
33  private ioTierStatisticsSortType: number = 0;
34
35  set data(ioTierStatisticsSelection: SelectionParam | unknown) {
36    if (ioTierStatisticsSelection === this.ioTierStatisticsSelectionParam) {
37      return;
38    }
39    this.ioTierStatisticsProgressEL!.loading = true;
40    // @ts-ignore
41    this.loadingPage.style.visibility = 'visible';
42    // @ts-ignore
43    this.ioTierStatisticsSelectionParam = ioTierStatisticsSelection;
44    // @ts-ignore
45    this.ioTierStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 20
46      }px`;
47    this.queryDataByDB(ioTierStatisticsSelection);
48  }
49
50  initElements(): void {
51    this.ioTierStatisticsProgressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progress');
52    this.loadingPage = this.shadowRoot!.querySelector('.loading');
53    this.ioTierStatisticsTbl = this.shadowRoot!.querySelector<LitTable>('#tb-io-tier-statistics');
54    this.ioTierStatisticsTbl!.addEventListener('column-click', (evt) => {
55      // @ts-ignore
56      this.ioTierStatisticsSortKey = evt.detail.key;
57      // @ts-ignore
58      this.ioTierStatisticsSortType = evt.detail.sort;
59      if (this.ioTierStatisticsSortType !== 0 && this.ioTierStatisticsSource.length > 0) {
60        this.sortTable(this.ioTierStatisticsSource[0], this.ioTierStatisticsSortKey);
61      }
62      this.ioTierStatisticsTbl!.recycleDataSource = this.ioTierStatisticsSource;
63    });
64  }
65
66  connectedCallback(): void {
67    super.connectedCallback();
68    new ResizeObserver((): void => {
69      if (this.parentElement!.clientHeight !== 0) {
70        // @ts-ignore
71        this.ioTierStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 25
72          }px`;
73        this.ioTierStatisticsTbl!.reMeauseHeight();
74        // @ts-ignore
75        this.loadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`;
76      }
77    }).observe(this.parentElement!);
78  }
79
80  getInitData(initIoTierItem: unknown, nameTitle: unknown = 'pname', subtitle: unknown = null): unknown {
81    if (nameTitle === 'path') {
82      // @ts-ignore
83      initIoTierItem.path =
84        // @ts-ignore
85        initIoTierItem.path !== null ? SpSystemTrace.DATA_DICT.get(parseInt(initIoTierItem.path)) : '-';
86    }
87    return {
88      // @ts-ignore
89      ...initIoTierItem,
90      // @ts-ignore
91      title: initIoTierItem[nameTitle] + (subtitle ? `(${initIoTierItem[subtitle]})` : ''),
92      // @ts-ignore
93      allDuration: Utils.getProbablyTime(initIoTierItem.allDuration),
94      // @ts-ignore
95      minDuration: Utils.getProbablyTime(initIoTierItem.minDuration),
96      // @ts-ignore
97      maxDuration: Utils.getProbablyTime(initIoTierItem.maxDuration),
98      // @ts-ignore
99      avgDuration: Utils.getProbablyTime(initIoTierItem.avgDuration),
100      // @ts-ignore
101      node: { ...initIoTierItem, children: [] },
102    };
103  }
104
105  queryDataByDB(ioTierParam: SelectionParam | unknown): void {
106    this.loadingList.push(1);
107    this.ioTierStatisticsProgressEL!.loading = true;
108    // @ts-ignore
109    this.loadingPage.style.visibility = 'visible';
110    getTabPaneIOTierStatisticsData(
111      // @ts-ignore
112      ioTierParam.leftNs + ioTierParam.recordStartNs,
113      // @ts-ignore
114      ioTierParam.rightNs + ioTierParam.recordStartNs,
115      // @ts-ignore
116      ioTierParam.diskIOipids
117    ).then((result): void => {
118      this.loadingList.splice(0, 1);
119      if (this.loadingList.length === 0) {
120        this.ioTierStatisticsProgressEL!.loading = false;
121        // @ts-ignore
122        this.loadingPage.style.visibility = 'hidden';
123      }
124      this.sortioTierStatisticsStatus(result, 'tier', 'ipid');
125    });
126  }
127  private theadClick(res: Array<unknown>): void {
128    let labels = this.ioTierStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label');
129    if (labels) {
130      for (let i = 0; i < labels.length; i++) {
131        let label = labels[i].innerHTML;
132        labels[i].addEventListener('click', (): void => {
133          if (label.includes('Tier') && i === 0) {
134            this.ioTierStatisticsTbl!.setStatus(res, false, 0, 1);
135            this.ioTierStatisticsTbl!.recycleDs = this.ioTierStatisticsTbl!.meauseTreeRowElement(
136              res,
137              RedrawTreeForm.Retract
138            );
139          } else if (label.includes('Process') && i === 1) {
140            this.ioTierStatisticsTbl!.setStatus(res, false, 0, 2);
141            this.ioTierStatisticsTbl!.recycleDs = this.ioTierStatisticsTbl!.meauseTreeRowElement(
142              res,
143              RedrawTreeForm.Retract
144            );
145          } else if (label.includes('Path') && i === 2) {
146            this.ioTierStatisticsTbl!.setStatus(res, true);
147            this.ioTierStatisticsTbl!.recycleDs = this.ioTierStatisticsTbl!.meauseTreeRowElement(
148              res,
149              RedrawTreeForm.Expand
150            );
151          }
152        });
153      }
154    }
155  }
156
157  sortioTierStatisticsStatus(result: Array<unknown>, firstLevel: string, secondLevel: string): void {
158    let ioTierFatherMap = new Map<unknown, unknown>();
159    let ioTierChildMap = new Map<unknown, unknown>();
160    let ioTierAllNode: unknown = {
161      title: 'All',
162      count: 0,
163      allDuration: 0,
164      minDuration: 0,
165      maxDuration: 0,
166      avgDuration: '',
167      children: [],
168    };
169    result.forEach((resultItem, idx): void => {
170      this.updateIoTierChildMap(ioTierChildMap, resultItem, firstLevel, secondLevel);
171      this.updateIoTierFatherMap(ioTierFatherMap, resultItem, firstLevel);
172      if (idx === 0) {
173        // @ts-ignore
174        ioTierAllNode.minDuration = resultItem.minDuration;
175      } else {
176        // @ts-ignore
177        ioTierAllNode.minDuration =
178          // @ts-ignore
179          ioTierAllNode.minDuration <= resultItem.minDuration ? ioTierAllNode.minDuration : resultItem.minDuration;
180      } // @ts-ignore
181      ioTierAllNode.count += resultItem.count;
182      // @ts-ignore
183      ioTierAllNode.allDuration += resultItem.allDuration;
184      // @ts-ignore
185      ioTierAllNode.maxDuration =
186        // @ts-ignore
187        ioTierAllNode.maxDuration >= resultItem.maxDuration ? ioTierAllNode.maxDuration : resultItem.maxDuration;
188    });
189    this.calculateAvgDuration(ioTierFatherMap, ioTierChildMap, ioTierAllNode);
190    ioTierAllNode = this.getInitData(ioTierAllNode);
191    // @ts-ignore
192    ioTierAllNode.title = 'All';
193    // @ts-ignore
194    ioTierAllNode.path = { tier: null, pid: null, path: null, value: 'All' };
195    this.ioTierStatisticsSource = result.length > 0 ? [ioTierAllNode] : [];
196    if (this.ioTierStatisticsSortType !== 0 && result.length > 0) {
197      this.sortTable(this.ioTierStatisticsSource[0], this.ioTierStatisticsSortKey);
198    }
199    this.theadClick(this.ioTierStatisticsSource);
200    this.ioTierStatisticsTbl!.recycleDataSource = this.ioTierStatisticsSource;
201  }
202
203  private updateIoTierFatherMap(ioTierFatherMap: Map<unknown, unknown>, resultItem: unknown, firstLevel: string): void {
204    // @ts-ignore
205    if (ioTierFatherMap.has(resultItem[firstLevel])) {
206      // @ts-ignore
207      let currentFatherObject = ioTierFatherMap.get(resultItem[firstLevel]);
208      // @ts-ignore
209      currentFatherObject.count += resultItem.count;
210      // @ts-ignore
211      currentFatherObject.allDuration += resultItem.allDuration;
212      // @ts-ignore
213      currentFatherObject.minDuration =
214        // @ts-ignore
215        currentFatherObject.minDuration <= resultItem.minDuration
216          ? // @ts-ignore
217          currentFatherObject.minDuration
218          : // @ts-ignore
219          resultItem.minDuration;
220      // @ts-ignore
221      currentFatherObject.maxDuration =
222        // @ts-ignore
223        currentFatherObject.maxDuration >= resultItem.maxDuration
224          ? // @ts-ignore
225          currentFatherObject.maxDuration
226          : // @ts-ignore
227          resultItem.maxDuration;
228      // @ts-ignore
229      currentFatherObject.children.push(this.getInitData(resultItem));
230    } else {
231      // @ts-ignore
232      ioTierFatherMap.set(resultItem[firstLevel], {
233        // @ts-ignore
234        ...resultItem,
235        children: [this.getInitData(resultItem)],
236      });
237    }
238  }
239
240  private updateIoTierChildMap(
241    ioTierChildMap: Map<unknown, unknown>,
242    resultItem: unknown,
243    firstLevel: string,
244    secondLevel: string
245  ): void {
246    // @ts-ignore
247    if (ioTierChildMap.has(`${resultItem[firstLevel]}_${resultItem[secondLevel]}`)) {
248      // @ts-ignore
249      let currentChildObject = ioTierChildMap.get(`${resultItem[firstLevel]}_${resultItem[secondLevel]}`);
250      // @ts-ignore
251      currentChildObject.count += resultItem.count;
252      // @ts-ignore
253      currentChildObject.allDuration += resultItem.allDuration; // @ts-ignore
254      currentChildObject.minDuration = // @ts-ignore
255        currentChildObject.minDuration <= resultItem.minDuration // @ts-ignore
256          ? currentChildObject.minDuration // @ts-ignore
257          : resultItem.minDuration; // @ts-ignore
258      currentChildObject.maxDuration = // @ts-ignore
259        currentChildObject.maxDuration >= resultItem.maxDuration // @ts-ignore
260          ? currentChildObject.maxDuration // @ts-ignore
261          : resultItem.maxDuration; // @ts-ignore
262      currentChildObject.children.push(this.getInitData(resultItem, 'path', null));
263    } else {
264      // @ts-ignore
265      ioTierChildMap.set(`${resultItem[firstLevel]}_${resultItem[secondLevel]}`, {
266        // @ts-ignore
267        ...resultItem,
268        children: [this.getInitData(resultItem, 'path', null)],
269      });
270    }
271  }
272
273  private calculateAvgDuration(
274    ioTierFatherMap: Map<unknown, unknown>,
275    ioTierChildMap: Map<unknown, unknown>,
276    ioTierAllNode: unknown
277  ): void {
278    for (let ks of ioTierFatherMap.keys()) {
279      let sp = ioTierFatherMap.get(ks); // @ts-ignore
280      sp!.children = []; // @ts-ignore
281      sp.avgDuration = sp.allDuration / sp.count;
282      let ioTierNode = this.getInitData(sp, 'tier', null); // @ts-ignore
283      ioTierNode.path = {
284        // @ts-ignore
285        tier: ioTierNode.tier,
286        pid: null,
287        path: null, // @ts-ignore
288        value: ioTierNode.title,
289      };
290      for (let kst of ioTierChildMap.keys()) {
291        // @ts-ignore
292        if (kst.startsWith(`${ks}_`)) {
293          let spt = ioTierChildMap.get(kst); // @ts-ignore
294          spt.avgDuration = spt.allDuration / spt.count;
295          let data = this.getInitData(spt!, 'pname', 'pid'); // @ts-ignore
296          data.path = {
297            // @ts-ignore
298            tier: ioTierNode.tier, // @ts-ignore
299            pid: data.pid,
300            path: null, // @ts-ignore
301            value: `All-${ioTierNode.title}-${data.title}`,
302          }; // @ts-ignore
303          data.children.forEach((e: unknown): void => {
304            // @ts-ignore
305            e.path = {
306              // @ts-ignore
307              tier: ioTierNode.tier, // @ts-ignore
308              pid: data.pid, // @ts-ignore
309              path: e.path, // @ts-ignore
310              value: `All-${ioTierNode.title}-${data.title}-${e.title}`,
311            };
312          }); // @ts-ignore
313          sp!.children.push(data);
314        }
315      } // @ts-ignore
316      ioTierAllNode.children.push(ioTierNode);
317    }
318    // @ts-ignore
319    ioTierAllNode.avgDuration = ioTierAllNode.allDuration / ioTierAllNode.count;
320  }
321
322  sortTable(allNode: unknown, key: string): void {
323    // @ts-ignore
324    allNode.children.sort((ioTierStatNodeA: unknown, ioTierStatNodeB: unknown) => {
325      return this.ioTierStatisticsSortType === 1 ?
326        // @ts-ignore
327        ioTierStatNodeA.node[key] - ioTierStatNodeB.node[key] :
328        this.ioTierStatisticsSortType === 2 ?
329          // @ts-ignore
330          ioTierStatNodeB.node[key] - ioTierStatNodeA.node[key] : 0;
331
332    }); // @ts-ignore
333    allNode.children.forEach((item: unknown): void => {
334      // @ts-ignore
335      item.children.sort((ioTierStatItemA: unknown, ioTierStatItemB: unknown) => {
336        return this.ioTierStatisticsSortType === 1 ?
337          // @ts-ignore
338          ioTierStatItemA.node[key] - ioTierStatItemB.node[key] :
339          this.ioTierStatisticsSortType === 2 ?
340            // @ts-ignore
341            ioTierStatItemB.node[key] - ioTierStatItemA.node[key] : 0;
342      }); // @ts-ignore
343      item.children.forEach((ioTierStatItem: unknown): void => {
344        // @ts-ignore
345        ioTierStatItem.children.sort((ioTierStatItemA: unknown, ioTierStatItemB: unknown) => {
346          return this.ioTierStatisticsSortType === 1 ?
347            // @ts-ignore
348            ioTierStatItemA.node[key] - ioTierStatItemB.node[key] :
349            this.ioTierStatisticsSortType === 2 ?
350              // @ts-ignore
351              ioTierStatItemB.node[key] - ioTierStatItemA.node[key] : 0;
352        });
353      });
354    });
355  }
356
357  initHtml(): string {
358    return `
359        <style>
360        .io-tier-stat-progress{
361            bottom: 5px;
362            position: absolute;
363            height: 1px;
364            left: 0;
365            right: 0;
366        }
367        :host{
368            padding: 10px 10px 0 10px;
369            display: flex;
370            flex-direction: column;
371        }
372        .io-tier-stat-loading{
373            bottom: 0;
374            position: absolute;
375            left: 0;
376            right: 0;
377            width:100%;
378            background:transparent;
379            z-index: 999999;
380        }
381        </style>
382        <lit-table id="tb-io-tier-statistics" style="height: auto" tree>
383            <lit-table-column class="io-tier-stat-column" width="20%" title="Tier/Process/Path" data-index="title" key="title" align="flex-start"retract>
384            </lit-table-column>
385            <lit-table-column class="io-tier-stat-column" width="1fr" title="Count" data-index="count" key="count" align="flex-start" order>
386            </lit-table-column>
387            <lit-table-column class="io-tier-stat-column" width="1fr" title="Total Latency" data-index="allDuration" key="allDuration" align="flex-start" order>
388            </lit-table-column>
389            <lit-table-column class="io-tier-stat-column" width="1fr" title="Min Total Latency" data-index="minDuration" key="minDuration" align="flex-start" order>
390            </lit-table-column>
391            <lit-table-column class="io-tier-stat-column" width="1fr" title="Avg Total Latency" data-index="avgDuration" key="avgDuration" align="flex-start" order>
392            </lit-table-column>
393            <lit-table-column class="io-tier-stat-column" width="1fr" title="Max Total Latency" data-index="maxDuration" key="maxDuration" align="flex-start" order>
394            </lit-table-column>
395        </lit-table>
396        <lit-progress-bar class="progress io-tier-stat-progress"></lit-progress-bar>
397        <div class="loading io-tier-stat-loading"></div>
398        `;
399  }
400}
401