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 { SpSchedulingAnalysis } from './SpSchedulingAnalysis.js'; 18import { DrawerCpuTabs } from './DrawerCpuTabs.js'; 19import { LitChartPie } from '../../../base-ui/chart/pie/LitChartPie.js'; 20import { LitDrawer } from '../../../base-ui/drawer/LitDrawer.js'; 21import '../../../base-ui/drawer/LitDrawer.js'; 22import './DrawerCpuTabs.js'; 23import { procedurePool } from '../../database/Procedure.js'; 24import { info } from '../../../log/Log.js'; 25import { LitSelect } from '../../../base-ui/select/LitSelect'; 26import '../../../base-ui/progress-bar/LitProgressBar.js'; 27import { LitProgressBar } from '../../../base-ui/progress-bar/LitProgressBar.js'; 28import { pieChartColors } from '../../../base-ui/chart/pie/LitChartPieData.js'; 29import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil.js'; 30 31@element('tab-cpu-analysis') 32export class TabCpuAnalysis extends BaseElement { 33 private cpuUsageGrid: HTMLDivElement | undefined; 34 private cpuUsageChart: HTMLDivElement | undefined; 35 private drawer: LitDrawer | undefined | null; 36 private cpuPieMap: Map<number, LitChartPie> = new Map<number, LitChartPie>(); 37 private schedulingSelect: LitSelect | undefined | null; 38 private drawerCpuTabs: DrawerCpuTabs | undefined | null; 39 private progress: LitProgressBar | null | undefined; 40 private loadingUsage: boolean = false; 41 private loadingPieData: boolean = false; 42 43 initElements(): void { 44 this.progress = this.shadowRoot!.querySelector<LitProgressBar>('#loading'); 45 this.cpuUsageGrid = this.shadowRoot?.querySelector('#cpu_usage_table') as HTMLDivElement; 46 this.cpuUsageChart = this.shadowRoot?.querySelector('#cpu_usage_chart') as HTMLDivElement; 47 this.schedulingSelect = this.shadowRoot?.querySelector<LitSelect>('#scheduling_select'); 48 this.drawer = this.shadowRoot!.querySelector<LitDrawer>('#drawer-right'); 49 this.drawerCpuTabs = this.shadowRoot?.querySelector<DrawerCpuTabs>('#drawer-cpu-tabs'); 50 this.schedulingSelect!.onchange = (e) => { 51 this.loadingPieData = true; 52 this.progress!.loading = this.loadingUsage || this.loadingPieData; 53 this.queryPieChartDataByType((e as any).detail.text); 54 }; 55 this.drawer!.onClose = (e: any) => { 56 this.drawerCpuTabs!.clearData(); 57 }; 58 } 59 60 init() { 61 this.cpuPieMap.clear(); 62 this.cpuUsageGrid!.innerHTML = ''; 63 this.cpuUsageChart!.innerHTML = ''; 64 this.schedulingSelect!.value = '1'; 65 this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); 66 for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) { 67 let cpuPie = new LitChartPie(); 68 cpuPie.className = 'pie-chart'; 69 this.cpuPieMap.set(i, cpuPie); 70 this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${i}`, 0)); 71 this.cpuUsageChart!.append(this.createUsageChartItem(i, cpuPie)); 72 } 73 this.loadingUsage = true; 74 this.loadingPieData = true; 75 this.progress!.loading = this.loadingUsage || this.loadingPieData; 76 this.queryLogicWorker('scheduling-getCpuUsage', 'query Cpu Usage Time:', (res) => { 77 if (res && res.length > 0) { 78 this.cpuUsageGrid!.innerHTML = ''; 79 this.cpuUsageGrid!.append(this.createUsageItem('usage', '%')); 80 if (res instanceof Array) { 81 for (let re of res) { 82 this.cpuUsageGrid!.append(this.createUsageItem(`CPU: ${re.cpu}`, ((re.usage || 0) * 100).toFixed(2))); 83 } 84 } 85 } 86 this.loadingUsage = false; 87 this.progress!.loading = this.loadingUsage || this.loadingPieData; 88 }); 89 this.queryPieChartDataByType('CPU Idle'); 90 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 91 event: 'CPU Data', 92 action: 'trace_tab', 93 }); 94 } 95 96 queryPieChartDataByType(type: string) { 97 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 98 event: 'Analysis ' + type, 99 action: 'scheduling_analysis', 100 }); 101 let tip = ''; 102 if (type === 'CPU Frequency') { 103 tip = 'freq:'; 104 } else if (type === 'CPU Idle') { 105 tip = 'idle:'; 106 } else { 107 tip = 'irq:'; 108 } 109 this.queryLogicWorker(`scheduling-${type}`, `query ${type} Analysis Time:`, (res) => { 110 for (let key of this.cpuPieMap.keys()) { 111 this.cpuPieMap.get(key)!.config = { 112 appendPadding: 10, 113 data: res.get(key) || [], 114 angleField: 'sum', 115 colorField: 'value', 116 radius: 0.8, 117 tip: (obj) => { 118 return `<div> 119 <div>${tip}${obj.obj.value}</div> 120 <div>ratio:${obj.obj.ratio}%</div> 121 </div> 122 `; 123 }, 124 label: { 125 type: 'outer', 126 color: 127 type !== 'CPU Idle' 128 ? undefined 129 : (it) => { 130 return pieChartColors[(it as any).value]; 131 }, 132 }, 133 interactions: [ 134 { 135 type: 'element-active', 136 }, 137 ], 138 }; 139 } 140 this.loadingPieData = false; 141 this.progress!.loading = this.loadingUsage || this.loadingPieData; 142 }); 143 } 144 145 queryLogicWorker(cpuAnalysisType: string, log: string, handler: (res: any) => void) { 146 let cpuAnalysisTime = new Date().getTime(); 147 procedurePool.submitWithName( 148 'logic1', 149 cpuAnalysisType, 150 { 151 endTs: SpSchedulingAnalysis.endTs, 152 total: SpSchedulingAnalysis.totalDur, 153 }, 154 undefined, 155 handler 156 ); 157 let durTime = new Date().getTime() - cpuAnalysisTime; 158 info(log, durTime); 159 } 160 161 createUsageItem(name: string, value: any) { 162 let div = document.createElement('div'); 163 div.className = 'usage_item_box'; 164 div.innerHTML = `<div class="usage_item">${name}</div><div class="usage_item">${value}</div>`; 165 return div; 166 } 167 168 createUsageChartItem(cpu: number, pie: LitChartPie) { 169 let div = document.createElement('div'); 170 div.className = 'usage_chart'; 171 div.style.cursor = 'pointer'; 172 div.innerHTML = ` 173 <div style="height: 40px;line-height: 40px;margin-left: 10px">CPU: ${cpu}</div> 174 `; 175 div.append(pie); 176 div.addEventListener('click', (event) => { 177 if (this.loadingUsage || this.loadingPieData) { 178 return; 179 } 180 this.drawer!.title = `CPU: ${cpu}`; 181 this.drawer!.visible = true; 182 this.drawerCpuTabs!.init(cpu, this.schedulingSelect!.value); 183 }); 184 return div; 185 } 186 187 initHtml(): string { 188 return ` 189 <style> 190 :host { 191 width: 100%; 192 height: 100%; 193 background-color: var(--dark-background,#FFFFFF); 194 } 195 .cpu_usage{ 196 display: flex; 197 flex-direction: row; 198 box-sizing: border-box; 199 padding: 15px; 200 background-color: var(--dark-background,#FFFFFF); 201 } 202 .usage_item{ 203 height: 50px; 204 line-height: 50px; 205 text-align: center; 206 border: solid 1px var(--dark-border1,#f0f0f0); 207 } 208 .usage_item_box{ 209 border: solid 1px var(--dark-border1,#f0f0f0); 210 flex: 1; 211 } 212 .usage_chart{ 213 height: 360px; 214 color: var(--dark-color1,#252525); 215 background-color: var(--dark-background,#FFFFFF); 216 } 217 .pie-chart{ 218 display: flex; 219 box-sizing: border-box; 220 height: 300px; 221 } 222 .grid_usage{ 223 display: grid; 224 width: 100%; 225 box-sizing: border-box; 226 grid-template-columns: repeat(4,calc((100% - 30px) / 4)); 227 grid-column-gap: 10px; 228 grid-row-gap: 10px; 229 padding: 10px; 230 background-color: var(--dark-background5,#F6F6F6); 231 } 232 .cpu-statistics{ 233 height: 50px; 234 display: flex; 235 flex-direction: row; 236 justify-content: space-between; 237 align-items: center; 238 padding:0px 15px; 239 background-color: var(--dark-background,#FFFFFF); 240 } 241 </style> 242 <div style="display: flex;flex-direction: column;overflow-x: hidden;overflow-y: auto;height: 100%"> 243 <lit-progress-bar id="loading" style="height: 1px;width: 100%"></lit-progress-bar> 244 <div class="cpu_usage" id="cpu_usage_table"></div> 245 <div class="cpu-statistics"> 246 <div>CPU Statistics By Duration</div> 247 <lit-select default-value="1" id="scheduling_select"> 248 <lit-select-option value="1">CPU Idle</lit-select-option> 249 <lit-select-option value="2">CPU Frequency</lit-select-option> 250 <lit-select-option value="3">CPU Irq</lit-select-option> 251 </lit-select> 252 </div> 253 <div class="grid_usage" id="cpu_usage_chart"></div> 254 </div> 255 <lit-drawer id="drawer-right" title="CPU:0" content-width="65vw" placement="right" style="position: fixed" fixed mask mask-closeable closeable content-padding="0"> 256 <drawer-cpu-tabs id="drawer-cpu-tabs"></drawer-cpu-tabs> 257 </lit-drawer> 258 `; 259 } 260} 261