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 "../../base-ui/popover/LitPopover.js" 18import "../../base-ui/button/LitButton.js"; 19import {LitMainMenuGroup} from "../../base-ui/menu/LitMainMenuGroup.js"; 20import {LitMainMenuItem} from "../../base-ui/menu/LitMainMenuItem.js"; 21import {SpRecordSetting} from "./setting/SpRecordSetting.js"; 22import {LitMainMenu, MenuGroup, MenuItem} from "../../base-ui/menu/LitMainMenu.js"; 23import {SpProbesConfig} from "./setting/SpProbesConfig.js"; 24import {SpTraceCommand} from "./setting/SpTraceCommand.js"; 25 26import { 27 CpuConfig, 28 CreateSessionRequest, 29 DiskioConfig, FileSystemConfig, 30 FpsConfig, 31 HilogConfig, 32 HiperfPluginConfig, HiSystemEventConfig, 33 levelFromJSON, 34 MemoryConfig, 35 NativeHookConfig, 36 NetworkConfig, 37 ProcessConfig, 38 ProfilerPluginConfig, 39 ProfilerSessionConfig, 40 ProfilerSessionConfigBufferConfig, 41 ProfilerSessionConfigBufferConfigPolicy, 42 ProfilerSessionConfigMode, 43 sysMeminfoTypeFromJSON, 44 sysVMeminfoTypeFromJSON, 45 TracePluginConfig, 46 Type 47} from "./setting/bean/ProfilerServiceTypes.js"; 48import {PluginConvertUtils} from "./setting/utils/PluginConvertUtils.js"; 49import {SpAllocations} from "./setting/SpAllocations.js"; 50import {SpRecordPerf} from "./setting/SpRecordPerf.js"; 51import {HdcDeviceManager} from "../../hdc/HdcDeviceManager.js"; 52import {LitButton} from "../../base-ui/button/LitButton.js"; 53import {SpApplication} from "../SpApplication.js"; 54import {LitSearch} from "./trace/search/Search.js"; 55import {LitProgressBar} from "../../base-ui/progress-bar/LitProgressBar.js"; 56import {info, log} from "../../log/Log.js"; 57import {CmdConstant} from "../../command/CmdConstant.js"; 58import {Cmd} from "../../command/Cmd.js"; 59import {SpFileSystem} from "./setting/SpFileSystem.js"; 60import {SpSdkConfig} from "./setting/SpSdkConfig.js"; 61import {SpVmTracker} from "./setting/SpVmTracker.js"; 62 63@element('sp-record-trace') 64export class SpRecordTrace extends BaseElement { 65 public static serialNumber: string = ''; 66 // 1GB 67 public static MaxFileSize: number = 1024 * 1024 * 1024; 68 public static isVscode = false; 69 70 set vs(vs: boolean) { 71 if (vs) { 72 SpRecordTrace.isVscode = true; 73 this.setAttribute("vs", '') 74 } else { 75 SpRecordTrace.isVscode = false; 76 this.removeAttribute("vs"); 77 } 78 } 79 80 get vs(): boolean { 81 return this.hasAttribute("vs"); 82 } 83 84 static MEM_INFO = ["MEMINFO_ACTIVE", "MEMINFO_ACTIVE_ANON", "MEMINFO_ACTIVE_FILE", "MEMINFO_ANON_PAGES", "MEMINFO_BUFFERS", 85 "MEMINFO_CACHED", "MEMINFO_CMA_FREE", "MEMINFO_CMA_TOTAL", "MEMINFO_COMMIT_LIMIT", "MEMINFO_COMMITED_AS", 86 "MEMINFO_DIRTY", "MEMINFO_INACTIVE", "MEMINFO_INACTIVE_ANON", "MEMINFO_INACTIVE_FILE", 87 "MEMINFO_KERNEL_STACK", "MEMINFO_MAPPED", "MEMINFO_MEM_AVAILABLE", "MEMINFO_MEM_FREE", "MEMINFO_MEM_TOTAL", 88 "MEMINFO_MLOCKED", "MEMINFO_PAGE_TABLES", "MEMINFO_SHMEM", "MEMINFO_SLAB", "MEMINFO_SLAB_RECLAIMABLE", 89 "MEMINFO_SLAB_UNRECLAIMABLE", "MEMINFO_SWAP_CACHED", "MEMINFO_SWAP_FREE", "MEMINFO_SWAP_TOTAL", 90 "MEMINFO_UNEVICTABLE", "MEMINFO_VMALLOC_CHUNK", "MEMINFO_VMALLOC_TOTAL", "MEMINFO_VMALLOC_USED", 91 "MEMINFO_WRITEBACK", "MEMINFO_KERNEL_RECLAIMABLE"] 92 static VMEM_INFO = ["VMEMINFO_UNSPECIFIED", "VMEMINFO_NR_FREE_PAGES", "VMEMINFO_NR_ALLOC_BATCH", 93 "VMEMINFO_NR_INACTIVE_ANON", "VMEMINFO_NR_ACTIVE_ANON", "VMEMINFO_NR_INACTIVE_FILE", 94 "VMEMINFO_NR_ACTIVE_FILE", "VMEMINFO_NR_UNEVICTABLE", "VMEMINFO_NR_MLOCK", "VMEMINFO_NR_ANON_PAGES", 95 "VMEMINFO_NR_MAPPED", "VMEMINFO_NR_FILE_PAGES", "VMEMINFO_NR_DIRTY", "VMEMINFO_NR_WRITEBACK", 96 "VMEMINFO_NR_SLAB_RECLAIMABLE", "VMEMINFO_NR_SLAB_UNRECLAIMABLE", "VMEMINFO_NR_PAGE_TABLE_PAGES", 97 "VMEMINFO_NR_KERNEL_STACK", "VMEMINFO_NR_OVERHEAD", "VMEMINFO_NR_UNSTABLE", "VMEMINFO_NR_BOUNCE", 98 "VMEMINFO_NR_VMSCAN_WRITE", "VMEMINFO_NR_VMSCAN_IMMEDIATE_RECLAIM", "VMEMINFO_NR_WRITEBACK_TEMP", 99 "VMEMINFO_NR_ISOLATED_ANON", "VMEMINFO_NR_ISOLATED_FILE", "VMEMINFO_NR_SHMEM", "VMEMINFO_NR_DIRTIED", 100 "VMEMINFO_NR_WRITTEN", "VMEMINFO_NR_PAGES_SCANNED", "VMEMINFO_WORKINGSET_REFAULT", 101 "VMEMINFO_WORKINGSET_ACTIVATE", "VMEMINFO_WORKINGSET_NODERECLAIM", "VMEMINFO_NR_ANON_TRANSPARENT_HUGEPAGES", 102 "VMEMINFO_NR_FREE_CMA", "VMEMINFO_NR_SWAPCACHE", "VMEMINFO_NR_DIRTY_THRESHOLD", 103 "VMEMINFO_NR_DIRTY_BACKGROUND_THRESHOLD", "VMEMINFO_PGPGIN", "VMEMINFO_PGPGOUT", "VMEMINFO_PGPGOUTCLEAN", 104 "VMEMINFO_PSWPIN", "VMEMINFO_PSWPOUT", "VMEMINFO_PGALLOC_DMA"] 105 static VMEM_INFO_SECOND = ["VMEMINFO_PGALLOC_NORMAL", "VMEMINFO_PGALLOC_MOVABLE", "VMEMINFO_PGFREE", "VMEMINFO_PGACTIVATE", 106 "VMEMINFO_PGDEACTIVATE", "VMEMINFO_PGFAULT", "VMEMINFO_PGMAJFAULT", "VMEMINFO_PGREFILL_DMA", 107 "VMEMINFO_PGREFILL_NORMAL", "VMEMINFO_PGREFILL_MOVABLE", "VMEMINFO_PGSTEAL_KSWAPD_DMA", 108 "VMEMINFO_PGSTEAL_KSWAPD_NORMAL", "VMEMINFO_PGSTEAL_KSWAPD_MOVABLE", "VMEMINFO_PGSTEAL_DIRECT_DMA", 109 "VMEMINFO_PGSTEAL_DIRECT_NORMAL", "VMEMINFO_PGSTEAL_DIRECT_MOVABLE", "VMEMINFO_PGSCAN_KSWAPD_DMA", 110 "VMEMINFO_PGSCAN_KSWAPD_NORMAL", "VMEMINFO_PGSCAN_KSWAPD_MOVABLE", "VMEMINFO_PGSCAN_DIRECT_DMA", 111 "VMEMINFO_PGSCAN_DIRECT_NORMAL", "VMEMINFO_PGSCAN_DIRECT_MOVABLE", "VMEMINFO_PGSCAN_DIRECT_THROTTLE", 112 "VMEMINFO_PGINODESTEAL", "VMEMINFO_SLABS_SCANNED", "VMEMINFO_KSWAPD_INODESTEAL", 113 "VMEMINFO_KSWAPD_LOW_WMARK_HIT_QUICKLY", "VMEMINFO_KSWAPD_HIGH_WMARK_HIT_QUICKLY", "VMEMINFO_PAGEOUTRUN", 114 "VMEMINFO_ALLOCSTALL", "VMEMINFO_PGROTATED", "VMEMINFO_DROP_PAGECACHE", "VMEMINFO_DROP_SLAB", 115 "VMEMINFO_PGMIGRATE_SUCCESS", "VMEMINFO_PGMIGRATE_FAIL", "VMEMINFO_COMPACT_MIGRATE_SCANNED", 116 "VMEMINFO_COMPACT_FREE_SCANNED", "VMEMINFO_COMPACT_ISOLATED", "VMEMINFO_COMPACT_STALL", 117 "VMEMINFO_COMPACT_FAIL", "VMEMINFO_COMPACT_SUCCESS", "VMEMINFO_COMPACT_DAEMON_WAKE", 118 "VMEMINFO_UNEVICTABLE_PGS_CULLED", "VMEMINFO_UNEVICTABLE_PGS_SCANNED", "VMEMINFO_UNEVICTABLE_PGS_RESCUED", 119 "VMEMINFO_UNEVICTABLE_PGS_MLOCKED", "VMEMINFO_UNEVICTABLE_PGS_MUNLOCKED"] 120 static VMEM_INFO_THIRD = [ 121 "VMEMINFO_UNEVICTABLE_PGS_CLEARED", "VMEMINFO_UNEVICTABLE_PGS_STRANDED", "VMEMINFO_NR_ZSPAGES", 122 "VMEMINFO_NR_ION_HEAP", "VMEMINFO_NR_GPU_HEAP", "VMEMINFO_ALLOCSTALL_DMA", "VMEMINFO_ALLOCSTALL_MOVABLE", 123 "VMEMINFO_ALLOCSTALL_NORMAL", "VMEMINFO_COMPACT_DAEMON_FREE_SCANNED", 124 "VMEMINFO_COMPACT_DAEMON_MIGRATE_SCANNED", "VMEMINFO_NR_FASTRPC", "VMEMINFO_NR_INDIRECTLY_RECLAIMABLE", 125 "VMEMINFO_NR_ION_HEAP_POOL", "VMEMINFO_NR_KERNEL_MISC_RECLAIMABLE", "VMEMINFO_NR_SHADOW_CALL_STACK_BYTES", 126 "VMEMINFO_NR_SHMEM_HUGEPAGES", "VMEMINFO_NR_SHMEM_PMDMAPPED", "VMEMINFO_NR_UNRECLAIMABLE_PAGES", 127 "VMEMINFO_NR_ZONE_ACTIVE_ANON", "VMEMINFO_NR_ZONE_ACTIVE_FILE", "VMEMINFO_NR_ZONE_INACTIVE_ANON", 128 "VMEMINFO_NR_ZONE_INACTIVE_FILE", "VMEMINFO_NR_ZONE_UNEVICTABLE", "VMEMINFO_NR_ZONE_WRITE_PENDING", 129 "VMEMINFO_OOM_KILL", "VMEMINFO_PGLAZYFREE", "VMEMINFO_PGLAZYFREED", "VMEMINFO_PGREFILL", 130 "VMEMINFO_PGSCAN_DIRECT", "VMEMINFO_PGSCAN_KSWAPD", "VMEMINFO_PGSKIP_DMA", "VMEMINFO_PGSKIP_MOVABLE", 131 "VMEMINFO_PGSKIP_NORMAL", "VMEMINFO_PGSTEAL_DIRECT", "VMEMINFO_PGSTEAL_KSWAPD", "VMEMINFO_SWAP_RA", 132 "VMEMINFO_SWAP_RA_HIT", "VMEMINFO_WORKINGSET_RESTORE" 133 ] 134 // sys.mem.total sys.mem.free sys.mem.buffers sys.mem.cached sys.mem.shmem sys.mem.slab sys.mem.swap.total 135 // sys.mem.swap.free sys.mem.mapped sys.mem.vmalloc.used sys.mem.page.tables sys.mem.kernel.stack 136 // sys.mem.active sys.mem.inactive sys.mem.unevictable sys.mem.vmalloc.total sys.mem.slab.unreclaimable 137 // sys.mem.cma.total sys.mem.cma.free 138 static ABALITY_MEM_INFO = ["MEMINFO_MEM_TOTAL", "MEMINFO_MEM_FREE", "MEMINFO_BUFFERS", "MEMINFO_CACHED", 139 "MEMINFO_SHMEM", "MEMINFO_SLAB", "MEMINFO_SWAP_TOTAL", "MEMINFO_SWAP_FREE", "MEMINFO_MAPPED", 140 "MEMINFO_VMALLOC_USED", "MEMINFO_PAGE_TABLES", "MEMINFO_KERNEL_STACK", "MEMINFO_ACTIVE", "MEMINFO_INACTIVE", 141 "MEMINFO_UNEVICTABLE", "MEMINFO_VMALLOC_TOTAL", "MEMINFO_SLAB_UNRECLAIMABLE", "MEMINFO_CMA_TOTAL", 142 "MEMINFO_CMA_FREE", "MEMINFO_KERNEL_RECLAIMABLE"] 143 144 schedulingEvents = [ 145 "sched/sched_switch", 146 "power/suspend_resume", 147 "sched/sched_wakeup", 148 "sched/sched_wakeup_new", 149 "sched/sched_waking", 150 "sched/sched_process_exit", 151 "sched/sched_process_free", 152 "task/task_newtask", 153 "task/task_rename" 154 ] 155 powerEvents = [ 156 "regulator/regulator_set_voltage", 157 "regulator/regulator_set_voltage_complete", 158 "power/clock_enable", 159 "power/clock_disable", 160 "power/clock_set_rate", 161 "power/suspend_resume" 162 ] 163 cpuFreqEvents = [ 164 "power/cpu_frequency", 165 "power/cpu_idle", 166 "power/suspend_resume" 167 ] 168 sysCallsEvents = [ 169 "raw_syscalls/sys_enter", 170 "raw_syscalls/sys_exit" 171 ] 172 highFrequencyEvents = [ 173 "mm_event/mm_event_record", 174 "kmem/rss_stat", 175 "ion/ion_stat", 176 "dmabuf_heap/dma_heap_stat", 177 "kmem/ion_heap_grow", 178 "kmem/ion_heap_shrink" 179 ] 180 advancedConfigEvents = ["sched/sched_switch", 181 "sched/sched_wakeup", 182 "sched/sched_wakeup_new", 183 "sched/sched_waking", 184 "sched/sched_process_exit", 185 "sched/sched_process_free", 186 "irq/irq_handler_entry", 187 "irq/irq_handler_exit", 188 "irq/softirq_entry", 189 "irq/softirq_exit", 190 "irq/softirq_raise", 191 "power/clock_disable", 192 "power/clock_enable", 193 "power/clock_set_rate", 194 "power/cpu_frequency", 195 "power/cpu_idle", 196 "clk/clk_disable", 197 "clk/clk_disable_complete", 198 "clk/clk_enable", 199 "clk/clk_enable_complete", 200 "clk/clk_set_rate", 201 "clk/clk_set_rate_complete", 202 "binder/binder_transaction", 203 "binder/binder_transaction_alloc_buf", 204 "binder/binder_transaction_received", 205 "binder/binder_lock", 206 "binder/binder_locked", 207 "binder/binder_unlock", 208 "workqueue/workqueue_execute_start", 209 "workqueue/workqueue_execute_end", 210 "oom/oom_score_adj_update", 211 "ftrace/print" 212 ] 213 private _menuItems: Array<MenuItem> | undefined 214 215 public deviceSelect: HTMLSelectElement | undefined; 216 217 private stopButtonEl: HTMLButtonElement | null | undefined; 218 219 private recordButton: LitButton | undefined; 220 private sp: SpApplication | undefined; 221 private progressEL: LitProgressBar | undefined; 222 private litSearch: LitSearch | undefined; 223 private addButton: LitButton | undefined | null; 224 225 private recordSetting: SpRecordSetting | undefined; 226 private probesConfig: SpProbesConfig | undefined; 227 private traceCommand: SpTraceCommand | undefined; 228 private spAllocations: SpAllocations | undefined; 229 private spRecordPerf: SpRecordPerf | undefined; 230 private spFileSystem: SpFileSystem | undefined; 231 private spSdkConfig: SpSdkConfig | undefined; 232 private spVmTracker: SpVmTracker | undefined; 233 234 private menuGroup: LitMainMenuGroup | undefined | null; 235 private appContent: HTMLElement | undefined | null; 236 237 compareArray(devs: Array<string>): boolean { 238 let clearFlag: boolean = false; 239 let optionArray = new Array(); 240 if (devs.length != this.deviceSelect!.options.length) { 241 clearFlag = true 242 } else { 243 let optionArray = new Array(); 244 for (let i = 0; i < this.deviceSelect!.options.length; i++) { 245 optionArray.push(this.deviceSelect!.options[i].value) 246 } 247 devs.forEach(value => { 248 if (optionArray.indexOf(value) == -1) { 249 clearFlag = true 250 } 251 }) 252 } 253 return clearFlag; 254 } 255 256 refreshDeviceList() { 257 if (this.vs) { 258 Cmd.execHdcCmd(CmdConstant.CMD_HDC_DEVICES, (res: string) => { 259 let devs: string[] = res.trim().replace(/\r\n/g, "\r").replace(/\n/g, "\r").split(/\r/); 260 if (devs.length == 1 && devs[0].indexOf("Empty") != -1) { 261 this.deviceSelect!.innerHTML = ''; 262 return; 263 } 264 let clearFlag = this.compareArray(devs); 265 if (clearFlag) { 266 this.deviceSelect!.innerHTML = ''; 267 for (let i = 0; i < devs.length; i++) { 268 let dev = devs[i]; 269 let option = document.createElement("option") 270 option.className = 'select' 271 option.textContent = dev; 272 this.deviceSelect!.appendChild(option) 273 if (i == 0) { 274 SpRecordTrace.serialNumber = option.value; 275 } 276 } 277 } 278 }); 279 } else { 280 this.deviceSelect!.innerHTML = ''; 281 HdcDeviceManager.getDevices().then((devs: USBDevice[]) => { 282 for (let len = 0; len < devs.length; len++) { 283 let dev = devs[len]; 284 let option = document.createElement("option") 285 option.className = 'select' 286 if (typeof dev.serialNumber === "string") { 287 option.value = dev.serialNumber; 288 } 289 option.textContent = dev!.serialNumber ? dev!.serialNumber!.toString() : 'hdc Device'; 290 this.deviceSelect!.appendChild(option) 291 if (len == 0) { 292 SpRecordTrace.serialNumber = option.value; 293 HdcDeviceManager.connect(option.value).then(() => { 294 }); 295 } 296 } 297 }); 298 } 299 } 300 301 freshMenuDisable(disable: boolean) { 302 let mainMenu = this.sp!.shadowRoot?.querySelector('#main-menu') as LitMainMenu 303 mainMenu.menus?.forEach(men => { 304 men.children.forEach(child => { 305 // @ts-ignore 306 child.disabled = disable 307 } 308 ) 309 } 310 ) 311 mainMenu.menus = mainMenu.menus; 312 } 313 314 set showHint(bool: boolean) { 315 if (bool) { 316 this.setAttribute("show_hint", ''); 317 } else { 318 this.removeAttribute("show_hint"); 319 } 320 } 321 322 private refreshDeviceTimer: any; 323 324 initElements(): void { 325 let parentElement = this.parentNode as HTMLElement; 326 parentElement.style.overflow = 'hidden' 327 this.addButton = this.shadowRoot?.querySelector<LitButton>(".add"); 328 this.addButton!.addEventListener("click", () => { 329 if (this.vs) { 330 this.refreshDeviceList(); 331 } else { 332 HdcDeviceManager.findDevice().then(usbDevices => { 333 log(usbDevices) 334 this.refreshDeviceList(); 335 }); 336 } 337 }) 338 this.deviceSelect = this.shadowRoot?.querySelector("#device-select") as HTMLSelectElement; 339 this.deviceSelect!.onchange = () => { 340 let value = this.deviceSelect!.options[this.deviceSelect!.selectedIndex].value; 341 SpRecordTrace.serialNumber = value; 342 if (!this.vs) { 343 HdcDeviceManager.connect(value).then(() => { 344 }); 345 } 346 } 347 if (navigator.usb) { 348 navigator.usb.addEventListener('connect', (ev: USBConnectionEvent) => { 349 this.usbConnectionListener(ev); 350 }); 351 navigator.usb.addEventListener('disconnect', (ev: USBConnectionEvent) => { 352 this.usbDisConnectionListener(ev) 353 }); 354 } 355 this.recordSetting = new SpRecordSetting(); 356 this.probesConfig = new SpProbesConfig(); 357 this.traceCommand = new SpTraceCommand(); 358 this.spAllocations = new SpAllocations(); 359 this.spRecordPerf = new SpRecordPerf(); 360 this.spFileSystem = new SpFileSystem(); 361 this.spSdkConfig = new SpSdkConfig(); 362 this.spVmTracker = new SpVmTracker(); 363 this.recordButton = this.shadowRoot?.querySelector(".record") as LitButton; 364 this.sp = document.querySelector("sp-application") as SpApplication; 365 this.progressEL = this.sp.shadowRoot?.querySelector('.progress') as LitProgressBar 366 this.litSearch = this.sp.shadowRoot?.querySelector('#lit-search') as LitSearch; 367 this.recordButton!.addEventListener("click", () => { 368 this.recordButtonListener() 369 }) 370 this.spRecordPerf!.addEventListener("addProbe", (event: any) => { 371 this.showHint = false; 372 }) 373 this.spAllocations!.addEventListener("addProbe", (event: any) => { 374 this.showHint = false; 375 }) 376 this.probesConfig!.addEventListener("addProbe", (event: any) => { 377 this.showHint = false; 378 }) 379 380 this.stopButtonEl = this.traceCommand!.shadowRoot?.querySelector<HTMLButtonElement>('#stop-button'); 381 this.stopButtonEl!.addEventListener('click', ev => { 382 this.stopRecordListener(); 383 }) 384 this.menuGroup = this.shadowRoot?.querySelector('#menu-group') as LitMainMenuGroup 385 this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement 386 this.appContent.append(this.recordSetting) 387 this.initMenuItems(); 388 } 389 390 stopRecordListener() { 391 if (this.vs) { 392 let cmd = Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]); 393 Cmd.execHdcCmd(cmd, (res: string) => { 394 this.freshMenuDisable(false) 395 this.freshConfigMenuDisable(false) 396 this.progressEL!.loading = false 397 this.sp!.search = false; 398 this.litSearch!.clear(); 399 this.recordButton!.style.pointerEvents = 'auto'; 400 this.addButton!.style.pointerEvents = 'auto'; 401 this.deviceSelect!.style.pointerEvents = 'auto'; 402 this.traceCommand!.show = false; 403 }) 404 } else { 405 let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement; 406 HdcDeviceManager.connect(selectedOption.value).then(result => { 407 if (result) { 408 this.freshMenuDisable(false) 409 this.freshConfigMenuDisable(false) 410 try { 411 this.progressEL!.loading = false 412 this.sp!.search = false; 413 this.litSearch!.clear(); 414 this.recordButton!.style.pointerEvents = 'auto'; 415 this.addButton!.style.pointerEvents = 'auto'; 416 this.deviceSelect!.style.pointerEvents = 'auto'; 417 HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_STOP, true).then(result => { 418 }) 419 } catch (exception) { 420 log(exception) 421 } 422 this.traceCommand!.show = false; 423 } 424 }) 425 } 426 } 427 428 private initMenuItems() { 429 let that = this 430 this._menuItems = [ 431 { 432 title: "Record setting", 433 icon: "properties", 434 fileChoose: false, 435 clickHandler: function (ev: InputEvent) { 436 that.appContent!.innerHTML = "" 437 that.appContent!.append(that.recordSetting!) 438 that.freshMenuItemsStatus('Record setting') 439 } 440 }, 441 { 442 title: "Trace command", 443 icon: "dbsetbreakpoint", 444 fileChoose: false, 445 clickHandler: function (ev: InputEvent) { 446 that.freshMenuItemsStatus('Trace command') 447 let request = that.makeRequest(); 448 that.appContent!.innerHTML = "" 449 that.appContent!.append(that.traceCommand!) 450 that.traceCommand!.hdcCommon = 451 PluginConvertUtils.createHdcCmd( 452 PluginConvertUtils.BeanToCmdTxt(request, false), that.recordSetting!.output, that.recordSetting!.maxDur) 453 } 454 }, 455 { 456 title: "Probes config", icon: "realIntentionBulb", fileChoose: false, 457 clickHandler: function (ev: InputEvent) { 458 that.appContent!.innerHTML = "" 459 that.appContent!.append(that.probesConfig!) 460 that.freshMenuItemsStatus('Probes config') 461 } 462 }, 463 { 464 title: "Native Memory", 465 icon: "externaltools", 466 fileChoose: false, 467 clickHandler: function (ev: InputEvent) { 468 that.appContent!.innerHTML = "" 469 that.appContent!.append(that.spAllocations!) 470 that.freshMenuItemsStatus('Native Memory') 471 } 472 }, 473 { 474 title: "Hiperf", icon: "realIntentionBulb", fileChoose: false, 475 clickHandler: function (ev: InputEvent) { 476 that.appContent!.innerHTML = "" 477 that.appContent!.append(that.spRecordPerf!) 478 that.freshMenuItemsStatus('Hiperf') 479 } 480 }, 481 { 482 title: "eBPF Config", icon: "file-config", fileChoose: false, 483 clickHandler: function (ev: InputEvent) { 484 that.appContent!.innerHTML = "" 485 that.appContent!.append(that.spFileSystem!) 486 that.freshMenuItemsStatus('eBPF Config') 487 } 488 }, 489 { 490 title: "VM Tracker", icon: "vm-tracker", fileChoose: false, 491 clickHandler: function (ev: InputEvent) { 492 that.appContent!.innerHTML = "" 493 that.appContent!.append(that.spVmTracker!) 494 that.freshMenuItemsStatus('VM Tracker') 495 } 496 }, 497 { 498 title: "SDK Config", icon: "file-config", fileChoose: false, 499 clickHandler: function (ev: InputEvent) { 500 that.appContent!.innerHTML = "" 501 that.appContent!.append(that.spSdkConfig!) 502 that.freshMenuItemsStatus('SDK Config') 503 } 504 } 505 ] 506 this._menuItems?.forEach(item => { 507 let th = new LitMainMenuItem(); 508 th.setAttribute('icon', item.icon || ""); 509 th.setAttribute('title', item.title || ""); 510 th.style.height = "60px" 511 th.style.fontFamily = "Helvetica-Bold" 512 th.style.fontSize = "16px" 513 th.style.lineHeight = "28px" 514 th.style.fontWeight = "700" 515 th.style.opacity = "0.9" 516 th.removeAttribute('file'); 517 th.addEventListener('click', e => { 518 if (item.clickHandler) { 519 item.clickHandler(item) 520 } 521 }) 522 this.menuGroup!.appendChild(th); 523 }) 524 } 525 526 usbConnectionListener(event: USBConnectionEvent) { 527 if (event.isTrusted) { 528 let usbDevice: USBDevice = event.device; 529 let option = document.createElement("option") 530 option.className = 'select' 531 if (typeof usbDevice.serialNumber === "string") { 532 option.value = usbDevice.serialNumber; 533 } 534 option.selected = true; 535 option.textContent = usbDevice!.serialNumber ? usbDevice!.serialNumber.replace(/"/g, "") 536 : 'hdc Device'; 537 this.deviceSelect!.appendChild(option) 538 SpRecordTrace.serialNumber = option.value; 539 HdcDeviceManager.connect(option.value).then(() => { 540 }); 541 } 542 } 543 544 usbDisConnectionListener(event: USBConnectionEvent) { 545 let disConnectDevice: USBDevice = event.device; 546 for (let index = 0; index < this.deviceSelect!.children.length; index++) { 547 let option = this.deviceSelect!.children[index] as HTMLOptionElement; 548 if (option.value == disConnectDevice.serialNumber) { 549 let optValue = option.value; 550 HdcDeviceManager.disConnect(optValue).then(() => { 551 }); 552 this.deviceSelect!.removeChild(option); 553 if (SpRecordTrace.serialNumber == optValue) { 554 let options = this.deviceSelect!.options 555 if (options.length > 0) { 556 let selectedOpt = options[this.deviceSelect!.selectedIndex] 557 SpRecordTrace.serialNumber = selectedOpt.value; 558 } else { 559 SpRecordTrace.serialNumber = ''; 560 } 561 } 562 } 563 } 564 } 565 566 recordButtonListener() { 567 let request = this.makeRequest(); 568 if (request.pluginConfigs.length == 0) { 569 this.showHint = true; 570 return; 571 } else { 572 this.showHint = false; 573 } 574 let traceCommandStr = PluginConvertUtils.createHdcCmd( 575 PluginConvertUtils.BeanToCmdTxt(request, false), this.recordSetting!.output, this.recordSetting!.maxDur) 576 let selectedOption = this.deviceSelect!.options[this.deviceSelect!.selectedIndex] as HTMLOptionElement; 577 if (selectedOption) { 578 SpRecordTrace.serialNumber = selectedOption.value; 579 } else { 580 this.sp!.search = true; 581 this.litSearch!.clear(); 582 this.progressEL!.loading = false 583 this.litSearch!.setPercent("please connect device", -1); 584 } 585 if (this.vs) { 586 this.appContent!.innerHTML = "" 587 this.appContent!.append(this.traceCommand!) 588 let config = this.makeRequest(); 589 this.traceCommand!.hdcCommon = 590 PluginConvertUtils.createHdcCmd( 591 PluginConvertUtils.BeanToCmdTxt(config, false), this.recordSetting!.output, this.recordSetting!.maxDur) 592 this.freshMenuItemsStatus('Trace command') 593 Cmd.execHdcCmd(Cmd.formatString(CmdConstant.CMS_HDC_STOP, [SpRecordTrace.serialNumber]), (stopRes: string) => { 594 let cmd = Cmd.formatString(CmdConstant.CMD_MOUNT_DEVICES, [SpRecordTrace.serialNumber]); 595 Cmd.execHdcCmd(cmd, (res: string) => { 596 this.sp!.search = true; 597 this.progressEL!.loading = true 598 this.litSearch!.clear(); 599 this.litSearch!.setPercent("tracing " + this.recordSetting!.maxDur * 1000 + "ms", -1); 600 this.buttonDisable(true); 601 this.traceCommand!.show = true; 602 this.freshMenuDisable(true) 603 this.freshConfigMenuDisable(true) 604 Cmd.execHdcTraceCmd(traceCommandStr, SpRecordTrace.serialNumber, (traceResult: string) => { 605 if (traceResult.indexOf("DestroySession done") != -1) { 606 this.litSearch!.setPercent("tracing htrace down", -1); 607 let cmd = Cmd.formatString(CmdConstant.CMD_FIEL_RECV_DEVICES, [SpRecordTrace.serialNumber, this.recordSetting!.output]) 608 Cmd.execFileRecv(cmd, this.recordSetting!.output, (rt: ArrayBuffer) => { 609 this.litSearch!.setPercent("downloading Hitrace file ", 101); 610 let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf("/") + 1) 611 let file = new File([rt], fileName); 612 let main = this!.parentNode!.parentNode!.querySelector("lit-main-menu") as LitMainMenu 613 let children = main.menus as Array<MenuGroup>; 614 let child = children[0].children as Array<MenuItem> 615 let fileHandler = child[0].fileHandler; 616 if (fileHandler) { 617 this.freshMenuDisable(false) 618 this.freshConfigMenuDisable(false) 619 fileHandler({detail: file}) 620 } 621 }) 622 } else { 623 this.litSearch!.setPercent("tracing htrace failed, please check your config ", -1); 624 } 625 this.buttonDisable(false); 626 }) 627 }) 628 }) 629 } else { 630 HdcDeviceManager.connect(selectedOption.value).then(result => { 631 log("result is " + result); 632 if (result) { 633 this.appContent!.innerHTML = "" 634 this.appContent!.append(this.traceCommand!) 635 let config = this.makeRequest(); 636 this.traceCommand!.hdcCommon = 637 PluginConvertUtils.createHdcCmd( 638 PluginConvertUtils.BeanToCmdTxt(config, false), this.recordSetting!.output, this.recordSetting!.maxDur) 639 this.freshMenuItemsStatus('Trace command') 640 try { 641 HdcDeviceManager.stopHiprofiler(CmdConstant.CMS_STOP, true).then(() => { 642 HdcDeviceManager.shellResultAsString(CmdConstant.CMD_MOUNT, true).then(() => { 643 this.sp!.search = true; 644 this.progressEL!.loading = true 645 this.litSearch!.clear(); 646 this.litSearch!.setPercent("tracing " + this.recordSetting!.maxDur * 1000 + "ms", -1); 647 this.buttonDisable(true); 648 this.traceCommand!.show = true; 649 this.freshMenuDisable(true) 650 this.freshConfigMenuDisable(true) 651 HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false).then(traceResult => { 652 let re = this.isSuccess(traceResult) 653 if (re == 0) { 654 this.litSearch!.setPercent("tracing htrace down", -1); 655 HdcDeviceManager.shellResultAsString(CmdConstant.CMD_TRACE_FILE_SIZE + this.recordSetting!.output, false).then(traceFileSize => { 656 if (Number(traceFileSize) <= SpRecordTrace.MaxFileSize) { 657 HdcDeviceManager.fileRecv(this.recordSetting!.output, (perNumber: number) => { 658 this.litSearch!.setPercent("downloading Hitrace file ", perNumber); 659 }).then(pullRes => { 660 this.litSearch!.setPercent("downloading Hitrace file ", 101); 661 pullRes.arrayBuffer().then(buffer => { 662 let fileName = this.recordSetting!.output.substring(this.recordSetting!.output.lastIndexOf("/") + 1) 663 let file = new File([buffer], fileName); 664 let main = this!.parentNode!.parentNode!.querySelector("lit-main-menu") as LitMainMenu 665 let children = main.menus as Array<MenuGroup>; 666 let child = children[0].children as Array<MenuItem> 667 let fileHandler = child[0].fileHandler; 668 if (fileHandler) { 669 this.freshConfigMenuDisable(false); 670 this.freshMenuDisable(false) 671 fileHandler({detail: file}) 672 } 673 }) 674 }); 675 } else { 676 this.litSearch!.setPercent("htrace file is too big", -1); 677 } 678 }) 679 } else if (re == 2) { 680 this.litSearch!.setPercent("stop tracing htrace ", -1); 681 } else if (re == -1) { 682 this.litSearch!.setPercent("The device is abnormal", -1); 683 this.progressEL!.loading = false 684 } else { 685 this.litSearch!.setPercent("tracing htrace failed, please check your config ", -1); 686 } 687 this.freshConfigMenuDisable(false); 688 this.freshMenuDisable(false) 689 this.buttonDisable(false); 690 }); 691 }); 692 }) 693 } catch (e) { 694 this.traceCommand!.show = false; 695 this.freshMenuDisable(false) 696 this.freshConfigMenuDisable(false) 697 this.buttonDisable(false); 698 } 699 } else { 700 this.sp!.search = true; 701 this.litSearch!.clear(); 702 this.litSearch!.setPercent("please kill other hdc-server !", -1); 703 } 704 } 705 ); 706 } 707 708 } 709 710 private isSuccess(traceResult: string): number { 711 if (traceResult.indexOf("CreateSession FAIL") != -1) { 712 return 1; 713 } else if (traceResult.indexOf("Signal") != -1) { 714 return 2; 715 } else if (traceResult.indexOf("The device is abnormal") != -1) { 716 return -1 717 } else { 718 return 0; 719 } 720 } 721 722 private makeRequest = () => { 723 let request = this.createSessionRequest(); 724 let hasMonitorMemory = false; 725 let hasSamps = false; 726 if (this.probesConfig!.traceConfig.length > 0) { 727 if (this.probesConfig!.traceConfig.find(value => { 728 return value != "FPS" && value != "AbilityMonitor" && value != "HiSystemEvent" 729 })) { 730 request.pluginConfigs.push(this.createHtracePluginConfig()) 731 } 732 if (this.probesConfig!.traceConfig.indexOf("FPS") != -1) { 733 request.pluginConfigs.push(this.createFpsPluginConfig()) 734 } 735 if (this.probesConfig!.traceConfig.indexOf("AbilityMonitor") != -1) { 736 hasMonitorMemory = true; 737 this.createMonitorPlugin(this, request); 738 } 739 if (this.probesConfig!.traceConfig.indexOf("HiSystemEvent") != -1) { 740 request.pluginConfigs.push(this.createHiSystemEventPluginConfig()) 741 } 742 } 743 let reportingFrequency: number; 744 if (this.recordSetting!.maxDur > 20) { 745 reportingFrequency = 5 746 } else { 747 reportingFrequency = 2 748 } 749 if (this.spVmTracker!.startSamp && this.spVmTracker!.process != "") { 750 hasSamps = true; 751 } 752 if (this.probesConfig!.memoryConfig.length > 0 || hasMonitorMemory || hasSamps) { 753 request.pluginConfigs.push(this.createMemoryPluginConfig(reportingFrequency,this.probesConfig!.memoryConfig.length > 0, hasMonitorMemory, hasSamps)) 754 } 755 if (this.spAllocations!.appProcess != "") { 756 request.pluginConfigs.push(this.createNativePluginConfig(reportingFrequency)) 757 } 758 if (this.spRecordPerf!.startSamp) { 759 request.pluginConfigs.push(this.createHiperConfig(reportingFrequency)) 760 } 761 if (this.spFileSystem!.startRecord) { 762 request.pluginConfigs.push(this.createSystemConfig(reportingFrequency)) 763 } 764 if (this.spSdkConfig!.startSamp && this.spSdkConfig!.getPlugName() != "") { 765 request.pluginConfigs.push(this.createSdkConfig(reportingFrequency)) 766 } 767 return request; 768 } 769 770 private createSessionRequest() { 771 let bufferConfig: ProfilerSessionConfigBufferConfig = { 772 pages: this.recordSetting!.bufferSize * 256, 773 policy: ProfilerSessionConfigBufferConfigPolicy.RECYCLE 774 } 775 let sessionConfig: ProfilerSessionConfig = { 776 buffers: [bufferConfig], 777 sessionMode: ProfilerSessionConfigMode.OFFLINE, 778 resultFile: this.recordSetting!.output, 779 resultMaxSize: 0, 780 sampleDuration: this.recordSetting!.maxDur * 1000, 781 keepAliveTime: 0 782 } 783 let request: CreateSessionRequest = { 784 requestId: 1, 785 sessionConfig: sessionConfig, 786 pluginConfigs: [] 787 } 788 return request; 789 } 790 791 private createMonitorPlugin(that: this, request: CreateSessionRequest) { 792 let processPlugin = that.createProcessPlugin(); 793 let cpuPlugin = that.createCpuPlugin(); 794 let diskIoPlugin = that.createDiskIOPlugin(); 795 let netWorkPlugin = that.createNetworkPlugin(); 796 request.pluginConfigs.push(processPlugin) 797 request.pluginConfigs.push(cpuPlugin) 798 request.pluginConfigs.push(diskIoPlugin) 799 request.pluginConfigs.push(netWorkPlugin) 800 } 801 802 private createNetworkPlugin() { 803 let netWorkConfig: NetworkConfig = { 804 testFile: "/data/local/tmp/" 805 } 806 let netWorkPlugin: ProfilerPluginConfig<NetworkConfig> = { 807 pluginName: "network-plugin", 808 sampleInterval: 1000, 809 configData: netWorkConfig 810 } 811 return netWorkPlugin; 812 } 813 814 private createDiskIOPlugin() { 815 let diskIoConfig: DiskioConfig = { 816 reportIoStats: "IO_REPORT" 817 } 818 let diskIoPlugin: ProfilerPluginConfig<DiskioConfig> = { 819 pluginName: "diskio-plugin", 820 sampleInterval: 1000, 821 configData: diskIoConfig 822 } 823 return diskIoPlugin; 824 } 825 826 private createCpuPlugin() { 827 let cpuConfig: CpuConfig = { 828 pid: 0, 829 reportProcessInfo: true 830 } 831 let cpuPlugin: ProfilerPluginConfig<CpuConfig> = { 832 pluginName: "cpu-plugin", 833 sampleInterval: 1000, 834 configData: cpuConfig 835 } 836 return cpuPlugin; 837 } 838 839 private createProcessPlugin() { 840 let processConfig: ProcessConfig = { 841 report_process_tree: true, 842 report_cpu: true, 843 report_diskio: true, 844 report_pss: true, 845 } 846 let processPlugin: ProfilerPluginConfig<ProcessConfig> = { 847 pluginName: "process-plugin", 848 sampleInterval: 1000, 849 configData: processConfig 850 } 851 return processPlugin; 852 } 853 854 createTraceEvents(traceConfig: Array<string>): Array<string> { 855 let traceEvents = new Set<string>(); 856 traceConfig.forEach(config => { 857 switch (config) { 858 case "Scheduling details": 859 this.schedulingEvents.forEach((eve: string) => { 860 traceEvents.add(eve) 861 }); 862 break; 863 case "CPU Frequency and idle states": 864 this.cpuFreqEvents.forEach((eve: string) => { 865 traceEvents.add(eve) 866 }); 867 break; 868 case "High frequency memory": 869 this.highFrequencyEvents.forEach((eve: string) => { 870 traceEvents.add(eve) 871 }); 872 break; 873 case "Advanced ftrace config": 874 this.advancedConfigEvents.forEach((eve: string) => { 875 traceEvents.add(eve) 876 }); 877 break; 878 case "Syscalls": 879 this.sysCallsEvents.forEach((eve: string) => { 880 traceEvents.add(eve) 881 }); 882 break; 883 case "Board voltages & frequency": 884 this.powerEvents.forEach((eve: string) => { 885 traceEvents.add(eve) 886 }); 887 break; 888 } 889 } 890 ) 891 let ftraceEventsArray: string[] = []; 892 info("traceEvents length is: ", traceEvents.size) 893 for (const ftraceEvent of traceEvents) { 894 ftraceEventsArray.push(ftraceEvent) 895 } 896 return ftraceEventsArray 897 } 898 899 initHtml(): string { 900 return ` 901 <style> 902 :host{ 903 display: block; 904 height: 100%; 905 width: 100%; 906 background-color: var(--dark-background5,#F6F6F6); 907 } 908 .container { 909 background-color: var(--dark-background5,#F6F6F6); 910 height:100%; 911 } 912 913 .header { 914 padding-top: 30px; 915 padding-bottom: 20px; 916 background-color: var(--dark-background3,#FFFFFF); 917 width: 100%; 918 } 919 920 .span-col-2{ 921 margin-left: 20px; 922 display: flex; 923 align-items: center 924 } 925 926 .header-right { 927 display: flex; 928 margin-left: auto; 929 margin-right: 5%; 930 } 931 .header-des{ 932 font-family: PingFangSC-Regular; 933 font-size: 1em; 934 color: #999999; 935 text-align: left; 936 font-weight: 400; 937 } 938 939 .target { 940 opacity: 0.9; 941 font-family: Helvetica; 942 font-size: 14px; 943 color: var(--dark-color2,#000000); 944 line-height: 16px; 945 font-weight: 400; 946 white-space:nowrap; 947 align-self: center; 948 } 949 950 .select{ 951 width: 300px; 952 height: 32px; 953 margin-left: 14px; 954 margin-right: 24px; 955 background: var(--dark-background1,#ffffff); 956 border: 1px solid var(--dark-color1,#4D4D4D); 957 border-radius: 16px; 958 opacity: 0.6; 959 font-family: Helvetica; 960 font-size: 14px; 961 color: var(--dark-color1,#000000); 962 text-align: center; 963 line-height: 20px; 964 font-weight: 400; 965 padding: 5px 10px 5px 10px; 966 -webkit-appearance: none; 967 background: url('img/down.png') no-repeat 96% center; 968 } 969 .body{ 970 width: 90%; 971 height:80vh; 972 margin-left: 3%; 973 margin-top: 2%; 974 margin-bottom: 2%; 975 display: grid; 976 grid-template-columns: min-content 1fr; 977 background-color: var(--dark-background3,#FFFFFF); 978 border-radius: 16px 16px 16px 16px; 979 } 980 981 .menugroup{ 982 height: 100%; 983 background: var(--dark-background3,#FFFFFF); 984 } 985 .menuitem{ 986 background: var(--dark-background3,#FFFFFF); 987 } 988 .content{ 989 background: var(--dark-background3,#FFFFFF); 990 border-style: none none none solid; 991 border-width: 1px; 992 border-color: rgba(166,164,164,0.2); 993 border-radius: 0px 16px 16px 0px; 994 } 995 :host([show_hint]) #hint { 996 display: block 997 } 998 #hint { 999 display: none; 1000 } 1001 1002 </style> 1003 <div class="container"> 1004 <div class="header"> 1005 <div style="display: flex;margin-bottom: 24px;margin-left:20px;"> 1006 <span class="target">Target Platform:</span> 1007 <select class="select" id = "device-select"> 1008 </select> 1009 <lit-button style="width: 180px"class="add" height="32px" width="164px" color="#0A59F7" font_size="14px" border="1px solid #0A59F7" 1010 padding="0 0 0 12px" justify_content="left" icon="add" margin_icon="0 10px 0 8px">Add HDC Device</lit-button> 1011 <div class="header-right"> 1012 <lit-button class="record" height="32px" width="96px" font_size="14px" justify_content="center" color="#FFFFFF" 1013 border_radius="16px" back='#0A59F7'>Record</lit-button> 1014 </div> 1015 </div> 1016 <div class="span-col-2" > 1017 <span class="header-des" id="hint">It looks like you didn't add any probes. Please add at least one</span> 1018 </div> 1019 </div> 1020 1021 <div class="body"> 1022 <lit-main-menu-group class="menugroup" id= "menu-group" title="" nocollapsed radius></lit-main-menu-group> 1023 <div id="app-content" class="content"> 1024 </div> 1025 </div> 1026 </div> 1027 `; 1028 } 1029 1030 private createHilogConfig(probesConfig: SpProbesConfig, reportingFrequency: number) { 1031 let hilogConfig: HilogConfig = { 1032 deviceType: Type.HI3516, 1033 logLevel: levelFromJSON(probesConfig.hilogConfig[0]), 1034 needClear: true 1035 } 1036 let hilogConfigProfilerPluginConfig: ProfilerPluginConfig<HilogConfig> = { 1037 pluginName: "hilog-plugin", 1038 sampleInterval: reportingFrequency * 1000, 1039 configData: hilogConfig, 1040 } 1041 return hilogConfigProfilerPluginConfig; 1042 } 1043 1044 private createHiperConfig(reportingFrequency: number) { 1045 let perfConfig = this.spRecordPerf!.getPerfConfig(); 1046 let recordArgs = ""; 1047 recordArgs = recordArgs + "-f " + perfConfig?.frequency; 1048 if (perfConfig?.process && !perfConfig?.process.includes("ALL") && perfConfig?.process.length > 0) { 1049 recordArgs = recordArgs + " -p " + perfConfig?.process; 1050 } else { 1051 recordArgs = recordArgs + " -a "; 1052 } 1053 if (perfConfig?.cpu && !perfConfig?.cpu.includes("ALL") && perfConfig?.cpu.length > 0) { 1054 recordArgs = recordArgs + " -c " + perfConfig?.cpu; 1055 } 1056 if (perfConfig?.cpuPercent != 0) { 1057 recordArgs = recordArgs + " --cpu-limit " + perfConfig?.cpuPercent; 1058 } 1059 if (perfConfig?.eventList && !perfConfig?.eventList.includes("NONE") && perfConfig?.eventList.length > 0) { 1060 recordArgs = recordArgs + " -e " + perfConfig?.eventList; 1061 if (perfConfig?.isOffCpu) { 1062 recordArgs = recordArgs + ",sched:sched_waking"; 1063 } 1064 } else { 1065 recordArgs = recordArgs + " -e hw-cpu-cycles" 1066 if (perfConfig?.isOffCpu) { 1067 recordArgs = recordArgs + ",sched:sched_waking"; 1068 } 1069 } 1070 if (perfConfig?.callStack != "none") { 1071 recordArgs = recordArgs + " --call-stack " + perfConfig?.callStack 1072 } 1073 1074 if (perfConfig?.branch != "none") { 1075 recordArgs = recordArgs + " -j " + perfConfig?.branch 1076 } 1077 1078 if (perfConfig?.clockType) { 1079 recordArgs = recordArgs + " --clockid " + perfConfig?.clockType 1080 } 1081 1082 if (perfConfig?.isOffCpu) { 1083 recordArgs = recordArgs + " --offcpu" 1084 } 1085 1086 if (perfConfig?.noInherit) { 1087 recordArgs = recordArgs + " --no-inherit" 1088 } 1089 1090 if (perfConfig?.mmap) { 1091 recordArgs = recordArgs + " -m " + perfConfig.mmap; 1092 } 1093 info("record config Args is: ", recordArgs) 1094 let hiPerf: HiperfPluginConfig = { 1095 isRoot: false, 1096 outfileName: "/data/local/tmp/perf.data", 1097 recordArgs: recordArgs 1098 } 1099 let hiPerfPluginConfig: ProfilerPluginConfig<HiperfPluginConfig> = { 1100 pluginName: "hiperf-plugin", 1101 sampleInterval: reportingFrequency * 1000, 1102 configData: hiPerf, 1103 } 1104 return hiPerfPluginConfig; 1105 } 1106 1107 private createSystemConfig(reportingFrequency: number) { 1108 let systemConfig = this.spFileSystem!.getSystemConfig(); 1109 let recordArgs = "hiebpf"; 1110 if (this.spFileSystem?.startFileSystem && this.spFileSystem?.startVirtualMemory) { 1111 recordArgs += " --events fs,ptrace " 1112 } else if (this.spFileSystem?.startFileSystem) { 1113 recordArgs += " --events fs " 1114 } else if (this.spFileSystem?.startVirtualMemory) { 1115 recordArgs += " --events ptrace " 1116 } 1117 recordArgs += "--duration " + this.recordSetting?.maxDur 1118 if (systemConfig?.process && !systemConfig?.process.includes("ALL") && systemConfig?.process.length > 0) { 1119 recordArgs = recordArgs + " --pids " + systemConfig?.process; 1120 } 1121 let systemPluginConfig: FileSystemConfig = { 1122 cmdLine: recordArgs, 1123 outfileName: "/data/local/tmp/ebpf.data", 1124 } 1125 let ebpfPluginConfig: ProfilerPluginConfig<FileSystemConfig> = { 1126 pluginName: "hiebpf-plugin", 1127 sampleInterval: 1000, 1128 configData: systemPluginConfig, 1129 } 1130 return ebpfPluginConfig; 1131 } 1132 1133 private createNativePluginConfig(reportingFrequency: number) { 1134 let appProcess = this.spAllocations!.appProcess; 1135 let re = /^[0-9]+.?[0-9]*/; 1136 let pid = 0; 1137 let processName = ""; 1138 let processId = ""; 1139 if (appProcess.indexOf("(") != -1) { 1140 processId = appProcess.slice(appProcess.lastIndexOf("(") + 1, appProcess.lastIndexOf(")")) 1141 } else { 1142 processId = appProcess; 1143 } 1144 if (re.test(processId)) { 1145 pid = Number(processId); 1146 } else { 1147 processName = appProcess; 1148 } 1149 let nativeConfig: NativeHookConfig = { 1150 pid: pid, 1151 saveFile: false, 1152 fileName: "", 1153 filterSize: this.spAllocations!.filter, 1154 smbPages: this.spAllocations!.shared, 1155 maxStackDepth: this.spAllocations!.unwind, 1156 processName: processName, 1157 mallocFreeMatchingInterval: 1000, 1158 mallocFreeMatchingCnt: 1000, 1159 stringCompressed: true, 1160 fpUnwind: this.spAllocations!.fp_unwind 1161 } 1162 let nativePluginConfig: ProfilerPluginConfig<NativeHookConfig> = { 1163 pluginName: "nativehook", 1164 sampleInterval: reportingFrequency * 1000, 1165 configData: nativeConfig, 1166 } 1167 return nativePluginConfig; 1168 } 1169 1170 private createMemoryPluginConfig(reportingFrequency: number, hasmemoryConfig: boolean, hasMonitorMemory: boolean, hasSmaps: boolean) { 1171 let memoryconfig: MemoryConfig = { 1172 reportProcessTree: false, 1173 reportSysmemMemInfo: false, 1174 sysMeminfoCounters: [], 1175 reportSysmemVmemInfo: false, 1176 sysVmeminfoCounters: [], 1177 reportProcessMemInfo: false, 1178 reportAppMemInfo: false, 1179 reportAppMemByMemoryService: false, 1180 pid: [] 1181 } 1182 if (hasmemoryConfig || hasMonitorMemory) { 1183 memoryconfig.reportProcessTree = true; 1184 memoryconfig.reportSysmemMemInfo = true; 1185 memoryconfig.reportSysmemVmemInfo = true; 1186 memoryconfig.reportProcessMemInfo = true; 1187 } 1188 if (hasSmaps) { 1189 memoryconfig.reportSmapsMemInfo = true 1190 let pid = Number(this.spVmTracker?.process); 1191 memoryconfig.pid.push(pid) 1192 } 1193 if (hasMonitorMemory) { 1194 SpRecordTrace.ABALITY_MEM_INFO.forEach(va => { 1195 memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); 1196 }) 1197 } 1198 this.probesConfig!.memoryConfig.forEach(value => { 1199 if (value.indexOf("Kernel meminfo") != -1) { 1200 if (hasMonitorMemory) { 1201 memoryconfig.sysMeminfoCounters = []; 1202 } 1203 SpRecordTrace.MEM_INFO.forEach(va => { 1204 memoryconfig.sysMeminfoCounters.push(sysMeminfoTypeFromJSON(va)); 1205 }) 1206 } 1207 if (value.indexOf("Virtual memory stats") != -1) { 1208 SpRecordTrace.VMEM_INFO.forEach((me => { 1209 memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) 1210 })) 1211 SpRecordTrace.VMEM_INFO_SECOND.forEach((me => { 1212 memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) 1213 })) 1214 SpRecordTrace.VMEM_INFO_THIRD.forEach((me => { 1215 memoryconfig.sysVmeminfoCounters.push(sysVMeminfoTypeFromJSON(me)) 1216 })) 1217 } 1218 }) 1219 let profilerPluginConfig: ProfilerPluginConfig<MemoryConfig> = { 1220 pluginName: "memory-plugin", 1221 sampleInterval: reportingFrequency * 1000, 1222 configData: memoryconfig, 1223 } 1224 return profilerPluginConfig; 1225 } 1226 1227 private createFpsPluginConfig() { 1228 let fpsConfig: FpsConfig = { 1229 reportFps: true 1230 } 1231 let fpsPlugin: ProfilerPluginConfig<FpsConfig> = { 1232 pluginName: "hidump-plugin", 1233 sampleInterval: 1000, 1234 configData: fpsConfig 1235 } 1236 return fpsPlugin; 1237 } 1238 1239 private createHiSystemEventPluginConfig() { 1240 let hiSystemEventConfig: HiSystemEventConfig = { 1241 msg: '' 1242 } 1243 let hiSystemEventPlugin: ProfilerPluginConfig<HiSystemEventConfig> = { 1244 pluginName: "hisysevent-plugin", 1245 sampleInterval: 1000, 1246 configData: hiSystemEventConfig 1247 } 1248 return hiSystemEventPlugin; 1249 } 1250 1251 private createHtracePluginConfig() { 1252 let tracePluginConfig: TracePluginConfig = { 1253 ftraceEvents: this.createTraceEvents(this.probesConfig!.traceConfig), 1254 hitraceCategories: [], 1255 hitraceApps: [], 1256 bufferSizeKb: 2048, 1257 flushIntervalMs: 1000, 1258 flushThresholdKb: 4096, 1259 parseKsyms: true, 1260 clock: "mono", 1261 tracePeriodMs: 200, 1262 rawDataPrefix: "", 1263 traceDurationMs: 0, 1264 debugOn: false, 1265 hitraceTime: this.recordSetting!.maxDur 1266 } 1267 if (this.probesConfig!.traceEvents.length > 0) { 1268 tracePluginConfig.hitraceCategories = this.probesConfig!.traceEvents 1269 } 1270 let htraceProfilerPluginConfig: ProfilerPluginConfig<TracePluginConfig> = { 1271 pluginName: "ftrace-plugin", 1272 sampleInterval: 1000, 1273 configData: tracePluginConfig 1274 } 1275 return htraceProfilerPluginConfig; 1276 } 1277 1278 private createSdkConfig(reportingFrequency: number) { 1279 let gpuConfig = this.spSdkConfig!.getGpuConfig(); 1280 let gpuPluginConfig: ProfilerPluginConfig<any> = { 1281 pluginName: this.spSdkConfig!.getPlugName(), 1282 sampleInterval: this.spSdkConfig!.getSampleInterval(), 1283 configData: gpuConfig, 1284 } 1285 return gpuPluginConfig; 1286 } 1287 1288 1289 freshConfigMenuDisable(disable: boolean) { 1290 let querySelectors = this.shadowRoot?.querySelectorAll<LitMainMenuItem>('lit-main-menu-item') 1291 querySelectors!.forEach(item => { 1292 if (disable) { 1293 item.style.pointerEvents = 'none' 1294 this.traceCommand!.show = true; 1295 } else { 1296 item.style.pointerEvents = 'auto' 1297 this.traceCommand!.show = false; 1298 } 1299 item.disabled = disable; 1300 }) 1301 } 1302 1303 public startRefreshDeviceList() { 1304 if (this.refreshDeviceTimer == null) { 1305 this.refreshDeviceTimer = setInterval(() => { 1306 this.refreshDeviceList(); 1307 }, 5000) 1308 } 1309 } 1310 1311 buttonDisable(disable: boolean) { 1312 if (disable) { 1313 this.recordButton!.style.pointerEvents = 'none'; 1314 this.addButton!.style.pointerEvents = 'none'; 1315 this.deviceSelect!.style.pointerEvents = 'none'; 1316 } else { 1317 this.recordButton!.style.pointerEvents = 'auto'; 1318 this.addButton!.style.pointerEvents = 'auto'; 1319 this.deviceSelect!.style.pointerEvents = 'auto'; 1320 } 1321 } 1322 1323 freshMenuItemsStatus(currentValue: string) { 1324 let litMainMenuGroup = this.shadowRoot?.querySelector<LitMainMenuGroup>('lit-main-menu-group'); 1325 let litMainMenuItemNodeListOf = litMainMenuGroup!.querySelectorAll<LitMainMenuItem>('lit-main-menu-item'); 1326 litMainMenuItemNodeListOf.forEach(item =>{ 1327 item.back = item.title == currentValue; 1328 }) 1329 } 1330}