• 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 } 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: any;
30  private loadingList: number[] = [];
31  private ioTierStatisticsSource: Array<any> = [];
32  private ioTierStatisticsSortKey: string = '';
33  private ioTierStatisticsSortType: number = 0;
34  private ioTierStatisticsResultData: Array<any> = [];
35
36  set data(ioTierStatisticsSelection: SelectionParam | any) {
37    if (ioTierStatisticsSelection == this.ioTierStatisticsSelectionParam) {
38      return;
39    }
40    this.ioTierStatisticsProgressEL!.loading = true;
41    this.loadingPage.style.visibility = 'visible';
42    this.ioTierStatisticsSelectionParam = ioTierStatisticsSelection;
43    // @ts-ignore
44    this.ioTierStatisticsTbl!.shadowRoot!.querySelector('.table').style.height =
45      this.parentElement!.clientHeight - 20 + 'px';
46    this.queryDataByDB(ioTierStatisticsSelection);
47  }
48
49  initElements(): void {
50    this.ioTierStatisticsProgressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progress');
51    this.loadingPage = this.shadowRoot!.querySelector('.loading');
52    this.ioTierStatisticsTbl = this.shadowRoot!.querySelector<LitTable>('#tb-io-tier-statistics');
53    this.ioTierStatisticsTbl!.addEventListener('column-click', (evt) => {
54      // @ts-ignore
55      this.ioTierStatisticsSortKey = evt.detail.key;
56      // @ts-ignore
57      this.ioTierStatisticsSortType = evt.detail.sort;
58
59      let newSource = JSON.parse(JSON.stringify(this.ioTierStatisticsSource));
60      if (this.ioTierStatisticsSortType != 0 && newSource.length > 0)
61        this.sortTable(newSource[0], this.ioTierStatisticsSortKey);
62      this.ioTierStatisticsTbl!.recycleDataSource = newSource;
63    });
64  }
65
66  connectedCallback() {
67    super.connectedCallback();
68    new ResizeObserver((entries) => {
69      if (this.parentElement!.clientHeight != 0) {
70        // @ts-ignore
71        this.ioTierStatisticsTbl!.shadowRoot!.querySelector('.table').style.height =
72          this.parentElement!.clientHeight - 25 + 'px';
73        this.ioTierStatisticsTbl!.reMeauseHeight();
74        this.loadingPage.style.height = this.parentElement!.clientHeight - 24 + 'px';
75      }
76    }).observe(this.parentElement!);
77  }
78
79  getInitData(initIoTierItem: any, nameTitle: any = 'pname', subtitle: any = null) {
80    if (nameTitle == 'path') {
81      initIoTierItem.path =
82        initIoTierItem.path != null ? SpSystemTrace.DATA_DICT.get(parseInt(initIoTierItem.path)) : '-';
83    }
84    return {
85      ...initIoTierItem,
86      title: initIoTierItem[nameTitle] + (subtitle ? '(' + initIoTierItem[subtitle] + ')' : ''),
87      allDuration: Utils.getProbablyTime(initIoTierItem.allDuration),
88      minDuration: Utils.getProbablyTime(initIoTierItem.minDuration),
89      maxDuration: Utils.getProbablyTime(initIoTierItem.maxDuration),
90      avgDuration: Utils.getProbablyTime(initIoTierItem.avgDuration),
91      node: { ...initIoTierItem, children: [] },
92    };
93  }
94
95  queryDataByDB(ioTierParam: SelectionParam | any) {
96    this.loadingList.push(1);
97    this.ioTierStatisticsProgressEL!.loading = true;
98    this.loadingPage.style.visibility = 'visible';
99    getTabPaneIOTierStatisticsData(
100      ioTierParam.leftNs + ioTierParam.recordStartNs,
101      ioTierParam.rightNs + ioTierParam.recordStartNs,
102      ioTierParam.diskIOipids
103    ).then((result) => {
104      this.loadingList.splice(0, 1);
105      if (this.loadingList.length == 0) {
106        this.ioTierStatisticsProgressEL!.loading = false;
107        this.loadingPage.style.visibility = 'hidden';
108      }
109      this.ioTierStatisticsResultData = JSON.parse(JSON.stringify(result));
110      this.sortioTierStatisticsStatus(result, 'tier', 'ipid');
111    });
112  }
113
114  sortioTierStatisticsStatus(result: Array<any>, firstLevel: string, secondLevel: string) {
115    let ioTierFatherMap = new Map<any, any>();
116    let ioTierChildMap = new Map<any, any>();
117    let ioTierAllNode: any = {
118      title: 'All',
119      count: 0,
120      allDuration: 0,
121      minDuration: 0,
122      maxDuration: 0,
123      avgDuration: '',
124      children: [],
125    };
126    result.forEach((resultItem, idx) => {
127      this.updateIoTierChildMap(ioTierChildMap, resultItem, firstLevel, secondLevel);
128      this.updateIoTierFatherMap(ioTierFatherMap, resultItem, firstLevel);
129      if (idx == 0) {
130        ioTierAllNode.minDuration = resultItem.minDuration;
131      } else {
132        ioTierAllNode.minDuration =
133          ioTierAllNode.minDuration <= resultItem.minDuration ? ioTierAllNode.minDuration : resultItem.minDuration;
134      }
135      ioTierAllNode.count += resultItem.count;
136      ioTierAllNode.allDuration += resultItem.allDuration;
137      ioTierAllNode.maxDuration =
138        ioTierAllNode.maxDuration >= resultItem.maxDuration ? ioTierAllNode.maxDuration : resultItem.maxDuration;
139    });
140    this.calculateAvgDuration(ioTierFatherMap, ioTierChildMap, ioTierAllNode);
141    ioTierAllNode = this.getInitData(ioTierAllNode);
142    ioTierAllNode.title = 'All';
143    ioTierAllNode.path = {tier: null, pid: null, path: null, value: 'All'};
144    this.ioTierStatisticsSource = result.length > 0 ? [ioTierAllNode] : [];
145    let newSource = JSON.parse(JSON.stringify(this.ioTierStatisticsSource));
146    if (this.ioTierStatisticsSortType != 0 && result.length > 0)
147      this.sortTable(newSource[0], this.ioTierStatisticsSortKey);
148    this.ioTierStatisticsTbl!.recycleDataSource = newSource;
149  }
150
151  private updateIoTierFatherMap(ioTierFatherMap: Map<any, any>, resultItem: any, firstLevel: string): void {
152    if (ioTierFatherMap.has(resultItem[firstLevel])) {
153      let currentFatherObject = ioTierFatherMap.get(resultItem[firstLevel]);
154      currentFatherObject.count += resultItem.count;
155      currentFatherObject.allDuration += resultItem.allDuration;
156      currentFatherObject.minDuration =
157        currentFatherObject.minDuration <= resultItem.minDuration
158          ? currentFatherObject.minDuration
159          : resultItem.minDuration;
160      currentFatherObject.maxDuration =
161        currentFatherObject.maxDuration >= resultItem.maxDuration
162          ? currentFatherObject.maxDuration
163          : resultItem.maxDuration;
164      currentFatherObject.children.push(this.getInitData(resultItem));
165    } else {
166      ioTierFatherMap.set(resultItem[firstLevel], {
167        ...resultItem,
168        children: [this.getInitData(resultItem)],
169      });
170    }
171  }
172
173  private updateIoTierChildMap(ioTierChildMap: Map<any, any>, resultItem: any, firstLevel: string,
174                               secondLevel: string): void {
175    if (ioTierChildMap.has(resultItem[firstLevel] + '_' + resultItem[secondLevel])) {
176      let currentChildObject = ioTierChildMap.get(resultItem[firstLevel] + '_' + resultItem[secondLevel]);
177      currentChildObject.count += resultItem.count;
178      currentChildObject.allDuration += resultItem.allDuration;
179      currentChildObject.minDuration =
180        currentChildObject.minDuration <= resultItem.minDuration
181          ? currentChildObject.minDuration
182          : resultItem.minDuration;
183      currentChildObject.maxDuration =
184        currentChildObject.maxDuration >= resultItem.maxDuration
185          ? currentChildObject.maxDuration
186          : resultItem.maxDuration;
187      currentChildObject.children.push(this.getInitData(resultItem, 'path', null));
188    } else {
189      ioTierChildMap.set(resultItem[firstLevel] + '_' + resultItem[secondLevel], {
190        ...resultItem,
191        children: [this.getInitData(resultItem, 'path', null)],
192      });
193    }
194  }
195
196  private calculateAvgDuration(ioTierFatherMap: Map<any, any>, ioTierChildMap: Map<any, any>, ioTierAllNode: any): void {
197    for (let ks of ioTierFatherMap.keys()) {
198      let sp = ioTierFatherMap.get(ks);
199      sp!.children = [];
200      sp.avgDuration = sp.allDuration / sp.count;
201      let ioTierNode = this.getInitData(sp, 'tier', null);
202      ioTierNode.path = {
203        tier: ioTierNode.tier,
204        pid: null,
205        path: null,
206        value: ioTierNode.title,
207      };
208      for (let kst of ioTierChildMap.keys()) {
209        if (kst.startsWith(ks + '_')) {
210          let spt = ioTierChildMap.get(kst);
211          let data = this.getInitData(spt!, 'pname', 'pid');
212          data.path = {
213            tier: ioTierNode.tier,
214            pid: data.pid,
215            path: null,
216            value: 'All-' + ioTierNode.title + '-' + data.title,
217          };
218          data.children.forEach((e: any) => {
219            e.path = {
220              tier: ioTierNode.tier,
221              pid: data.pid,
222              path: e.path,
223              value: 'All-' + ioTierNode.title + '-' + data.title + '-' + e.title,
224            };
225          });
226          sp!.children.push(data);
227        }
228      }
229      ioTierAllNode.children.push(ioTierNode);
230    }
231
232    ioTierAllNode.avgDuration = ioTierAllNode.allDuration / ioTierAllNode.count;
233  }
234
235  sortTable(allNode: any, key: string) {
236    allNode.children.sort((ioTierStatNodeA: any, ioTierStatNodeB: any) => {
237      if (this.ioTierStatisticsSortType == 1) {
238        return ioTierStatNodeA.node[key] - ioTierStatNodeB.node[key];
239      } else if (this.ioTierStatisticsSortType == 2) {
240        return ioTierStatNodeB.node[key] - ioTierStatNodeA.node[key];
241      }
242    });
243    allNode.children.forEach((item: any) => {
244      item.children.sort((ioTierStatItemA: any, ioTierStatItemB: any) => {
245        if (this.ioTierStatisticsSortType == 1) {
246          return ioTierStatItemA.node[key] - ioTierStatItemB.node[key];
247        } else if (this.ioTierStatisticsSortType == 2) {
248          return ioTierStatItemB.node[key] - ioTierStatItemA.node[key];
249        }
250      });
251      item.children.forEach((ioTierStatItem: any) => {
252        ioTierStatItem.children.sort((ioTierStatItemA: any, ioTierStatItemB: any) => {
253          if (this.ioTierStatisticsSortType == 1) {
254            return ioTierStatItemA.node[key] - ioTierStatItemB.node[key];
255          } else if (this.ioTierStatisticsSortType == 2) {
256            return ioTierStatItemB.node[key] - ioTierStatItemA.node[key];
257          }
258        });
259      });
260    });
261  }
262
263  initHtml(): string {
264    return `
265        <style>
266        .io-tier-stat-progress{
267            bottom: 5px;
268            position: absolute;
269            height: 1px;
270            left: 0;
271            right: 0;
272        }
273        :host{
274            padding: 10px 10px 0 10px;
275            display: flex;
276            flex-direction: column;
277        }
278        .io-tier-stat-loading{
279            bottom: 0;
280            position: absolute;
281            left: 0;
282            right: 0;
283            width:100%;
284            background:transparent;
285            z-index: 999999;
286        }
287        </style>
288        <lit-table id="tb-io-tier-statistics" style="height: auto" tree>
289            <lit-table-column class="io-tier-stat-column" width="20%" title="Tier/Process/Path" data-index="title" key="title" align="flex-start"retract>
290            </lit-table-column>
291            <lit-table-column class="io-tier-stat-column" width="1fr" title="Count" data-index="count" key="count" align="flex-start" order>
292            </lit-table-column>
293            <lit-table-column class="io-tier-stat-column" width="1fr" title="Total Latency" data-index="allDuration" key="allDuration" align="flex-start" order>
294            </lit-table-column>
295            <lit-table-column class="io-tier-stat-column" width="1fr" title="Min Total Latency" data-index="minDuration" key="minDuration" align="flex-start" order>
296            </lit-table-column>
297            <lit-table-column class="io-tier-stat-column" width="1fr" title="Avg Total Latency" data-index="avgDuration" key="avgDuration" align="flex-start" order>
298            </lit-table-column>
299            <lit-table-column class="io-tier-stat-column" width="1fr" title="Max Total Latency" data-index="maxDuration" key="maxDuration" align="flex-start" order>
300            </lit-table-column>
301        </lit-table>
302        <lit-progress-bar class="progress io-tier-stat-progress"></lit-progress-bar>
303        <div class="loading io-tier-stat-loading"></div>
304        `;
305  }
306}
307