• 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 {SelectionParam} from "../../../../bean/BoxSelection.js";
19import {
20    getTabPaneIOTierStatisticsData,
21} from "../../../../database/SqlLite.js";
22import {Utils} from "../../base/Utils.js";
23import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js";
24import {TabPaneFilter} from "../TabPaneFilter.js";
25
26@element('tabpane-io-tier-statistics')
27export class TabPaneIOTierStatistics extends BaseElement {
28    private tbl: LitTable | null | undefined;
29    private range: HTMLLabelElement | null | undefined;
30    private loadDataInCache: boolean = true;
31    private selectionParam:SelectionParam | null | undefined;
32    private progressEL:LitProgressBar | null | undefined;
33    private filter: TabPaneFilter | null | undefined;
34    private loadingPage:any;
35    private loadingList:number[] = [];
36    private source: Array<any> = [];
37    private typeList: Array<string> = ["OPEN", "CLOSE", "READ" , "WRITE"];
38    private sortKey: string = "";
39    private sortType: number = 0;
40    private resultData: Array<any> = [];
41
42    set data(val: SelectionParam | any) {
43        if(val == this.selectionParam){
44            return;
45        }
46        this.progressEL!.loading = true
47        this.loadingPage.style.visibility = "visible"
48        this.selectionParam = val;
49        // @ts-ignore
50        this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 20) + "px"
51        this.queryDataByDB(val)
52    }
53
54    initElements(): void {
55        this.progressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progress')
56        this.loadingPage = this.shadowRoot!.querySelector('.loading');
57        this.tbl = this.shadowRoot!.querySelector<LitTable>('#tb-states');
58        this.tbl!.addEventListener('column-click', (evt) => {
59            // @ts-ignore
60            this.sortKey = evt.detail.key
61            // @ts-ignore
62            this.sortType = evt.detail.sort;
63
64            let newSource = JSON.parse(JSON.stringify(this.source));
65            if (this.sortType != 0 && newSource.length > 0) this.sortTable(newSource[0],this.sortKey);
66            this.tbl!.recycleDataSource = newSource;
67        })
68    }
69
70    connectedCallback() {
71        super.connectedCallback();
72        new ResizeObserver((entries) => {
73            if (this.parentElement!.clientHeight != 0) {
74                // @ts-ignore
75                this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 25) + "px"
76                this.tbl!.reMeauseHeight()
77                this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px"
78            }
79        }).observe(this.parentElement!);
80    }
81
82    getInitData(item:any,nameTitle:any = "pname",subtitle:any = null){
83        return {
84            ...item,
85            title : item[nameTitle]+(subtitle?("("+item[subtitle]+")"):""),
86            allDuration : Utils.getProbablyTime(item.allDuration),
87            minDuration : Utils.getProbablyTime(item.minDuration),
88            maxDuration : Utils.getProbablyTime(item.maxDuration),
89            avgDuration : Utils.getProbablyTime(item.avgDuration),
90            node:{...item,children:[]},
91        }
92    }
93
94    queryDataByDB(val: SelectionParam | any) {
95        this.loadingList.push(1)
96        this.progressEL!.loading = true
97        this.loadingPage.style.visibility = "visible";
98        getTabPaneIOTierStatisticsData(val.leftNs + val.recordStartNs,val.rightNs + val.recordStartNs,val.diskIOipids).then(result => {
99            this.loadingList.splice(0,1)
100            if(this.loadingList.length == 0) {
101                this.progressEL!.loading = false
102                this.loadingPage.style.visibility = "hidden"
103            }
104            this.resultData = JSON.parse(JSON.stringify(result));
105            this.sortStatus(result,"tier","ipid")
106        })
107    }
108
109    sortStatus(result:Array<any>,firstLevel:string,secondLevel:string){
110        let fatherMap = new Map<any,any>();
111        let childMap = new Map<any,any>();
112        let allNode:any = {
113            title:"All",
114            count:0,
115            allDuration:0,
116            minDuration:0,
117            maxDuration:0,
118            avgDuration:"",
119            children:[],
120        };
121        result.forEach((item,idx)=>{
122            if (childMap.has(item[firstLevel]+"_"+item[secondLevel])) {
123                let obj1 = childMap.get(item[firstLevel]+"_"+item[secondLevel]);
124                obj1.count += item.count;
125                obj1.allDuration += item.allDuration;
126                obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration;
127                obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration;
128                obj1.children.push(this.getInitData(item,"path",null));
129            }else {
130                childMap.set(item[firstLevel]+"_"+item[secondLevel],{
131                    ...item,
132                    children:[this.getInitData(item,"path",null)]
133                })
134            }
135
136            if (fatherMap.has(item[firstLevel])) {
137                let obj1 = fatherMap.get(item[firstLevel]);
138                obj1.count += item.count;
139                obj1.allDuration += item.allDuration;
140                obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration;
141                obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration;
142                obj1.children.push(this.getInitData(item));
143            }else {
144                fatherMap.set(item[firstLevel],{
145                    ...item,
146                    children:[this.getInitData(item)]
147                })
148            }
149            if (idx == 0) {
150                allNode.minDuration = item.minDuration;
151            }else {
152                allNode.minDuration = allNode.minDuration<=item.minDuration?allNode.minDuration:item.minDuration;
153            }
154            allNode.count += item.count;
155            allNode.allDuration += item.allDuration;
156            allNode.maxDuration = allNode.maxDuration>=item.maxDuration?allNode.maxDuration:item.maxDuration;
157        })
158
159        for (let ks of fatherMap.keys()) {
160            let sp = fatherMap.get(ks)
161            sp!.children = [];
162            sp.avgDuration = sp.allDuration/sp.count;
163            let node = this.getInitData(sp,"tier",null);
164            node.path = {tier:node.tier,pid:null,path:null,value:node.title}
165            for (let kst of childMap.keys()) {
166                if (kst.startsWith(ks + "_")) {
167                    let spt = childMap.get(kst)
168                    let data = this.getInitData(spt!,"pname","pid")
169                    data.path = {tier:node.tier,pid:data.pid,path:null,value:"All-"+node.title+"-"+data.title}
170                    data.children.forEach((e:any)=>{
171                        e.path = {tier:node.tier,pid:data.pid,path:e.pid,value:"All-"+node.title+"-"+data.title+"-"+e.title}
172                    })
173                    sp!.children.push(data);
174                }
175            }
176            allNode.children.push(node)
177        }
178
179        allNode.avgDuration = allNode.allDuration/allNode.count;
180        allNode = this.getInitData(allNode);
181        allNode.title = "All";
182        allNode.path = {tier:null,pid:null,path:null,value:"All"}
183        this.source = result.length > 0 ? [allNode] : [];
184        let newSource = JSON.parse(JSON.stringify(this.source));
185        if (this.sortType != 0 && result.length > 0) this.sortTable(newSource[0],this.sortKey);
186        this.tbl!.recycleDataSource = newSource;
187    }
188
189    sortTable(allNode:any,key:string){
190        allNode.children.sort((a:any, b:any) => {
191            if (this.sortType == 1) {
192                return a.node[key] - b.node[key]
193            }else if (this.sortType == 2) {
194                return b.node[key] - a.node[key]
195            }
196        });
197        allNode.children.forEach((item:any)=>{
198            item.children.sort((a:any, b:any) => {
199                if (this.sortType == 1) {
200                    return a.node[key] - b.node[key]
201                }else if (this.sortType == 2) {
202                    return b.node[key] - a.node[key]
203                }
204            })
205            item.children.forEach((i:any)=>{
206                i.children.sort((a:any, b:any) => {
207                    if (this.sortType == 1) {
208                        return a.node[key] - b.node[key]
209                    }else if (this.sortType == 2) {
210                        return b.node[key] - a.node[key]
211                    }
212                })
213            });
214        });
215    }
216
217    initHtml(): string {
218        return `
219        <style>
220        :host{
221            display: flex;
222            flex-direction: column;
223            padding: 10px 10px 0 10px;
224        }
225        .progress{
226            bottom: 5px;
227            position: absolute;
228            height: 1px;
229            left: 0;
230            right: 0;
231        }
232        .loading{
233            bottom: 0;
234            position: absolute;
235            left: 0;
236            right: 0;
237            width:100%;
238            background:transparent;
239            z-index: 999999;
240        }
241        </style>
242        <lit-table id="tb-states" style="height: auto" tree>
243            <lit-table-column width="20%" title="Tier/Process/Path" data-index="title" key="title" align="flex-start">
244            </lit-table-column>
245            <lit-table-column width="1fr" title="Count" data-index="count" key="count" align="flex-start" order>
246            </lit-table-column>
247            <lit-table-column width="1fr" title="Total Latency" data-index="allDuration" key="allDuration" align="flex-start" order>
248            </lit-table-column>
249            <lit-table-column width="1fr" title="Min Total Latency" data-index="minDuration" key="minDuration" align="flex-start" order>
250            </lit-table-column>
251            <lit-table-column width="1fr" title="Avg Total Latency" data-index="avgDuration" key="avgDuration" align="flex-start" order>
252            </lit-table-column>
253            <lit-table-column width="1fr" title="Max Total Latency" data-index="maxDuration" key="maxDuration" align="flex-start" order>
254            </lit-table-column>
255        </lit-table>
256        <lit-progress-bar class="progress"></lit-progress-bar>
257        <div class="loading"></div>
258        `;
259    }
260}
261