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 { SpSchedulingAnalysis } from './SpSchedulingAnalysis'; 18import { DrawerCpuTabs } from './DrawerCpuTabs'; 19import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie'; 20import { LitDrawer } from '../../../base-ui/drawer/LitDrawer'; 21import '../../../base-ui/drawer/LitDrawer'; 22import './DrawerCpuTabs'; 23import { procedurePool } from '../../database/Procedure'; 24import { info } from '../../../log/Log'; 25import { LitSelect } from '../../../base-ui/select/LitSelect'; 26import '../../../base-ui/progress-bar/LitProgressBar'; 27import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar'; 28import { pieChartColors } from '../../../base-ui/chart/pie/LitChartPieData'; 29import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; 30import { TabCpuAnalysisHtml } from './TabCpuAnalysis.html'; 31 32@element('tab-cpu-analysis') 33export class TabCpuAnalysis extends BaseElement { 34 private cpuUsageGrid: HTMLDivElement | undefined; 35 private cpuUsageChart: HTMLDivElement | undefined; 36 private drawer: LitDrawer | undefined | null; 37 private cpuPieMap: Map<number, LitChartPie> = new Map<number, LitChartPie>(); 38 private schedulingSelect: LitSelect | undefined | null; 39 private drawerCpuTabs: DrawerCpuTabs | undefined | null; 40 private progress: LitProgressBar | null | undefined; 41 private loadingUsage: boolean = false; 42 private loadingPieData: boolean = false; 43 44 initElements(): void { 45 this.progress = this.shadowRoot!.querySelector<LitProgressBar>('#loading'); 46 this.cpuUsageGrid = this.shadowRoot?.querySelector('#cpu_usage_table') as HTMLDivElement; 47 this.cpuUsageChart = this.shadowRoot?.querySelector('#cpu_usage_chart') as HTMLDivElement; 48 this.schedulingSelect = this.shadowRoot?.querySelector<LitSelect>('#scheduling_select'); 49 this.drawer = this.shadowRoot!.querySelector<LitDrawer>('#drawer-right'); 50 this.drawerCpuTabs = this.shadowRoot?.querySelector<DrawerCpuTabs>('#drawer-cpu-tabs'); 51 this.schedulingSelect!.onchange = (e): void => { 52 this.loadingPieData = true; 53 this.progress!.loading = this.loadingUsage || this.loadingPieData; //@ts-ignore 54 this.queryPieChartDataByType((e as unknown).detail.text); 55 }; 56 this.drawer!.onClose = (): void => { 57 this.drawerCpuTabs!.clearData(); 58 }; 59 } 60 61 init(): void { 62 this.cpuPieMap.clear(); 63 this.cpuUsageGrid!.innerHTML = ''; 64 this.cpuUsageChart!.innerHTML = ''; 65 this.schedulingSelect!.value = '1'; 66 this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); 67 for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) { 68 let cpuPie = new LitChartPie(); 69 cpuPie.className = 'pie-chart'; 70 this.cpuPieMap.set(i, cpuPie); 71 this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${i}`, 0)); 72 this.cpuUsageChart!.append(this.createUsageChartItem(i, cpuPie)); 73 } 74 this.loadingUsage = true; 75 this.loadingPieData = true; 76 this.progress!.loading = this.loadingUsage || this.loadingPieData; 77 this.queryLogicWorker('scheduling-getCpuUsage', 'query Cpu Usage Time:', (res): void => { 78 //@ts-ignore 79 if (res && res.length > 0) { 80 this.cpuUsageGrid!.innerHTML = ''; 81 this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); 82 if (res instanceof Array) { 83 for (let re of res) { 84 this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${re.cpu}`, ((re.usage || 0) * 100).toFixed(2))); 85 } 86 } 87 } 88 this.loadingUsage = false; 89 this.progress!.loading = this.loadingUsage || this.loadingPieData; 90 }); 91 this.queryPieChartDataByType('CPU Idle'); 92 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 93 event: 'CPU Data', 94 action: 'trace_tab', 95 }); 96 } 97 98 queryPieChartDataByType(type: string): void { 99 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 100 event: `Analysis ${type}`, 101 action: 'scheduling_analysis', 102 }); 103 let tip = ''; 104 if (type === 'CPU Frequency') { 105 tip = 'freq:'; 106 } else if (type === 'CPU Idle') { 107 tip = 'idle:'; 108 } else { 109 tip = 'irq:'; 110 } 111 this.queryLogicWorker(`scheduling-${type}`, `query ${type} Analysis Time:`, (res): void => { 112 for (let key of this.cpuPieMap.keys()) { 113 this.cpuPieMap.get(key)!.config = { 114 appendPadding: 10, //@ts-ignore 115 data: res.get(key) || [], 116 angleField: 'sum', 117 colorField: 'value', 118 radius: 0.8, 119 tip: (obj): string => { 120 return `<div> 121 <div>${tip}${ 122 // @ts-ignore 123 obj.obj.value 124 }</div> 125 <div>ratio:${ 126 // @ts-ignore 127 obj.obj.ratio 128 }%</div> 129 </div> 130 `; 131 }, 132 label: { 133 type: 'outer', 134 color: 135 type !== 'CPU Idle' 136 ? undefined 137 : (it): string => { 138 //@ts-ignore 139 return pieChartColors[(it as unknown).value]; 140 }, 141 }, 142 interactions: [ 143 { 144 type: 'element-active', 145 }, 146 ], 147 }; 148 } 149 this.loadingPieData = false; 150 this.progress!.loading = this.loadingUsage || this.loadingPieData; 151 }); 152 } 153 154 queryLogicWorker(cpuAnalysisType: string, log: string, handler: (res: unknown) => void): void { 155 let cpuAnalysisTime = new Date().getTime(); 156 procedurePool.submitWithName( 157 'logic0', 158 cpuAnalysisType, 159 { 160 endTs: SpSchedulingAnalysis.endTs, 161 total: SpSchedulingAnalysis.totalDur, 162 }, 163 undefined, 164 handler 165 ); 166 let durTime = new Date().getTime() - cpuAnalysisTime; 167 info(log, durTime); 168 } 169 170 createUsageItem(name: string, value: unknown): HTMLDivElement { 171 let div = document.createElement('div'); 172 div.className = 'usage_item_box'; 173 div.innerHTML = `<div class="usage_item">${name}</div><div class="usage_item">${value}</div>`; 174 return div; 175 } 176 177 createUsageChartItem(cpu: number, pie: LitChartPie): HTMLDivElement { 178 let div = document.createElement('div'); 179 div.className = 'usage_chart'; 180 div.style.cursor = 'pointer'; 181 div.innerHTML = ` 182 <div style="height: 40px;line-height: 40px;margin-left: 10px">CPU: ${cpu}</div> 183 `; 184 div.append(pie); 185 div.addEventListener('click', (): void => { 186 if (this.loadingUsage || this.loadingPieData) { 187 return; 188 } 189 this.drawer!.drawerTitle = `CPU: ${cpu}`; 190 this.drawer!.visible = true; 191 this.drawerCpuTabs!.init(cpu, this.schedulingSelect!.value); 192 }); 193 return div; 194 } 195 196 initHtml(): string { 197 return TabCpuAnalysisHtml; 198 } 199} 200