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