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