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 { getTabPaneFilesystemStatistics } from '../../../../database/sql/SqlLite.sql'; 22 23@element('tabpane-file-statistics') 24export class TabPaneFileStatistics extends BaseElement { 25 private fileStatisticsTbl: LitTable | null | undefined; 26 private selectionParam: SelectionParam | null | undefined; 27 private fileStatisticsProgressEL: LitProgressBar | null | undefined; 28 private fileStatisticsLoadingPage: unknown; 29 private fileStatisticsLoadingList: number[] = []; 30 private fileStatisticsSource: Array<unknown> = []; 31 private typeList: Array<string> = ['OPEN', 'CLOSE', 'READ', 'WRITE']; 32 private fileStatisticsSortKey: string = ''; 33 private fileStatisticsSortType: number = 0; 34 35 set data(fileStatisticsSelection: SelectionParam | unknown) { 36 if (fileStatisticsSelection === this.selectionParam) { 37 return; 38 } 39 this.fileStatisticsProgressEL!.loading = true; // @ts-ignore 40 this.fileStatisticsLoadingPage.style.visibility = 'visible'; // @ts-ignore 41 this.selectionParam = fileStatisticsSelection; 42 // @ts-ignore 43 this.fileStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 25 44 }px`; 45 this.queryDataByDB(fileStatisticsSelection); 46 } 47 48 initElements(): void { 49 this.fileStatisticsProgressEL = this.shadowRoot!.querySelector<LitProgressBar>('.file-statistics-progress'); 50 this.fileStatisticsLoadingPage = this.shadowRoot!.querySelector('.file-statistics-loading'); 51 this.fileStatisticsTbl = this.shadowRoot!.querySelector<LitTable>('#tb-file-statistics'); 52 this.fileStatisticsTbl!.addEventListener('column-click', (evt: Event): void => { 53 // @ts-ignore 54 this.fileStatisticsSortKey = evt.detail.key; 55 // @ts-ignore 56 this.fileStatisticsSortType = evt.detail.sort; 57 if (this.fileStatisticsSortType !== 0 && this.fileStatisticsSource.length > 0) { 58 this.sortTable(this.fileStatisticsSource[0], this.fileStatisticsSortKey); 59 } 60 this.fileStatisticsTbl!.recycleDataSource = this.fileStatisticsSource; 61 }); 62 } 63 64 connectedCallback(): void { 65 super.connectedCallback(); 66 new ResizeObserver((): void => { 67 if (this.parentElement!.clientHeight !== 0) { 68 // @ts-ignore 69 this.fileStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 25 70 }px`; 71 this.fileStatisticsTbl!.reMeauseHeight(); // @ts-ignore 72 this.fileStatisticsLoadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`; 73 } 74 }).observe(this.parentElement!); 75 } 76 77 getInitData(item: unknown): unknown { 78 return { 79 // @ts-ignore 80 ...item, // @ts-ignore 81 title: `${item.name}(${item.pid})`, // @ts-ignore 82 logicalWrites: Utils.getBinaryByteWithUnit(item.logicalWrites), // @ts-ignore 83 logicalReads: Utils.getBinaryByteWithUnit(item.logicalReads), // @ts-ignore 84 otherFile: Utils.getBinaryByteWithUnit(item.otherFile), // @ts-ignore 85 allDuration: Utils.getProbablyTime(item.allDuration), // @ts-ignore 86 minDuration: Utils.getProbablyTime(item.minDuration), // @ts-ignore 87 maxDuration: Utils.getProbablyTime(item.maxDuration), // @ts-ignore 88 avgDuration: Utils.getProbablyTime(item.avgDuration), // @ts-ignore 89 node: { ...item, children: [] }, 90 }; 91 } 92 93 queryDataByDB(val: SelectionParam | unknown): void { 94 this.fileStatisticsLoadingList.push(1); 95 this.fileStatisticsProgressEL!.loading = true; // @ts-ignore 96 this.fileStatisticsLoadingPage.style.visibility = 'visible'; 97 getTabPaneFilesystemStatistics( 98 // @ts-ignore 99 val.leftNs + val.recordStartNs, // @ts-ignore 100 val.rightNs + val.recordStartNs, // @ts-ignore 101 val.fileSystemType 102 ).then((result): void => { 103 this.fileStatisticsLoadingList.splice(0, 1); 104 if (this.fileStatisticsLoadingList.length === 0) { 105 this.fileStatisticsProgressEL!.loading = false; // @ts-ignore 106 this.fileStatisticsLoadingPage.style.visibility = 'hidden'; 107 } 108 let fileStatisticsFatherMap = new Map<unknown, unknown>(); 109 let fileStatisticsAllNode: unknown = { 110 title: 'All', 111 count: 0, 112 logicalReads: 0, 113 logicalWrites: 0, 114 otherFile: 0, 115 allDuration: 0, 116 minDuration: 0, 117 maxDuration: 0, 118 avgDuration: '', 119 children: [], 120 }; 121 this.handleResult(result, fileStatisticsFatherMap, fileStatisticsAllNode); 122 fileStatisticsFatherMap.forEach((item): void => { 123 // @ts-ignore 124 item.avgDuration = item.allDuration / item.count; 125 let node = this.getInitData(item); // @ts-ignore 126 if (item.type < 4) { 127 // @ts-ignore 128 node.title = this.typeList[item.type]; 129 } else { 130 // @ts-ignore 131 node.title = item.type; 132 } // @ts-ignore 133 fileStatisticsAllNode.children.push(node); 134 }); // @ts-ignore 135 fileStatisticsAllNode.avgDuration = fileStatisticsAllNode.allDuration / fileStatisticsAllNode.count; 136 fileStatisticsAllNode = this.getInitData(fileStatisticsAllNode); // @ts-ignore 137 fileStatisticsAllNode.title = 'All'; 138 this.fileStatisticsSource = result.length > 0 ? [fileStatisticsAllNode] : []; 139 if (this.fileStatisticsSortType !== 0 && result.length > 0) { 140 this.sortTable(this.fileStatisticsSource[0], this.fileStatisticsSortKey); 141 } 142 this.theadClick(this.fileStatisticsSource); 143 this.fileStatisticsTbl!.recycleDataSource = this.fileStatisticsSource; 144 }); 145 } 146 private theadClick(res: Array<unknown>): void { 147 let labels = this.fileStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); 148 if (labels) { 149 for (let i = 0; i < labels.length; i++) { 150 let label = labels[i].innerHTML; 151 labels[i].addEventListener('click', (): void => { 152 if (label.includes('Syscall') && i === 0) { 153 this.fileStatisticsTbl!.setStatus(res, false, 0, 1); 154 this.fileStatisticsTbl!.recycleDs = this.fileStatisticsTbl!.meauseTreeRowElement( 155 res, 156 RedrawTreeForm.Retract 157 ); 158 } else if (label.includes('Process') && i === 1) { 159 this.fileStatisticsTbl!.setStatus(res, true); 160 this.fileStatisticsTbl!.recycleDs = this.fileStatisticsTbl!.meauseTreeRowElement( 161 res, 162 RedrawTreeForm.Retract 163 ); 164 } 165 }); 166 } 167 } 168 } 169 170 private handleResult( 171 result: Array<unknown>, 172 fileStatisticsFatherMap: Map<unknown, unknown>, 173 fileStatisticsAllNode: unknown 174 ): void { 175 result.forEach((item, idx): void => { 176 // @ts-ignore 177 if (fileStatisticsFatherMap.has(item.type)) { 178 // @ts-ignore 179 let fileStatisticsObj = fileStatisticsFatherMap.get(item.type); // @ts-ignore 180 fileStatisticsObj.count += item.count; // @ts-ignore 181 fileStatisticsObj.logicalReads += item.logicalReads; // @ts-ignore 182 fileStatisticsObj.logicalWrites += item.logicalWrites; // @ts-ignore 183 fileStatisticsObj.otherFile += item.otherFile; // @ts-ignore 184 fileStatisticsObj.allDuration += item.allDuration; // @ts-ignore 185 fileStatisticsObj.minDuration = // @ts-ignore 186 fileStatisticsObj.minDuration <= item.minDuration ? fileStatisticsObj.minDuration : item.minDuration; // @ts-ignore 187 fileStatisticsObj.maxDuration = // @ts-ignore 188 fileStatisticsObj.maxDuration >= item.maxDuration ? fileStatisticsObj.maxDuration : item.maxDuration; // @ts-ignore 189 fileStatisticsObj.children.push(this.getInitData(item)); 190 } else { 191 // @ts-ignore 192 fileStatisticsFatherMap.set(item.type, { 193 // @ts-ignore 194 type: item.type, // @ts-ignore 195 count: item.count, // @ts-ignore 196 logicalReads: item.logicalReads, // @ts-ignore 197 logicalWrites: item.logicalWrites, // @ts-ignore 198 otherFile: item.otherFile, // @ts-ignore 199 allDuration: item.allDuration, // @ts-ignore 200 minDuration: item.minDuration, // @ts-ignore 201 maxDuration: item.maxDuration, // @ts-ignore 202 children: [this.getInitData(item)], 203 }); 204 } 205 if (idx === 0) { 206 // @ts-ignore 207 fileStatisticsAllNode.minDuration = item.minDuration; 208 } else { 209 // @ts-ignore 210 fileStatisticsAllNode.minDuration = // @ts-ignore 211 fileStatisticsAllNode.minDuration <= item.minDuration ? fileStatisticsAllNode.minDuration : item.minDuration; 212 } // @ts-ignore 213 fileStatisticsAllNode.count += item.count; // @ts-ignore 214 fileStatisticsAllNode.logicalReads += item.logicalReads; // @ts-ignore 215 fileStatisticsAllNode.logicalWrites += item.logicalWrites; // @ts-ignore 216 fileStatisticsAllNode.otherFile += item.otherFile; // @ts-ignore 217 fileStatisticsAllNode.allDuration += item.allDuration; // @ts-ignore 218 fileStatisticsAllNode.maxDuration = // @ts-ignore 219 fileStatisticsAllNode.maxDuration >= item.maxDuration ? fileStatisticsAllNode.maxDuration : item.maxDuration; 220 }); 221 } 222 223 sortTable(fileStatisticsAllNode: unknown, key: string): void { 224 // @ts-ignore 225 fileStatisticsAllNode.children.sort((fileStatisticsA: unknown, fileStatisticsB: unknown) => { 226 return this.fileStatisticsSortType === 1 ? 227 // @ts-ignore 228 fileStatisticsA.node[key] - fileStatisticsB.node[key] : 229 this.fileStatisticsSortType === 2 ? 230 // @ts-ignore 231 fileStatisticsB.node[key] - fileStatisticsA.node[key] : 0; 232 }); // @ts-ignore 233 fileStatisticsAllNode.children.forEach((item: unknown): void => { 234 // @ts-ignore 235 item.children.sort((fileStatisticsA: unknown, fileStatisticsB: unknown) => { 236 return this.fileStatisticsSortType === 1 ? 237 // @ts-ignore 238 fileStatisticsA.node[key] - fileStatisticsB.node[key] : 239 this.fileStatisticsSortType === 2 ? 240 // @ts-ignore 241 fileStatisticsB.node[key] - fileStatisticsA.node[key] : 0; 242 }); 243 }); 244 } 245 246 initHtml(): string { 247 return ` 248 <style> 249 :host{ 250 display: flex; 251 flex-direction: column; 252 padding: 10px 10px; 253 } 254 .file-statistics-progress{ 255 bottom: 5px; 256 position: absolute; 257 height: 1px; 258 left: 0; 259 right: 0; 260 } 261 .file-statistics-loading{ 262 bottom: 0; 263 position: absolute; 264 left: 0; 265 right: 0; 266 width:100%; 267 background:transparent; 268 z-index: 999999; 269 } 270 </style> 271 <lit-table id="tb-file-statistics" style="height: auto" tree> 272 <lit-table-column class="fs-stat-column" width="20%" title="Syscall/Process" data-index="title" key="title" align="flex-start" retract> 273 </lit-table-column> 274 <lit-table-column class="fs-stat-column" width="1fr" title="Count" data-index="count" key="count" align="flex-start" order> 275 </lit-table-column> 276 <lit-table-column class="fs-stat-column" width="1fr" title="Logical Writes" data-index="logicalWrites" key="logicalWrites" align="flex-start" order> 277 </lit-table-column> 278 <lit-table-column class="fs-stat-column" width="1fr" title="Logical Reads" data-index="logicalReads" key="logicalReads" align="flex-start" order> 279 </lit-table-column> 280 <lit-table-column class="fs-stat-column" width="1fr" title="Other Filesystem Bytes" data-index="otherFile" key="otherFile" align="flex-start" order> 281 </lit-table-column> 282 <lit-table-column class="fs-stat-column" width="1fr" title="Duration" data-index="allDuration" key="allDuration" align="flex-start" order> 283 </lit-table-column> 284 <lit-table-column class="fs-stat-column" width="1fr" title="Min Duration" data-index="minDuration" key="minDuration" align="flex-start" order> 285 </lit-table-column> 286 <lit-table-column class="fs-stat-column" width="1fr" title="Avg Duration" data-index="avgDuration" key="avgDuration" align="flex-start" order> 287 </lit-table-column> 288 <lit-table-column class="fs-stat-column" width="1fr" title="Max Duration" data-index="maxDuration" key="maxDuration" align="flex-start" order> 289 </lit-table-column> 290 </lit-table> 291 <lit-progress-bar class="file-statistics-progress"></lit-progress-bar> 292 <div class="file-statistics-loading"></div> 293 `; 294 } 295} 296