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 unknown KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { SpSystemTrace } from './SpSystemTrace'; 17import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample'; 18import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample'; 19import { RangeSelect } from './trace/base/RangeSelect'; 20import { TraceRow } from './trace/base/TraceRow'; 21import { SportRuler } from './trace/timer-shaft/SportRuler'; 22import { SelectionParam } from '../bean/BoxSelection'; 23import { error, info } from '../../log/Log'; 24import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; 25import { queryEbpfSamplesCount, queryPlugins } from '../database/sql/Memory.sql'; 26import { SpChartManager } from './chart/SpChartManager'; 27import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; 28import { FlagsConfig } from './SpFlags'; 29import { threadPool, threadPool2 } from '../database/SqlLite'; 30import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; 31import { CpuStruct } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; 32import { PairPoint } from '../database/ui-worker/ProcedureWorkerCommon'; 33import { TraceSheet } from './trace/base/TraceSheet'; 34import { TimerShaftElement } from './trace/TimerShaftElement'; 35import { SpChartList } from './trace/SpChartList'; 36type HTMLElementAlias = HTMLElement | null | undefined; 37import { Utils } from './trace/base/Utils'; 38import { fuzzyQueryFuncRowData, queryFuncRowData } from '../database/sql/Func.sql'; 39import { convertTitle } from './chart/SpXpowerChart'; 40 41// 所有插件以及对应的表 42const pluginArray = [ 43 { 44 pluginName: 'ftrace-plugin', 45 tables: [ 46 'animation', 'app_startup', 'args', 'callstack', 'clk_event_filter', 47 'clock_event_filter', 'cpu_measure_filter', 'device_info', 'dynamic_frame', 'frame_maps', 48 'frame_slice', 'gpu_slice', 'instant', 'irq', 'process_measure_filter', 'process_measure', 49 'sched_slice', 'static_initalize', 'symbols', 'syscall', 'task_pool', 'thread_state', 'dma_fence' 50 ] 51 }, 52 { 53 pluginName: 'hiperf-plugin', 54 tables: [ 55 'perf_callchain', 'perf_files', 'perf_report', 'perf_sample', 'perf_thread' 56 ] 57 }, 58 { 59 pluginName: 'nativehook-plugin', 60 tables: [ 61 'native_hook', 'native_hook_frame', 'native_hook_statistic' 62 ] 63 }, 64 { 65 pluginName: 'arkTs-plugin', 66 tables: [ 67 'js_config', 'js_cpu_profiler_node', 'js_cpu_profiler_sample', 'js_heap_files', 'js_heap_info', 'js_heap_location', 68 'js_heap_nodes', 'js_heap_sample', 'js_heap_string', 'js_heap_trace_function_info', 'js_heap_trace_node', 'js_heap_edges' 69 ] 70 }, 71 { 72 pluginName: 'memory-plugin', 73 tables: [ 74 'memory_ashmem', 'memory_cpu', 'memory_dma', 'memory_process_gpu', 'memory_profile,', 'memory_rs_image', 'memory_window_gpu', 'smaps', 'sys_event_filter', 'sys_mem_measure' 75 ] 76 }, 77 { 78 pluginName: 'hisysevent-plugin', 79 tables: [ 80 'app_name', 'device_state', 'hisys_all_event', 'hisys_event_measure' 81 ] 82 }, 83 { 84 pluginName: 'ebpf-plugin', 85 tables: [ 86 'bio_latency_sample', 'ebpf_callstack', 'file_system_sample', 'paged_memory_sample' 87 ] 88 }, 89 { 90 pluginName: 'cpu-plugin', 91 tables: [ 92 'cpu_usage' 93 ] 94 }, 95 { 96 pluginName: 'diskio-plugin', 97 tables: [ 98 'diskio' 99 ] 100 }, 101 { 102 pluginName: 'hidump-plugin', 103 tables: [ 104 'hidump' 105 ] 106 }, 107 { 108 pluginName: 'process-plugin', 109 tables: [ 110 'live_process' 111 ] 112 }, 113 { 114 pluginName: 'hilog-plugin', 115 tables: [ 116 'log' 117 ] 118 }, 119 { 120 pluginName: 'network-plugin', 121 tables: [ 122 'network' 123 ] 124 }, 125 { 126 pluginName: 'xpower-plugin', 127 tables: [ 128 'xpower_measure' 129 ] 130 } 131]; 132 133function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unknown { 134 Object.assign(sp, { 135 ext(): string { 136 return 'Handle the right button click event'; 137 }, 138 }); 139 140 return function (event: unknown): void { 141 if (SpSystemTrace.btnTimer) { 142 return; 143 } 144 sp.checkclick = true; 145 // 唤醒树有值则不再重复添加 146 const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('['); 147 if (SpSystemTrace.wakeupList.length === 0) { 148 SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); 149 sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); 150 CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; 151 CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; 152 CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; 153 CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName; 154 CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; 155 sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); 156 } else { 157 sp.wakeupListNull(); 158 SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); 159 sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); 160 CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; 161 CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; 162 CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; 163 CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName; 164 CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; 165 sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); 166 } 167 let rightButton: HTMLElement | null | undefined = sp.traceSheetEL?.shadowRoot 168 ?.querySelector('#current-selection > tabpane-current-selection') 169 ?.shadowRoot?.querySelector('#rightButton'); 170 rightButton?.blur(); 171 setTimeout(() => { 172 requestAnimationFrame(() => sp.refreshCanvas(false)); 173 }, 300); 174 rightStar!.style.visibility = 'visible'; 175 rightStar!.style.cursor = 'pointer'; 176 SpSystemTrace.btnTimer = setTimeout((): void => { 177 SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器 178 }, 2000); 179 }; 180} 181function rightStarOnClick(sp: SpSystemTrace) { 182 return function (ev: unknown): void { 183 let wakeupLists = []; 184 wakeupLists.push(CpuStruct.selectCpuStruct?.cpu); 185 for (let wakeupBean of SpSystemTrace.wakeupList) { 186 wakeupLists.push(wakeupBean.cpu); 187 } 188 let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort(); 189 for (let wakeupCpu of wakeupCpuLists) { 190 // @ts-ignore 191 let cpuFavoriteRow: unknown = sp.shadowRoot?.querySelector<TraceRow<unknown>>( 192 `trace-row[row-type='cpu-data'][row-id='${Utils.getDistributedRowId(wakeupCpu)}']` 193 ); 194 if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) { 195 continue; 196 } 197 // @ts-ignore 198 cpuFavoriteRow!.setAttribute('collect-type', ''); 199 let replaceRow = document.createElement('div'); 200 // @ts-ignore 201 replaceRow.setAttribute('row-id', `${cpuFavoriteRow.rowId}-${cpuFavoriteRow.rowType}`); 202 replaceRow.setAttribute('type', 'replaceRow'); 203 // @ts-ignore 204 replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId); 205 replaceRow.style.display = 'none'; 206 // @ts-ignore 207 cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene'); 208 // @ts-ignore 209 if (sp.rowsEL!.contains(cpuFavoriteRow)) { 210 // @ts-ignore 211 sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow); 212 } 213 // @ts-ignore 214 cpuFavoriteRow.tampName = cpuFavoriteRow.name; 215 // @ts-ignore 216 sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, cpuFavoriteRow.traceId || sp.currentCollectGroup, true); 217 // @ts-ignore 218 sp.collectRows.push(cpuFavoriteRow); 219 sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); 220 sp.currentClickRow = null; 221 // @ts-ignore 222 cpuFavoriteRow.setAttribute('draggable', 'true'); 223 // @ts-ignore 224 cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp, cpuFavoriteRow)); 225 // @ts-ignore 226 cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp)); 227 // @ts-ignore 228 cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp, cpuFavoriteRow)); 229 // @ts-ignore 230 cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp)); 231 } 232 sp.refreshFavoriteCanvas(); 233 sp.refreshCanvas(true); 234 }; 235} 236function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: unknown) { 237 return function (): void { 238 // @ts-ignore 239 sp.currentClickRow = cpuFavoriteRow; 240 }; 241} 242function cpuFavoriteRowDragOver(sp: SpSystemTrace) { 243 return function (ev: unknown): void { 244 // @ts-ignore 245 ev.preventDefault(); 246 // @ts-ignore 247 ev.dataTransfer.dropEffect = 'move'; 248 }; 249} 250function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: unknown) { 251 return function (ev: unknown): void { 252 if (sp.favoriteChartListEL && sp.currentClickRow && sp.currentClickRow !== cpuFavoriteRow) { 253 // @ts-ignore 254 let rect = cpuFavoriteRow.getBoundingClientRect(); 255 // @ts-ignore 256 if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { 257 //向上移动 258 // @ts-ignore 259 sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow); 260 // @ts-ignore 261 } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { 262 //向下移动 263 // @ts-ignore 264 sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling); 265 } 266 sp.refreshFavoriteCanvas(); 267 } 268 }; 269} 270function cpuFavoriteRowDragendHandler(sp: SpSystemTrace): () => void { 271 return function (): void { 272 sp.linkNodes.forEach((itln) => { 273 if (itln[0].rowEL.collect) { 274 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 275 } else { 276 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 277 } 278 if (itln[1].rowEL.collect) { 279 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 280 } else { 281 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 282 } 283 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 284 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 285 }); 286 sp.currentClickRow = null; 287 }; 288} 289function triangleFlagHandler(sp: SpSystemTrace): (event: unknown) => void { 290 return function (event: unknown): void { 291 //@ts-ignore 292 let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); 293 //@ts-ignore 294 if (event.detail.timeCallback && temporaryTime) { 295 //@ts-ignore 296 event.detail.timeCallback(temporaryTime); 297 } 298 }; 299} 300function numberCalibrationHandler(sp: SpSystemTrace): (event: unknown) => void { 301 return function (event: unknown): void { 302 // @ts-ignore 303 sp.timerShaftEL!.sportRuler!.times = event.detail.time; 304 // @ts-ignore 305 sp.timerShaftEL!.sportRuler!.counts = event.detail.counts; 306 // @ts-ignore 307 sp.timerShaftEL!.sportRuler!.durations = event.detail.durations; 308 sp.timerShaftEL!.sportRuler?.draw(); 309 }; 310} 311function flagChangeHandler(sp: SpSystemTrace): (event: unknown) => void { 312 return function (event: unknown): void { 313 // @ts-ignore 314 sp.timerShaftEL?.modifyFlagList(event.detail); 315 // @ts-ignore 316 if (event.detail.hidden) { 317 //@ts-ignore 318 sp.selectFlag = undefined; 319 if (sp._flagList.length <= 0) { 320 let showTab = sp.getShowTab(); 321 showTab = showTab.filter((it) => it !== 'box-flag'); 322 if (TraceRow.rangeSelectObject && showTab.length > 0) { 323 sp.traceSheetEL?.displayTab(...showTab); 324 } else { 325 sp.traceSheetEL?.setMode('hidden'); 326 } 327 } 328 sp.refreshCanvas(true); 329 } 330 }; 331} 332function slicesChangeHandler(sp: SpSystemTrace): (event: unknown) => void { 333 return function (event: unknown): void { 334 // @ts-ignore 335 sp.timerShaftEL?.modifySlicesList(event.detail); 336 // @ts-ignore 337 if (event.detail.hidden) { 338 sp.slicestime = null; 339 if (sp._slicesList.length <= 0) { 340 let showTab = sp.getShowTab(); 341 showTab = showTab.filter((it) => it !== 'tabpane-current'); 342 if (TraceRow.rangeSelectObject && showTab.length > 0) { 343 sp.traceSheetEL?.displayTab(...showTab); 344 } else { 345 sp.traceSheetEL?.setMode('hidden'); 346 } 347 } 348 sp.refreshCanvas(true); 349 } 350 }; 351} 352function collectHandler(sp: SpSystemTrace): (event: unknown) => void { 353 return function (event: unknown): void { 354 // @ts-ignore 355 let currentRow = event.detail.row; 356 if (currentRow.collect) { 357 collectHandlerYes(sp, currentRow, event); 358 } else { 359 collectHandlerNo(sp, currentRow, event); 360 } 361 sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); 362 sp.refreshFavoriteCanvas(); 363 sp.refreshCanvas(true); 364 sp.linkNodes.forEach((itln) => { 365 if (itln[0].rowEL === currentRow) { 366 if (itln[0].rowEL.collect) { 367 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 368 } else { 369 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 370 } 371 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 372 } else if (itln[1].rowEL === currentRow) { 373 if (itln[1].rowEL.collect) { 374 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 375 } else { 376 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 377 } 378 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 379 } 380 }); 381 // 收藏夹元素拖动排序功能 382 sp.currentClickRow = null; 383 currentRow.setAttribute('draggable', 'true'); 384 currentRow.addEventListener('dragstart', () => { 385 sp.currentClickRow = currentRow; 386 }); 387 currentRow.addEventListener('dragover', (ev: unknown) => { 388 // @ts-ignore 389 ev.preventDefault(); 390 // @ts-ignore 391 ev.dataTransfer.dropEffect = 'move'; 392 }); 393 currentRow.addEventListener('drop', collectHandlerDrop(sp, currentRow)); 394 currentRow.addEventListener('dragend', collectHandlerDragEnd(sp)); 395 }; 396} 397function collectHandlerNo(sp: SpSystemTrace, currentRow: unknown, event: unknown): void { 398 // @ts-ignore 399 sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect'); 400 // @ts-ignore 401 if (event.detail.type !== 'auto-collect') { 402 // @ts-ignore 403 let rowIndex = sp.collectRows.indexOf(currentRow); 404 if (rowIndex !== -1) { 405 sp.collectRows.splice(rowIndex, 1); 406 } 407 } 408 let row = currentRow; 409 let allowExpansionRow = []; 410 // @ts-ignore 411 while (row.hasParentRowEl) { 412 // @ts-ignore 413 let parent = row.parentRowEl; 414 allowExpansionRow.push(parent); 415 row = parent; 416 } 417 if (allowExpansionRow.length === 1) { 418 for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { 419 if (allowExpansionRow[index]?.hasAttribute('scene')) { 420 if (allowExpansionRow[index]!.expansion) { 421 allowExpansionRow[index].updateChildRowStatus(); 422 } else { 423 allowExpansionRow[index].expansion = true; 424 } 425 } 426 } 427 } else { 428 for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { 429 let currentItemRow = allowExpansionRow[index]; 430 if (currentItemRow.hasAttribute('scene')) { 431 if (currentItemRow.rowParentId !== '') { 432 if (currentItemRow.expansion) { 433 currentItemRow.updateChildRowStatus(); 434 } else { 435 currentItemRow.expansion = true; 436 } 437 } 438 else { 439 currentItemRow.expansion = true; 440 let number = currentItemRow.childrenList.indexOf(currentRow); 441 if (number !== -1) {// 确保 currentRow 在 childrenList 中 442 let childrenEl = currentItemRow.childrenList[number]; 443 let childrenNextEl = currentItemRow.childrenList[number + 1]; 444 if (childrenEl) { 445 if (childrenNextEl) { 446 currentItemRow.parentNode.insertBefore(childrenEl, currentItemRow.childrenList[number + 1]); 447 } else if (childrenEl.nextSibling) { 448 currentItemRow.parentNode.insertBefore(childrenEl, childrenEl.nextSibling); 449 } else { 450 currentItemRow.parentNode.appendChild(childrenEl); 451 } 452 } 453 } 454 } 455 } 456 } 457 } 458 allowExpansionRow.length = 0; 459 // @ts-ignore 460 let traceId = currentRow.traceId ? `${currentRow.traceId}-` : ''; 461 let replaceRow = sp.rowsEL!.querySelector<HTMLCanvasElement>( 462 // @ts-ignore 463 `div[row-id='${traceId}${currentRow.rowId}-${currentRow.rowType}']` 464 ); 465 // 取消收藏时,删除父亲ID 466 // @ts-ignore 467 currentRow.name = currentRow.tampName; 468 //@ts-ignore xpower转换名称 469 if (currentRow.rowType === 'xpower-system') { 470 //@ts-ignore 471 let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement; 472 //@ts-ignore 473 titleEl.title = convertTitle(currentRow.tampName); 474 } 475 if (replaceRow !== null) { 476 // @ts-ignore 477 sp.rowsEL!.replaceChild(currentRow, replaceRow); 478 // @ts-ignore 479 currentRow.style.boxShadow = '0 10px 10px #00000000'; 480 } 481} 482function collectHandlerYes(sp: SpSystemTrace, currentRow: unknown, event: unknown): void { 483 if (!sp.collectRows.find((find) => find === currentRow)) { 484 // @ts-ignore 485 sp.collectRows.push(currentRow); 486 } 487 let replaceRow = document.createElement('div'); 488 // @ts-ignore 489 let traceId = currentRow.traceId ? `${currentRow.traceId}-` : ''; 490 // @ts-ignore 491 replaceRow.setAttribute('row-id', `${traceId}${currentRow.rowId}-${currentRow.rowType}`); 492 replaceRow.setAttribute('type', 'replaceRow'); 493 // @ts-ignore 494 replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); 495 replaceRow.style.display = 'none'; 496 // @ts-ignore 497 if (!currentRow.hasAttribute('scene')) { 498 // @ts-ignore 499 currentRow.setAttribute('row-hidden', ''); 500 } else { 501 // @ts-ignore 502 currentRow.removeAttribute('row-hidden'); 503 } 504 // 添加收藏时,在线程名前面追加父亲ID 505 // @ts-ignore 506 let rowParentId = currentRow.rowParentId; 507 // @ts-ignore 508 currentRow.tampName = currentRow.name; 509 if (rowParentId) { 510 // @ts-ignore 511 let parentRows = sp.shadowRoot?.querySelectorAll<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}']`); 512 parentRows?.forEach((parentRow) => { 513 if ( 514 parentRow?.name && 515 // @ts-ignore 516 parentRow?.name !== currentRow.name && 517 !parentRow.rowType!.startsWith('cpu') && 518 !parentRow.rowType!.startsWith('thread') && 519 !parentRow.rowType!.startsWith('func') && 520 // @ts-ignore 521 !currentRow.name.includes(parentRow.name) 522 ) { 523 //@ts-ignore 524 currentRow.name = currentRow.protoParentId ? `${currentRow.name} (${currentRow.protoParentId})` : 525 //@ts-ignore 526 `${currentRow.name} (${parentRow.name})`; 527 } 528 }); 529 } 530 // @ts-ignore 531 if (!currentRow.hasParentRowEl) { 532 // @ts-ignore 533 sp.rowsEL!.replaceChild(replaceRow, currentRow); 534 } 535 //@ts-ignore xpower转换名称 536 if (currentRow.rowType === 'xpower-system') { 537 //@ts-ignore 538 let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement; 539 //@ts-ignore 540 titleEl.title = convertTitle(currentRow.tampName); 541 } 542 // @ts-ignore 543 let group = currentRow.traceId || sp.currentCollectGroup; 544 // @ts-ignore 545 sp.favoriteChartListEL?.insertRow(currentRow, group, event.detail.type !== 'auto-collect'); 546} 547function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null): (ev: unknown) => void { 548 return function (ev: unknown) { 549 if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) { 550 // @ts-ignore 551 let rect = currentRow!.getBoundingClientRect(); 552 // @ts-ignore 553 if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { 554 //向上移动 555 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!); 556 // @ts-ignore 557 } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { 558 //向下移动 559 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!); 560 } 561 sp.refreshFavoriteCanvas(); 562 } 563 }; 564} 565function collectHandlerDragEnd(sp: SpSystemTrace): (ev: unknown) => void { 566 return function (ev: unknown): void { 567 sp.linkNodes.forEach((itln) => { 568 if (itln[0].rowEL.collect) { 569 if (sp.timerShaftEL?._checkExpand) { 570 itln[0].rowEL.translateY = 571 itln[0].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; 572 } else { 573 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 574 } 575 } else { 576 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 577 } 578 if (itln[1].rowEL.collect) { 579 if (sp.timerShaftEL?._checkExpand) { 580 itln[1].rowEL.translateY = 581 itln[1].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; 582 } else { 583 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 584 } 585 } else { 586 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 587 } 588 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 589 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 590 }); 591 sp.currentClickRow = null; 592 }; 593} 594function selectHandler(sp: SpSystemTrace): void { 595 sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => { 596 rows.forEach((item) => { 597 sp.setAttribute('clickRow', item.rowType!); 598 sp.setAttribute('rowName', item.name); 599 sp.setAttribute('rowId', item.rowId!); 600 }); 601 if (rows.length === 0) { 602 const allRows = [ 603 // @ts-ignore 604 ...sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>('trace-row'), 605 ...sp.favoriteChartListEL!.getAllCollectRows(), 606 ]; 607 for (const row of allRows) { 608 row.checkType = '-1'; 609 if (row.folder) { 610 row.childrenList.forEach((item) => { 611 row.checkType = '-1'; 612 }); 613 } 614 } 615 sp.refreshCanvas(true); 616 if (!SportRuler.isMouseInSportRuler) { 617 sp.traceSheetEL?.setMode('max'); 618 sp.traceSheetEL?.setMode('hidden'); 619 } 620 return; 621 } 622 let checkRows = rows; 623 if (!refreshCheckBox) { 624 checkRows = [ 625 ...rows, 626 // @ts-ignore 627 ...sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`trace-row[check-type='2']`), 628 ...sp.favoriteChartListEL!.getAllSelectCollectRows(), 629 ]; 630 } 631 checkRows = checkRows.filter((item, index, self) => { 632 return self.findIndex(obj => obj.rowId === item.rowId && obj.rowType === item.rowType && obj.name === item.name) === index; 633 }); 634 selectHandlerRefreshCheckBox(sp, checkRows, refreshCheckBox); 635 if (!sp.isSelectClick) { 636 sp.rangeTraceRow = []; 637 } 638 selectHandlerRows(sp, checkRows); 639 }; 640} 641// @ts-ignore 642function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array<TraceRow<unknown>>, refreshCheckBox: boolean): void { 643 if (refreshCheckBox) { 644 if (rows.length > 0) { 645 sp.queryAllTraceRow().forEach((row) => (row.checkType = '0')); 646 rows.forEach((it) => (it.checkType = '2')); 647 } else { 648 sp.queryAllTraceRow().forEach((row) => (row.checkType = '-1')); 649 return; 650 } 651 } 652} 653// @ts-ignore 654function selectHandlerRows(sp: SpSystemTrace, rows: Array<TraceRow<unknown>>): void { 655 let selection = new SelectionParam(); 656 selection.traceId = Utils.currentSelectTrace; 657 selection.cpuStateRowsId = sp.stateRowsId; 658 selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; 659 selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; 660 selection.recordStartNs = Utils.getInstance().getRecordStartNS(Utils.currentSelectTrace); 661 rows.forEach((it) => { 662 selection.pushSelection(it, sp); 663 if (sp.rangeTraceRow!.length !== rows.length) { 664 let event = sp.createPointEvent(it); 665 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 666 action: 'trace_row', // @ts-ignore 667 event: event, 668 }); 669 } 670 sp.setParentCheckStatus(it); 671 }); 672 if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { 673 selection.promiseList.push( 674 queryEbpfSamplesCount( 675 TraceRow.rangeSelectObject?.startNS || 0, 676 TraceRow.rangeSelectObject?.endNS || 0, 677 selection.diskIOipids 678 ).then((res) => { 679 if (res.length > 0) { 680 //@ts-ignore 681 selection.fsCount = res[0].fsCount; 682 //@ts-ignore 683 selection.vmCount = res[0].vmCount; 684 } 685 return new Promise((resolve) => resolve(1)); 686 }) 687 ); 688 } 689 sp.rangeTraceRow = rows; 690 sp.isSelectClick = false; 691 sp.selectStructNull(); 692 sp.timerShaftEL?.removeTriangle('inverted'); 693 if (selection.promiseList.length > 0) { 694 Promise.all(selection.promiseList).then(() => { 695 selection.promiseList = []; 696 sp.traceSheetEL?.rangeSelect(selection); 697 }); 698 } else { 699 sp.traceSheetEL?.rangeSelect(selection); 700 } 701 sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 702 sp.selectionParam = selection; 703 sp.refreshCanvas(true); 704} 705function resizeObserverHandler(sp: SpSystemTrace): void { 706 // @ts-ignore 707 new ResizeObserver((entries) => { 708 TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth(); 709 requestAnimationFrame(() => { 710 sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth()); 711 // @ts-ignore 712 sp.shadowRoot!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => { 713 it.updateWidth(sp.clientWidth); 714 }); 715 }); 716 }).observe(sp); 717 718 new ResizeObserver((entries) => { 719 sp.canvasPanelConfig(); 720 if (sp.traceSheetEL!.getAttribute('mode') === 'hidden') { 721 sp.timerShaftEL?.removeTriangle('triangle'); 722 } 723 if (sp.favoriteChartListEL?.style.display === 'flex') { 724 sp.refreshFavoriteCanvas(); 725 } 726 sp.refreshCanvas(true); 727 }).observe(sp.rowsPaneEL!); 728} 729function mutationObserverHandler(sp: SpSystemTrace): void { 730 new MutationObserver((mutations, observer) => { 731 for (const mutation of mutations) { 732 if (mutation.type === 'attributes') { 733 if (sp.style.visibility === 'visible') { 734 if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) { 735 sp.timerShaftEL?.setSlicesMark( 736 TraceRow.rangeSelectObject.startNS || 0, 737 TraceRow.rangeSelectObject.endNS || 0, 738 false 739 ); 740 SpSystemTrace.sliceRangeMark = undefined; 741 window.publish(window.SmartEvent.UI.RefreshCanvas, {}); 742 } 743 } 744 } 745 } 746 }).observe(sp, { 747 attributes: true, 748 childList: false, 749 subtree: false, 750 }); 751} 752function intersectionObserverHandler(sp: SpSystemTrace): void { 753 sp.intersectionObserver = new IntersectionObserver( 754 (entries) => { 755 entries.forEach((it) => { 756 // @ts-ignore 757 let tr = it.target as TraceRow<unknown>; 758 // 目标元素的可见比例 759 tr.intersectionRatio = it.intersectionRatio; 760 // 判断目标元素是否可见 isIntersecting为true是可见 761 if (!it.isIntersecting) { 762 tr.sleeping = true; 763 sp.invisibleRows.indexOf(tr) === -1 && sp.invisibleRows.push(tr); 764 } else { 765 tr.sleeping = false; 766 sp.visibleRows.indexOf(tr) === -1 && sp.visibleRows.push(tr); 767 } 768 }); 769 //更新可见泳道及不可见泳道值 770 sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping); 771 sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping); 772 if (sp.handler === -1) { 773 cancelAnimationFrame(sp.handler); 774 } 775 sp.handler = requestAnimationFrame(() => sp.refreshCanvas(false)); 776 }, 777 { threshold: [0, 0.01, 0.99, 1] } 778 ); 779} 780function observerHandler(sp: SpSystemTrace): void { 781 resizeObserverHandler(sp); 782 mutationObserverHandler(sp); 783 intersectionObserverHandler(sp); 784} 785function windowKeyDownHandler(sp: SpSystemTrace): (ev: KeyboardEvent) => void { 786 return function (ev: KeyboardEvent) { 787 if (ev.key.toLocaleLowerCase() === 'escape') { 788 sp.queryAllTraceRow().forEach((it) => { 789 it.checkType = '-1'; 790 }); 791 TraceRow.rangeSelectObject = undefined; 792 sp.rangeSelect.rangeTraceRow = []; 793 sp.selectStructNull(); 794 sp.timerShaftEL?.setSlicesMark(); 795 sp.traceSheetEL?.setMode('hidden'); 796 sp.removeLinkLinesByBusinessType('janks', 'task'); 797 } 798 }; 799} 800function smartEventSubscribe(sp: SpSystemTrace): void { 801 window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data)); 802 window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => { }); 803 window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false)); 804 window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => { 805 //@ts-ignore 806 sp.keyboardEnable = tr.enable; 807 if (!sp.keyboardEnable) { 808 sp.stopWASD(); 809 } 810 }); //@ts-ignore 811 window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => { 812 if (!collapse) { 813 // 一键折叠之前,记录当前打开的泳道图 814 // @ts-ignore 815 sp.expandRowList = Array.from(sp.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row[folder][expansion]')) || []; 816 } 817 sp.collapseAll = true; 818 sp.setAttribute('disable', ''); 819 sp.expandRowList!.forEach((it) => (it.expansion = collapse)); 820 sp.collapseAll = false; 821 sp.removeAttribute('disable'); 822 sp.refreshCanvas(true); 823 }); 824 window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => { 825 //@ts-ignore 826 sp.mouseEventEnable = tr.mouseEnable; 827 if (sp.mouseEventEnable) { 828 sp.removeAttribute('disable'); 829 } else { 830 sp.setAttribute('disable', ''); 831 } 832 }); //@ts-ignore 833 window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => (sp.currentCollectGroup = group)); 834} 835 836export function documentInitEvent(sp: SpSystemTrace): void { 837 if (!document) { 838 return; 839 } 840 document.addEventListener('triangle-flag', triangleFlagHandler(sp)); 841 document.addEventListener('number_calibration', numberCalibrationHandler(sp)); 842 document.addEventListener('flag-change', flagChangeHandler(sp)); 843 document.addEventListener('slices-change', slicesChangeHandler(sp)); 844 if (sp.timerShaftEL?.collecBtn) { 845 sp.timerShaftEL.collecBtn.onclick = (): void => { 846 if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) { 847 sp.timerShaftEL!.collecBtn!.removeAttribute('close'); 848 sp.favoriteChartListEL?.showCollectArea(); 849 } else { 850 sp.timerShaftEL!.collecBtn!.setAttribute('close', ''); 851 sp.favoriteChartListEL?.hideCollectArea(); 852 } 853 }; 854 } 855 document.addEventListener('collect', collectHandler(sp)); 856} 857 858export function spSystemTraceInitElement(sp: SpSystemTrace): void { 859 window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines()); 860 sp.traceSheetEL = sp.shadowRoot?.querySelector<TraceSheet>('.trace-sheet'); 861 if (!sp || !sp.shadowRoot || !sp.traceSheetEL) { 862 return; 863 } 864 let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot 865 ?.querySelector('#current-selection > tabpane-current-selection') 866 ?.shadowRoot?.querySelector('#rightButton'); 867 let rightStar: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot 868 ?.querySelector('#current-selection > tabpane-current-selection') 869 ?.shadowRoot?.querySelector('#right-star'); 870 sp.tipEL = sp.shadowRoot.querySelector<HTMLDivElement>('.tip'); 871 sp.rowsPaneEL = sp.shadowRoot.querySelector<HTMLDivElement>('.rows-pane'); 872 sp.rowsEL = sp.rowsPaneEL; 873 sp.spacerEL = sp.shadowRoot.querySelector<HTMLDivElement>('.spacer'); 874 sp.timerShaftEL = sp.shadowRoot.querySelector<TimerShaftElement>('.timer-shaft'); 875 sp.favoriteChartListEL = sp.shadowRoot.querySelector<SpChartList>('#favorite-chart-list'); 876 sp.collectEl1 = sp.favoriteChartListEL?.shadowRoot?.querySelector<HTMLDivElement>('#collect-group-1'); 877 sp.groupTitle1 = sp.favoriteChartListEL?.shadowRoot?.querySelector<HTMLDivElement>('#group-1-title'); 878 if (!sp.traceSheetEL.shadowRoot) { 879 return; 880 } 881 sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector<TabPaneFrequencySample>('tabpane-frequency-sample'); 882 sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector<TabPaneCounterSample>('tabpane-counter-sample'); 883 sp.wakeupListTbl = sp.traceSheetEL.shadowRoot?.querySelector('#current-selection > tabpane-current-selection')?. 884 shadowRoot?.querySelector('#wakeupListTbl'); 885 sp.rangeSelect = new RangeSelect(sp); 886 // @ts-ignore 887 rightButton?.addEventListener('click', rightButtonOnClick(sp, rightStar)); 888 rightStar?.addEventListener('click', rightStarOnClick(sp)); 889 documentInitEvent(sp); 890 SpSystemTrace.scrollViewWidth = sp.getScrollWidth(); 891 selectHandler(sp); 892 observerHandler(sp); 893 window.addEventListener('keydown', windowKeyDownHandler(sp)); 894 sp.chartManager = new SpChartManager(sp); 895 sp.canvasPanel = sp.shadowRoot.querySelector<HTMLCanvasElement>('#canvas-panel')!; 896 sp.canvasPanelCtx = sp.canvasPanel.getContext('2d'); 897 sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context(); 898 sp.canvasPanelConfig(); 899 smartEventSubscribe(sp); 900} 901 902function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: unknown, currentEntry: unknown): void { 903 if (findEntry) { 904 //findEntry不在range范围内,会把它移动到泳道最左侧 905 // @ts-ignore 906 if (findEntry.startTime + findEntry.dur > TraceRow.range!.endNS || findEntry.startTime < TraceRow.range!.startNS) { 907 // @ts-ignore 908 sp.moveRangeToLeft(findEntry.startTime!, findEntry.dur!); 909 } 910 cancelCurrentTraceRowHighlight(sp, currentEntry); 911 // @ts-ignore 912 if (findEntry.type === 'cpu') { 913 findEntryTypeCpu(sp, findEntry); 914 // @ts-ignore 915 } else if (findEntry.type === 'func') { 916 findEntryTypeFunc(sp, findEntry); 917 // @ts-ignore 918 } else if (findEntry.type === 'thread||process') { 919 findEntryTypeThreadProcess(sp, findEntry); 920 // @ts-ignore 921 } else if (findEntry.type === 'sdk') { 922 findEntryTypeSdk(sp, findEntry); 923 } 924 } 925} 926 927export function cancelCurrentTraceRowHighlight(sp: SpSystemTrace, currentEntry: unknown): void { 928 // @ts-ignore 929 if (currentEntry?.type === 'cpu') { 930 // @ts-ignore 931 sp.queryAllTraceRow(`trace-row[row-type='cpu-data'][row-id='${currentEntry.cpu}']`, 932 // @ts-ignore 933 (row) => row.rowType === 'cpu-data' && row.rowId === `${currentEntry.cpu}`)[0].highlight = false; 934 // @ts-ignore 935 } else if (currentEntry?.type === 'func') { 936 // @ts-ignore 937 let funId = (currentEntry.rowId === null || currentEntry.rowId === undefined) ? `${currentEntry.funName}-${currentEntry.pid}` : currentEntry.rowId; 938 // @ts-ignore 939 let funcRowID = (currentEntry.cookie === null || currentEntry.cookie === undefined) ? `${Utils.getDistributedRowId(currentEntry.tid)}` : funId; 940 // @ts-ignore 941 let parentRow = sp.queryAllTraceRow(`trace-row[row-id='${Utils.getDistributedRowId(currentEntry.pid)}'][folder]`, 942 // @ts-ignore 943 (row) => row.rowId === `trace-row[row-id='${Utils.getDistributedRowId(currentEntry.pid)}'][folder]`)[0]; 944 if (!parentRow) { 945 return; 946 } 947 // @ts-ignore 948 let filterRow: TraceRow<unknown> | undefined; 949 parentRow.childrenList.forEach((item) => { 950 if (item.rowId === 'sameThreadProcess') { 951 filterRow = parentRow.childrenList.concat(item.childrenList).filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; 952 } else { 953 filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; 954 } 955 }); 956 if (!filterRow) { 957 let rowsPaneEL = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace')?.shadowRoot?.querySelector('div > div.rows-pane'); 958 // @ts-ignore 959 let funcRow = rowsPaneEL?.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcRowID}'][row-type='func']`); 960 if (funcRow) { 961 filterRow = funcRow; 962 } else { 963 return; 964 } 965 } 966 filterRow.highlight = false; 967 // @ts-ignore 968 } else if (currentEntry?.type === 'sdk') { 969 // @ts-ignore 970 let parentRow = sp.shadowRoot!.querySelector<TraceRow<unknown>>("trace-row[row-type='sdk'][folder]"); 971 if (parentRow) { 972 let sdkRow = parentRow.childrenList.filter( 973 // @ts-ignore 974 (child) => child.rowId === currentEntry.rowId && child.rowType === currentEntry.rowType 975 )[0]; 976 sdkRow!.highlight = false; 977 } 978 } 979} 980 981export function spSystemTraceShowStruct( 982 sp: SpSystemTrace, 983 previous: boolean, 984 currentIndex: number, 985 structs: Array<unknown>, 986 retargetIndex?: number 987): number { 988 if (structs.length === 0) { 989 return 0; 990 } 991 let findIndex = spSystemTraceShowStructFindIndex(previous, currentIndex, structs, retargetIndex); 992 let findEntry: unknown = structs[findIndex]; 993 let currentEntry: unknown = undefined; 994 if (currentIndex >= 0) { 995 currentEntry = structs[currentIndex]; 996 } 997 moveRangeToCenterAndHighlight(sp, findEntry, currentEntry); 998 return findIndex; 999} 1000 1001function spSystemTraceShowStructFindIndex( 1002 previous: boolean, 1003 currentIndex: number, 1004 structs: Array<unknown>, 1005 retargetIndex: number | undefined 1006): number { 1007 const rangeStart = TraceRow.range!.startNS; 1008 const rangeEnd = TraceRow.range!.endNS; 1009 let findIndex = -1; 1010 if (retargetIndex) {//如果Go有值,直接跳转 1011 findIndex = retargetIndex - 1; 1012 } else if (previous) { 1013 //case1:current.start在start边界以右,需要从当前项往第一项遍历,找到structs[index].start < end 1014 //@ts-ignore 1015 if (structs[currentIndex].startTime! >= Math.round(rangeStart)) { 1016 findIndex = findPreviousOne(currentIndex - 1, 0, structs); 1017 //处理当前项如果是第一项 1018 findIndex = findIndex === -1 ? structs.length - 1 : findIndex; 1019 } else { 1020 //case2:current.start在start边界以左,需要从最后一项到当前项遍历,找到structs[index].start < end 1021 findIndex = findPreviousOne(structs.length - 1, currentIndex + 1, structs); 1022 } 1023 } else {//向后查找 1024 if (currentIndex === -1) {//输入框内输入内容后第一次搜索 1025 findIndex = findNextOne(0, structs.length - 1, structs); 1026 //处理当所有的项都在start以左 1027 return findIndex === -1 ? 0 : findIndex; 1028 } 1029 //case1:current.start 在end左侧 从当前项到最后一项遍历,找到startTime>start 1030 //@ts-ignore 1031 if (structs[currentIndex].startTime! < Math.round(rangeEnd)) {//case1 1032 findIndex = findNextOne(currentIndex + 1, structs.length - 1, structs); 1033 //处理当前项是最后一项 1034 findIndex = findIndex === -1 ? 0 : findIndex; 1035 } else { 1036 //case2: current.start 在end右侧 从第一项到当前项遍历,找到startTime>start 1037 findIndex = findNextOne(0, currentIndex - 1, structs); 1038 } 1039 } 1040 return findIndex; 1041} 1042//向前查找逻辑 1043function findPreviousOne(start: number, end: number, structs: Array<unknown>): number { 1044 let findIndex = -1; 1045 const rangeEnd = TraceRow.range!.endNS; 1046 for (let i = start; i >= end; i--) { 1047 let it = structs[i]; 1048 //@ts-ignore 1049 if (it.startTime! < rangeEnd) { 1050 findIndex = i; 1051 break; 1052 } 1053 } 1054 return findIndex; 1055} 1056//向后查找 1057function findNextOne(start: number, end: number, structs: Array<unknown>): number { 1058 let findIndex = -1; 1059 const rangeStart = TraceRow.range!.startNS; 1060 for (let i = start; i <= end; i++) { 1061 let it = structs[i]; 1062 //@ts-ignore 1063 if (it.startTime > rangeStart) { 1064 findIndex = i; 1065 break; 1066 } 1067 } 1068 return findIndex; 1069} 1070function findEntryTypeCpu(sp: SpSystemTrace, findEntry: unknown): void { 1071 // @ts-ignore 1072 CpuStruct.selectCpuStruct = findEntry; 1073 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 1074 sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row): boolean => row.rowType === 'cpu-data').forEach( 1075 (item): void => { 1076 // @ts-ignore 1077 if (item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`) { 1078 sp.rechargeCpuData( 1079 // @ts-ignore 1080 findEntry, // @ts-ignore 1081 item.dataListCache.find((it) => it.startTime > findEntry.startTime) 1082 ); 1083 let _findEntry = JSON.parse(JSON.stringify(findEntry)); 1084 _findEntry.type = 'thread'; 1085 item.fixedList = [_findEntry]; 1086 } 1087 // @ts-ignore 1088 item.highlight = item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`; 1089 item.draw(true); 1090 } 1091 ); 1092 // @ts-ignore 1093 sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); 1094 sp.onClickHandler(TraceRow.ROW_TYPE_CPU); 1095} 1096function findEntryTypeFunc(sp: SpSystemTrace, findEntry: unknown): void { 1097 sp.observerScrollHeightEnable = true; 1098 sp.scrollToActFunc( 1099 { 1100 // @ts-ignore 1101 startTs: findEntry.startTime, 1102 // @ts-ignore 1103 dur: findEntry.dur, 1104 // @ts-ignore 1105 tid: findEntry.tid, 1106 // @ts-ignore 1107 pid: findEntry.pid, 1108 // @ts-ignore 1109 depth: findEntry.depth, 1110 // @ts-ignore 1111 argsetid: findEntry.argsetid, 1112 // @ts-ignore 1113 funName: findEntry.funName, 1114 // @ts-ignore 1115 cookie: findEntry.cookie, 1116 // @ts-ignore 1117 //因异步trace分类出的rowId类型有三种,故新增row_id字段,该字段为异步方法的对应的rowId,支持搜索查询定位到该方法属于那个row,只有缓存的异步trace数据中含该字段 1118 row_id: findEntry.rowId ? findEntry.rowId : null, 1119 }, 1120 true 1121 ); 1122} 1123function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: unknown): void { 1124 let threadProcessRow = sp.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>('trace-row')[0]; 1125 if (threadProcessRow) { 1126 let filterRow = threadProcessRow.childrenList.filter( 1127 // @ts-ignore 1128 (row) => row.rowId === Utils.getDistributedRowId(findEntry.rowId) && row.rowId === findEntry.rowType 1129 )[0]; 1130 filterRow!.highlight = true; 1131 // @ts-ignore 1132 sp.closeAllExpandRows(Utils.getDistributedRowId(findEntry.rowParentId)); 1133 // @ts-ignore 1134 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 1135 let completeEntry = (): void => { 1136 sp.hoverStructNull(); 1137 sp.selectStructNull(); 1138 sp.wakeupListNull(); 1139 // @ts-ignore 1140 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 1141 }; 1142 if (filterRow!.isComplete) { 1143 completeEntry(); 1144 } else { 1145 filterRow!.onComplete = completeEntry; 1146 } 1147 } 1148} 1149function findEntryTypeSdk(sp: SpSystemTrace, findEntry: unknown): void { 1150 // @ts-ignore 1151 let parentRow = sp.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-type='sdk'][folder]`); 1152 if (parentRow) { 1153 let sdkRow = parentRow.childrenList.filter( 1154 // @ts-ignore 1155 (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType 1156 )[0]; 1157 sdkRow!.highlight = true; 1158 } 1159 sp.hoverStructNull(); 1160 sp.selectStructNull(); 1161 sp.wakeupListNull(); 1162 // @ts-ignore 1163 sp.onClickHandler(findEntry.rowType!); 1164 // @ts-ignore 1165 sp.closeAllExpandRows(findEntry.rowParentId); 1166 // @ts-ignore 1167 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 1168} 1169async function spSystemTraceInitBuffer( 1170 sp: SpSystemTrace, 1171 param: { buf?: ArrayBuffer; Url?: string; buf2?: ArrayBuffer }, 1172 wasmConfigUri: string, 1173 progress: Function 1174): Promise<{ 1175 status: boolean; 1176 msg: string; 1177} | null> { 1178 if (param.buf) { 1179 let configJson = ''; 1180 try { 1181 configJson = await fetch(wasmConfigUri).then((res) => res.text()); 1182 } catch (e) { 1183 error('getWasmConfigFailed', e); 1184 } 1185 let parseConfig = FlagsConfig.getSpTraceStreamParseConfig(); 1186 let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress); 1187 if (!status) { 1188 return { status: false, msg: msg }; 1189 } 1190 SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap; 1191 if (param.buf2) { 1192 let { status, msg } = await threadPool2.initSqlite(param.buf2, parseConfig, configJson, progress); 1193 if (!status) { 1194 return { status: false, msg: msg }; 1195 } 1196 } 1197 return null; 1198 } else { 1199 return null; 1200 } 1201} 1202async function spSystemTraceInitUrl( 1203 sp: SpSystemTrace, 1204 param: { buf?: ArrayBuffer; url?: string }, 1205 wasmConfigUri: string, 1206 progress: Function 1207): Promise<{ 1208 status: boolean; 1209 msg: string; 1210} | null> { 1211 if (param.url) { 1212 let { status, msg } = await threadPool.initServer(param.url, progress); 1213 if (!status) { 1214 return { status: false, msg: msg }; 1215 } else { 1216 return null; 1217 } 1218 } else { 1219 return null; 1220 } 1221} 1222export async function spSystemTraceInit( 1223 sp: SpSystemTrace, 1224 param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string }, 1225 wasmConfigUri: string, 1226 progress: Function, 1227 isDistributed: boolean 1228): Promise<unknown> { 1229 progress('Load database', 6); 1230 sp.rowsPaneEL!.scroll({ top: 0, left: 0 }); 1231 let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress); 1232 if (rsBuf) { 1233 return rsBuf; 1234 } 1235 let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, progress); 1236 if (rsUrl) { 1237 return rsUrl; 1238 } 1239 if (isDistributed) { 1240 await sp.chartManager?.initDistributedChart(progress, param.fileName1 || 'Trace 1', param.fileName2 || 'Trace 2'); 1241 } else { 1242 await sp.chartManager?.init(progress); 1243 } 1244 let rowId: string = ''; 1245 // @ts-ignore 1246 sp.rowsEL?.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => { 1247 if (it.name.includes('Ark Ts')) { 1248 rowId = it.rowId!; 1249 } 1250 if (it.folder) { 1251 it.addEventListener('expansion-change', sp.extracted(it)); 1252 } 1253 }); 1254 progress('completed', 100); 1255 info('All TraceRow Data initialized'); 1256 sp.loadTraceCompleted = true; 1257 // @ts-ignore 1258 sp.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => { 1259 if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) { 1260 it.addTemplateTypes('Ark Ts'); 1261 for (let child of it.childrenList) { 1262 child.addTemplateTypes('Ark Ts'); 1263 } 1264 } 1265 if (it.folder) { 1266 let offsetYTimeOut: unknown = undefined; 1267 it.addEventListener('expansion-change', expansionChangeHandler(sp, offsetYTimeOut)); 1268 } 1269 if (sp.loadTraceCompleted) { 1270 sp.traceSheetEL?.displaySystemLogsData(); 1271 sp.traceSheetEL?.displayHangsData(); 1272 sp.traceSheetEL?.displaySystemStatesData(); 1273 } 1274 // 如果有render_service进程,查询该进程下对应泳道的方法存起来,以便框选时直接使用 1275 if (it.getAttribute('name')?.includes('render_service') && it.getAttribute('row-type') === 'process') { 1276 queryRowsData(sp, it.childrenList); 1277 } 1278 sp.intersectionObserver?.observe(it); 1279 }); 1280 1281 for (let i = 0; i < pluginArray.length; i++) { 1282 let item = pluginArray[i]; 1283 for (let j = 0; j < item.tables.length; j++) { 1284 let tableItem = item.tables[j]; 1285 let res = await queryPlugins(tableItem) || []; 1286 if (res.length > 0) { 1287 SpStatisticsHttpUtil.recordPlugin.push(item.pluginName); 1288 break; 1289 } else { 1290 continue; 1291 } 1292 } 1293 } 1294 1295 // 统计插件 1296 SpStatisticsHttpUtil.recordPluginUsage(); 1297 // trace文件加载完毕,将动效json文件读取并存入缓存 1298 let funDetailUrl = `https://${window.location.host.split(':')[0]}:${window.location.port 1299 }/application/doc/funDetail.json`; 1300 let xhr = new XMLHttpRequest(); 1301 // 创建XMLHttpRequest对象 1302 xhr.open('GET', funDetailUrl); 1303 xhr.onreadystatechange = function (): void { 1304 if (xhr.readyState === 4 && xhr.status === 200) { 1305 let content = xhr.responseText; 1306 caches.open('/funDetail').then((cache) => { 1307 let headers = new Headers(); 1308 headers.append('Content-Type', 'application/json'); 1309 return cache 1310 .put( 1311 '/funDetail', 1312 new Response(content, { 1313 status: 200, 1314 headers, 1315 }) 1316 ) 1317 .then(); 1318 }); 1319 } 1320 }; 1321 xhr.send(); // 发送请求 1322 return { status: true, msg: 'success' }; 1323} 1324function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: unknown): (event: unknown) => void { 1325 return function (event: unknown) { 1326 sp.scrollH = sp.rowsPaneEL!.scrollHeight; 1327 let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce((pre, cur) => pre + cur.clientHeight!, 0); 1328 let offset = sp.rowsPaneEL!.scrollHeight - max; 1329 sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset; 1330 JankStruct.delJankLineFlag = false; 1331 if (offsetYTimeOut) { 1332 // @ts-ignore 1333 clearTimeout(offsetYTimeOut); 1334 } 1335 // @ts-ignore 1336 if (event.detail.expansion) { 1337 offsetYTimeOut = setTimeout(() => { 1338 sp.linkNodes.forEach((linkNode) => { 1339 JankStruct.selectJankStructList?.forEach((selectStruct: unknown) => { 1340 // @ts-ignore 1341 if (event.detail.rowId === selectStruct.pid) { 1342 // @ts-ignore 1343 JankStruct.selectJankStruct = selectStruct; 1344 // @ts-ignore 1345 JankStruct.hoverJankStruct = selectStruct; 1346 } 1347 }); 1348 linkNodeHandler(linkNode, sp); 1349 }); 1350 }, 300); 1351 } else { 1352 if (JankStruct!.selectJankStruct) { 1353 JankStruct.selectJankStructList?.push(<JankStruct>JankStruct!.selectJankStruct); 1354 } 1355 offsetYTimeOut = setTimeout(() => { 1356 sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp)); 1357 }, 300); 1358 } 1359 let refreshTimeOut = setTimeout(() => { 1360 sp.refreshCanvas(true); 1361 clearTimeout(refreshTimeOut); 1362 }, 360); 1363 }; 1364} 1365// 查询render_service对应方法行的所有数据 1366// @ts-ignore 1367function queryRowsData(sp: SpSystemTrace, rowList: Array<TraceRow<unknown>>): void { 1368 rowList.forEach((row): void => { 1369 if (row.getAttribute('row-type') === 'func') { 1370 if (row.getAttribute('name')?.startsWith('render_service')) { 1371 saveFrameRateData(sp, row, 'H:RSMainThread::DoComposition'); 1372 } else if (row.getAttribute('name')?.startsWith('RSHardwareThrea')) { 1373 saveFrameRateData(sp, row, 'H:Repaint'); 1374 } else if (row.getAttribute('name')?.startsWith('Present')) { 1375 savePresentData(sp, row, 'H:Waiting for Present Fence'); 1376 } 1377 } 1378 }); 1379} 1380 1381// 查到所有的数据存储起来 1382// @ts-ignore 1383function saveFrameRateData(sp: SpSystemTrace, row: TraceRow<unknown>, funcName: string): void { 1384 let dataList: unknown = []; 1385 queryFuncRowData(funcName, Number(row?.getAttribute('row-id'))).then((res): void => { 1386 if (res.length) { 1387 res.forEach((item): void => { 1388 // @ts-ignore 1389 dataList?.push({ startTime: item.startTime!, tid: item.tid }); 1390 }); 1391 if (funcName === 'H:RSMainThread::DoComposition') { 1392 // @ts-ignore 1393 sp.docomList = dataList; 1394 } else { 1395 // @ts-ignore 1396 sp.repaintList = dataList; 1397 } 1398 } 1399 }); 1400} 1401// 查到present泳道所有的数据存储起来 1402// @ts-ignore 1403function savePresentData(sp: SpSystemTrace, row: TraceRow<unknown>, funcName: string): void { 1404 let dataList: unknown = []; 1405 fuzzyQueryFuncRowData(funcName, Number(row?.getAttribute('row-id'))).then((res): void => { 1406 if (res.length) { 1407 res.forEach((item): void => { 1408 // @ts-ignore 1409 dataList?.push({ endTime: item.endTime!, tid: item.tid }); 1410 }); // @ts-ignore 1411 sp.presentList = dataList; 1412 } 1413 }); 1414} 1415function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace): void { 1416 if (linkNode[0].rowEL.collect) { 1417 linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; 1418 } else { 1419 linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 1420 } 1421 linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; 1422 if (linkNode[1].rowEL.collect) { 1423 linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; 1424 } else { 1425 linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 1426 } 1427 linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; 1428} 1429 1430const eventMap = { 1431 'cpu-data': 'Cpu', 1432 'cpu-state': 'Cpu State', 1433 'cpu-freq': 'Cpu Frequency', 1434 'cpu-limit-freq': 'Cpu Freq Limit', 1435 process: 'Process', 1436 'native-memory': 'Native Memory', 1437 thread: 'Thread', 1438 func: 'Func', 1439 mem: 'Memory', 1440 'virtual-memory-cell': 'Virtual Memory', 1441 'virtual-memory-group': 'Virtual Memory', 1442 fps: 'FPS', 1443 'ability-monitor': 'Ability Monitor', 1444 'cpu-ability': 'Cpu Ability', 1445 'memory-ability': 'Memory Ability', 1446 'disk-ability': 'DiskIO Ability', 1447 'network-ability': 'Network Ability', 1448 sdk: 'Sdk', 1449 'sdk-counter': 'SDK Counter', 1450 'sdk-slice': 'Sdk Slice', 1451 energy: 'Energy', 1452 'power-energy': 'Power Event', 1453 'system-energy': 'System Event', 1454 'anomaly-energy': 'Anomaly Event', 1455 'clock-group': 'Clocks', 1456 clock: 'clock', 1457 'irq-group': 'Irqs', 1458 irq: 'irq', 1459 hiperf: 'HiPerf (All)', 1460 'hiperf-event': 'HiPerf Event', 1461 'hiperf-report': 'HiPerf Report', 1462 'hiperf-process': 'HiPerf Process', 1463 'hiperf-thread': 'HiPerf Thread', 1464 'js-memory': 'Js Memory', 1465}; 1466export function spSystemTraceInitPointToEvent(sp: SpSystemTrace): void { 1467 sp.eventMap = eventMap; 1468} 1469 1470export function spSystemTraceParentRowSticky(sp: SpSystemTrace, deltaY: number): void { 1471 if (deltaY > 0) { 1472 // 从上往下划 1473 const expandRowList = sp.visibleRows.filter((vr) => vr.expansion); 1474 // @ts-ignore 1475 expandRowList.forEach((vr: TraceRow<unknown>) => { 1476 // @ts-ignore 1477 const visibleNotCollectList = vr.childrenList.filter((child: TraceRow<unknown>) => !child.collect && !child.sleeping); 1478 vr.sticky = visibleNotCollectList.length > 0; 1479 }); 1480 } else if (deltaY < 0) { 1481 // 从下往上划 1482 sp.visibleRows 1483 .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion && !vr.collect) 1484 .forEach((vr) => (vr.parentRowEl!.sticky = true)); 1485 } else { 1486 return; 1487 } 1488} 1489