1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import {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} 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; 37 38function rightButtonOnClick(sp: SpSystemTrace,rightStar: HTMLElementAlias) { 39 Object.assign(sp, { 40 ext(): string { 41 return "Handle the right button click event"; 42 } 43 }) 44 45 return function (event: any) { 46 if (SpSystemTrace.btnTimer) { 47 return; 48 } 49 // 唤醒树有值则不再重复添加 50 const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('['); 51 if (SpSystemTrace.wakeupList.length === 0) { 52 SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); 53 sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); 54 CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; 55 CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; 56 CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; 57 CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); 58 CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; 59 sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); 60 } else { 61 sp.wakeupListNull(); 62 SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); 63 sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); 64 CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; 65 CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; 66 CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; 67 CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); 68 CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; 69 sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); 70 } 71 setTimeout(() => { 72 requestAnimationFrame(() => sp.refreshCanvas(false)); 73 }, 300); 74 rightStar!.style.visibility = 'visible'; 75 rightStar!.style.cursor = 'pointer'; 76 SpSystemTrace.btnTimer = setTimeout(() => { 77 SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器 78 }, 2000); 79 } 80} 81function rightStarOnClick(sp:SpSystemTrace) { 82 return function (ev:any){ 83 let wakeupLists = []; 84 wakeupLists.push(CpuStruct.selectCpuStruct?.cpu); 85 for (let wakeupBean of SpSystemTrace.wakeupList) { 86 wakeupLists.push(wakeupBean.cpu); 87 } 88 let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort(); 89 for (let wakeupCpu of wakeupCpuLists) { 90 let cpuFavoriteRow: any = sp.shadowRoot?.querySelector<TraceRow<any>>( 91 `trace-row[row-type='cpu-data'][row-id='${wakeupCpu}']` 92 ); 93 if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) { 94 continue; 95 } 96 cpuFavoriteRow!.setAttribute('collect-type', ''); 97 let replaceRow = document.createElement('div'); 98 replaceRow.setAttribute('row-id', cpuFavoriteRow.rowId + '-' + cpuFavoriteRow.rowType); 99 replaceRow.setAttribute('type', 'replaceRow'); 100 replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId); 101 replaceRow.style.display = 'none'; 102 cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene'); 103 if (sp.rowsEL!.contains(cpuFavoriteRow)) { 104 sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow); 105 } 106 cpuFavoriteRow.tampName = cpuFavoriteRow.name; 107 sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, sp.currentCollectGroup, true); 108 sp.collectRows.push(cpuFavoriteRow); 109 sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); 110 sp.currentClickRow = null; 111 cpuFavoriteRow.setAttribute('draggable', 'true'); 112 cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp,cpuFavoriteRow)); 113 cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp)); 114 cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp,cpuFavoriteRow)); 115 cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp)); 116 } 117 sp.refreshFavoriteCanvas(); 118 sp.refreshCanvas(true); 119 } 120} 121function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: any) { 122 return function () { 123 sp.currentClickRow = cpuFavoriteRow; 124 } 125} 126function cpuFavoriteRowDragOver(sp: SpSystemTrace) { 127 return function (ev:any){ 128 ev.preventDefault(); 129 ev.dataTransfer.dropEffect = 'move'; 130 } 131} 132function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: any) { 133 return function (ev:any){ 134 if ( 135 sp.favoriteChartListEL != null && 136 sp.currentClickRow != null && 137 sp.currentClickRow !== cpuFavoriteRow 138 ) { 139 let rect = cpuFavoriteRow.getBoundingClientRect(); 140 if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { 141 //向上移动 142 sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow); 143 } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { 144 //向下移动 145 sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling); 146 } 147 sp.refreshFavoriteCanvas(); 148 } 149 } 150} 151function cpuFavoriteRowDragendHandler(sp: SpSystemTrace) { 152 return function(){ 153 sp.linkNodes.forEach((itln) => { 154 if (itln[0].rowEL.collect) { 155 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 156 } else { 157 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 158 } 159 if (itln[1].rowEL.collect) { 160 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 161 } else { 162 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 163 } 164 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 165 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 166 }); 167 sp.currentClickRow = null; 168 } 169} 170function triangleFlagHandler(sp:SpSystemTrace) { 171 return function (event:any) { 172 let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); 173 if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); 174 }; 175} 176function numberCalibrationHandler(sp: SpSystemTrace) { 177 return function (event: any) { 178 sp.timerShaftEL!.sportRuler!.times = event.detail.time; 179 sp.timerShaftEL!.sportRuler!.counts = event.detail.counts; 180 sp.timerShaftEL!.sportRuler!.durations = event.detail.durations; 181 sp.timerShaftEL!.sportRuler?.draw(); 182 } 183} 184function flagChangeHandler(sp: SpSystemTrace) { 185 return function (event: any) { 186 sp.timerShaftEL?.modifyFlagList(event.detail); 187 if (event.detail.hidden) { 188 sp.selectFlag = undefined; 189 if (sp._flagList.length <= 0) { 190 if (TraceRow.rangeSelectObject) { 191 let showTab = sp.getShowTab(); 192 showTab = showTab.filter((it) => it !== 'box-flag'); 193 sp.traceSheetEL?.displayTab(...showTab); 194 } else { 195 sp.traceSheetEL?.setAttribute('mode', 'hidden'); 196 } 197 } 198 sp.refreshCanvas(true); 199 } 200 } 201} 202function slicesChangeHandler(sp:SpSystemTrace) { 203 return function (event: any) { 204 sp.timerShaftEL?.modifySlicesList(event.detail); 205 if (event.detail.hidden) { 206 sp.slicestime = null; 207 if (sp._slicesList.length <= 0) { 208 if (TraceRow.rangeSelectObject) { 209 let showTab = sp.getShowTab(); 210 showTab = showTab.filter((it) => it !== 'tabpane-current'); 211 sp.traceSheetEL?.displayTab(...showTab); 212 } else { 213 sp.traceSheetEL?.setAttribute('mode', 'hidden'); 214 } 215 } 216 sp.refreshCanvas(true); 217 } 218 } 219} 220function collectHandler(sp: SpSystemTrace) { 221 return function (event: any) { 222 let currentRow = event.detail.row; 223 if (currentRow.collect) { 224 collectHandlerYes(sp,currentRow,event); 225 } else { 226 collectHandlerNo(sp,currentRow,event); 227 } 228 sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); 229 sp.refreshFavoriteCanvas(); 230 sp.refreshCanvas(true); 231 sp.linkNodes.forEach((itln) => { 232 if (itln[0].rowEL === currentRow) { 233 if (itln[0].rowEL.collect) { 234 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 235 } else { 236 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 237 } 238 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 239 } else if (itln[1].rowEL === currentRow) { 240 if (itln[1].rowEL.collect) { 241 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 242 } else { 243 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 244 } 245 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 246 } 247 }); 248 // 收藏夹元素拖动排序功能 249 sp.currentClickRow = null; 250 currentRow.setAttribute('draggable', 'true'); 251 currentRow.addEventListener('dragstart', () => { 252 sp.currentClickRow = currentRow; 253 }); 254 currentRow.addEventListener('dragover', (ev: any) => { 255 ev.preventDefault(); 256 ev.dataTransfer.dropEffect = 'move'; 257 }); 258 currentRow.addEventListener('drop', collectHandlerDrop(sp,currentRow)); 259 currentRow.addEventListener('dragend', collectHandlerDragEnd(sp)); 260 }; 261} 262function collectHandlerNo(sp: SpSystemTrace, currentRow: any, event: any) { 263 sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect'); 264 if (event.detail.type !== 'auto-collect') { 265 let rowIndex = sp.collectRows.indexOf(currentRow); 266 if (rowIndex !== -1) { 267 sp.collectRows.splice(rowIndex, 1); 268 } 269 } 270 let row = currentRow; 271 let allowExpansionRow = []; 272 while (row.hasParentRowEl) { 273 let parent = row.parentRowEl; 274 allowExpansionRow.push(parent); 275 row = parent; 276 } 277 for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { 278 if (allowExpansionRow[index]?.hasAttribute('scene')) { 279 if (allowExpansionRow[index]!.expansion) { 280 allowExpansionRow[index].updateChildRowStatus(); 281 } else { 282 allowExpansionRow[index].expansion = true; 283 } 284 } 285 } 286 allowExpansionRow.length = 0; 287 let replaceRow = sp.rowsEL!.querySelector<HTMLCanvasElement>( 288 `div[row-id='${currentRow.rowId}-${currentRow.rowType}']` 289 ); 290 // 取消收藏时,删除父亲ID 291 currentRow.name = currentRow.tampName; 292 if (replaceRow != null) { 293 sp.rowsEL!.replaceChild(currentRow, replaceRow); 294 currentRow.style.boxShadow = `0 10px 10px #00000000`; 295 } 296} 297function collectHandlerYes(sp: SpSystemTrace, currentRow: any, event: any){ 298 if ( 299 !sp.collectRows.find((find) => { 300 return find === currentRow; 301 }) 302 ) { 303 sp.collectRows.push(currentRow); 304 } 305 let replaceRow = document.createElement('div'); 306 replaceRow.setAttribute('row-id', currentRow.rowId + '-' + currentRow.rowType); 307 replaceRow.setAttribute('type', 'replaceRow'); 308 replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); 309 replaceRow.style.display = 'none'; 310 if (!currentRow.hasAttribute('scene')) { 311 currentRow.setAttribute('row-hidden', ''); 312 } else { 313 currentRow.removeAttribute('row-hidden'); 314 } 315 // 添加收藏时,在线程名前面追加父亲ID 316 let rowParentId = currentRow.rowParentId; 317 currentRow.tampName = currentRow.name; 318 if (rowParentId) { 319 let parentRows = sp.shadowRoot?.querySelectorAll<TraceRow<any>>(`trace-row[row-id='${rowParentId}']`); 320 parentRows?.forEach((parentRow) => { 321 if ( 322 parentRow?.name && 323 parentRow?.name != currentRow.name && 324 !parentRow.rowType!.startsWith('cpu') && 325 !parentRow.rowType!.startsWith('thread') && 326 !parentRow.rowType!.startsWith('func') && 327 !currentRow.name.includes(parentRow.name) 328 ) { 329 currentRow.name += '(' + parentRow.name + ')'; 330 } 331 }); 332 } 333 if (!currentRow.hasParentRowEl) { 334 sp.rowsEL!.replaceChild(replaceRow, currentRow); 335 } 336 sp.favoriteChartListEL?.insertRow(currentRow, sp.currentCollectGroup, event.detail.type !== 'auto-collect'); 337} 338function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement|undefined|null) { 339 return function (ev:any) { 340 if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) { 341 let rect = currentRow!.getBoundingClientRect(); 342 if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { 343 //向上移动 344 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!); 345 } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { 346 //向下移动 347 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!); 348 } 349 sp.refreshFavoriteCanvas(); 350 } 351 }; 352} 353function collectHandlerDragEnd(sp: SpSystemTrace) { 354 return function (ev:any) { 355 sp.linkNodes.forEach((itln) => { 356 if (itln[0].rowEL.collect) { 357 itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; 358 } else { 359 itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 360 } 361 if (itln[1].rowEL.collect) { 362 itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; 363 } else { 364 itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 365 } 366 itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; 367 itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; 368 }); 369 sp.currentClickRow = null; 370 }; 371} 372function selectHandler(sp: SpSystemTrace) { 373 sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => { 374 rows.forEach((item) => { 375 sp.setAttribute('clickRow', item.rowType!); 376 sp.setAttribute('rowName', item.name); 377 sp.setAttribute('rowId', item.rowId!); 378 }); 379 if (rows.length == 0) { 380 const allRows = [ 381 ...sp.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row'), 382 ...sp.favoriteChartListEL!.getAllCollectRows(), 383 ]; 384 for (const row of allRows) { 385 row.checkType = '-1'; 386 if (row.folder) { 387 row.childrenList.forEach((item) => { 388 row.checkType = '-1'; 389 }); 390 } 391 } 392 sp.refreshCanvas(true); 393 if (!SportRuler.isMouseInSportRuler) { 394 sp.traceSheetEL?.setAttribute('mode', 'hidden'); 395 } 396 return; 397 } 398 selectHandlerRefreshCheckBox(sp,rows, refreshCheckBox); 399 if (!sp.isSelectClick) { 400 sp.rangeTraceRow = []; 401 } 402 selectHandlerRows(sp, rows); 403 }; 404} 405function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array<TraceRow<any>>, refreshCheckBox: boolean) { 406 if (refreshCheckBox) { 407 if (rows.length > 0) { 408 sp.queryAllTraceRow().forEach((row) => { 409 row.checkType = '0'; 410 if (row.folder) { 411 row.childrenList.forEach((ite) => ite.checkType = '0'); 412 } 413 }); 414 rows.forEach((it) => it.checkType = '2'); 415 } else { 416 sp.queryAllTraceRow().forEach((row) => { 417 row.checkType = '-1'; 418 if (row.folder) { 419 row.childrenList.forEach((it) => it.checkType = '-1'); 420 } 421 }); 422 return; 423 } 424 } 425} 426function selectHandlerRows(sp: SpSystemTrace, rows: Array<TraceRow<any>>) { 427 let selection = new SelectionParam(); 428 selection.cpuStateRowsId = sp.stateRowsId; 429 selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; 430 selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; 431 selection.recordStartNs = (window as any).recordStartNS; 432 rows.forEach((it) => { 433 selection.pushSelection(it, sp); 434 if (sp.rangeTraceRow!.length !== rows.length) { 435 let event = sp.createPointEvent(it); 436 SpStatisticsHttpUtil.addOrdinaryVisitAction({ 437 action: 'trace_row', 438 event: event, 439 }); 440 } 441 }); 442 if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { 443 selection.promiseList.push( 444 queryEbpfSamplesCount( 445 TraceRow.rangeSelectObject?.startNS || 0, 446 TraceRow.rangeSelectObject?.endNS || 0, 447 selection.diskIOipids 448 ).then((res) => { 449 if (res.length > 0) { 450 selection.fsCount = res[0].fsCount; 451 selection.vmCount = res[0].vmCount; 452 } 453 return new Promise((resolve) => resolve(1)); 454 }) 455 ); 456 } 457 sp.rangeTraceRow = rows; 458 sp.isSelectClick = false; 459 sp.selectStructNull(); 460 sp.timerShaftEL?.removeTriangle('inverted'); 461 if (selection.promiseList.length > 0) { 462 Promise.all(selection.promiseList).then(() => { 463 selection.promiseList = []; 464 sp.traceSheetEL?.rangeSelect(selection); 465 }); 466 } else { 467 sp.traceSheetEL?.rangeSelect(selection); 468 } 469 sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 470 sp.selectionParam = selection; 471} 472function resizeObserverHandler(sp:SpSystemTrace) { 473 // @ts-ignore 474 new ResizeObserver((entries) => { 475 TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth(); 476 requestAnimationFrame(() => { 477 sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth()); 478 sp.shadowRoot!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 479 it.updateWidth(sp.clientWidth); 480 }); 481 }); 482 }).observe(sp); 483 484 new ResizeObserver((entries) => { 485 sp.canvasPanelConfig(); 486 if (sp.traceSheetEL!.getAttribute('mode') == 'hidden') { 487 sp.timerShaftEL?.removeTriangle('triangle'); 488 } 489 sp.refreshFavoriteCanvas(); 490 sp.refreshCanvas(true); 491 }).observe(sp.rowsPaneEL!); 492} 493function mutationObserverHandler(sp: SpSystemTrace) { 494 new MutationObserver((mutations, observer) => { 495 for (const mutation of mutations) { 496 if (mutation.type === 'attributes') { 497 if (sp.style.visibility === 'visible') { 498 if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) { 499 sp.timerShaftEL?.setSlicesMark( 500 TraceRow.rangeSelectObject.startNS || 0, 501 TraceRow.rangeSelectObject.endNS || 0, 502 false 503 ); 504 SpSystemTrace.sliceRangeMark = undefined; 505 window.publish(window.SmartEvent.UI.RefreshCanvas, {}); 506 } 507 } 508 } 509 } 510 }).observe(sp, { 511 attributes: true, 512 childList: false, 513 subtree: false, 514 }); 515} 516function intersectionObserverHandler(sp: SpSystemTrace) { 517 sp.intersectionObserver = new IntersectionObserver( 518 (entries) => { 519 entries.forEach((it) => { 520 let tr = it.target as TraceRow<any>; 521 tr.intersectionRatio = it.intersectionRatio; 522 if (!it.isIntersecting) { 523 tr.sleeping = true; 524 sp.invisibleRows.indexOf(tr) == -1 && sp.invisibleRows.push(tr); 525 sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping); 526 } else { 527 tr.sleeping = false; 528 sp.visibleRows.indexOf(tr) == -1 && sp.visibleRows.push(tr); 529 sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping); 530 } 531 sp.visibleRows 532 .filter((vr) => vr.expansion) 533 .forEach((vr) => { 534 vr.sticky = sp.visibleRows.some((vro) => vr.childrenList.filter((it) => !it.collect).indexOf(vro) >= 0); 535 }); 536 sp.visibleRows 537 .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion) 538 .forEach((vr) => (vr.parentRowEl!.sticky = true)); 539 if (sp.handler) { 540 clearTimeout(sp.handler); 541 } 542 sp.handler = setTimeout(() => sp.refreshCanvas(false), 100); 543 }); 544 }, 545 { threshold: [0, 0.01, 0.99, 1] } 546 ); 547} 548function observerHandler(sp: SpSystemTrace) { 549 resizeObserverHandler(sp); 550 mutationObserverHandler(sp); 551 intersectionObserverHandler(sp); 552} 553function windowKeyDownHandler(sp: SpSystemTrace) { 554 return function (ev: KeyboardEvent) { 555 if (ev.key.toLocaleLowerCase() === 'escape') { 556 sp.queryAllTraceRow().forEach((it) => { 557 it.checkType = '-1'; 558 }); 559 TraceRow.rangeSelectObject = undefined; 560 sp.rangeSelect.rangeTraceRow = []; 561 sp.selectStructNull(); 562 sp.timerShaftEL?.setSlicesMark(); 563 sp.traceSheetEL?.setAttribute('mode', 'hidden'); 564 sp.removeLinkLinesByBusinessType('janks', 'task'); 565 } 566 } 567} 568function smartEventSubscribe(sp: SpSystemTrace) { 569 window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data)); 570 window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => {}); 571 window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false)); 572 window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => { 573 sp.keyboardEnable = tr.enable; 574 if (!sp.keyboardEnable) { 575 sp.stopWASD(); 576 } 577 }); 578 window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => { 579 if (!collapse) { 580 // 一键折叠之前,记录当前打开的泳道图 581 sp.expandRowList = 582 Array.from(sp.rowsEL!.querySelectorAll<TraceRow<any>>(`trace-row[folder][expansion]`)) || []; 583 } 584 sp.collapseAll = true; 585 sp.setAttribute('disable', ''); 586 sp.expandRowList!.forEach((it) => (it.expansion = collapse)); 587 sp.collapseAll = false; 588 sp.removeAttribute('disable'); 589 sp.refreshCanvas(true); 590 }); 591 window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => { 592 sp.mouseEventEnable = tr.mouseEnable; 593 if (sp.mouseEventEnable) { 594 sp.removeAttribute('disable'); 595 } else { 596 sp.setAttribute('disable', ''); 597 } 598 }); 599 window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => sp.currentCollectGroup = group); 600} 601 602export function documentInitEvent(sp:SpSystemTrace) : void{ 603 if (!document) { 604 return 605 } 606 document.addEventListener('triangle-flag', triangleFlagHandler(sp)); 607 document.addEventListener('number_calibration', numberCalibrationHandler(sp)); 608 document.addEventListener('flag-change', flagChangeHandler(sp)); 609 document.addEventListener('slices-change', slicesChangeHandler(sp)); 610 if (sp.timerShaftEL?.collecBtn) { 611 sp.timerShaftEL.collecBtn.onclick = () => { 612 if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) { 613 sp.timerShaftEL!.collecBtn!.removeAttribute('close'); 614 sp.favoriteChartListEL?.showCollectArea(); 615 } else { 616 sp.timerShaftEL!.collecBtn!.setAttribute('close', ''); 617 sp.favoriteChartListEL?.hideCollectArea(); 618 } 619 }; 620 } 621 document.addEventListener('collect', collectHandler(sp)); 622} 623 624export function spSystemTraceInitElement(sp:SpSystemTrace){ 625 window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines()); 626 sp.traceSheetEL = sp.shadowRoot?.querySelector<TraceSheet>('.trace-sheet'); 627 if (!sp || !sp.shadowRoot || !sp.traceSheetEL){ 628 return; 629 } 630 let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot 631 ?.querySelector('#current-selection > tabpane-current-selection') 632 ?.shadowRoot?.querySelector('#rightButton'); 633 let rightStar: HTMLElement | null | undefined =sp.traceSheetEL.shadowRoot 634 ?.querySelector('#current-selection > tabpane-current-selection') 635 ?.shadowRoot?.querySelector('#right-star'); 636 sp.tipEL = sp.shadowRoot.querySelector<HTMLDivElement>('.tip'); 637 sp.rowsPaneEL = sp.shadowRoot.querySelector<HTMLDivElement>('.rows-pane'); 638 sp.rowsEL = sp.rowsPaneEL; 639 sp.spacerEL = sp.shadowRoot.querySelector<HTMLDivElement>('.spacer'); 640 sp.timerShaftEL = sp.shadowRoot.querySelector<TimerShaftElement>('.timer-shaft'); 641 sp.favoriteChartListEL = sp.shadowRoot.querySelector<SpChartList>('#favorite-chart-list'); 642 if (!sp.traceSheetEL.shadowRoot){ 643 return; 644 } 645 sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector<TabPaneFrequencySample>('tabpane-frequency-sample'); 646 sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector<TabPaneCounterSample>('tabpane-counter-sample'); 647 sp.rangeSelect = new RangeSelect(sp); 648 rightButton?.addEventListener('click', rightButtonOnClick(sp,rightStar)); 649 rightStar?.addEventListener('click', rightStarOnClick(sp)); 650 documentInitEvent(sp); 651 SpSystemTrace.scrollViewWidth = sp.getScrollWidth(); 652 selectHandler(sp); 653 observerHandler(sp); 654 window.addEventListener('keydown', windowKeyDownHandler(sp)); 655 sp.chartManager = new SpChartManager(sp); 656 sp.canvasPanel = sp.shadowRoot.querySelector<HTMLCanvasElement>('#canvas-panel')!; 657 sp.canvasPanelCtx = sp.canvasPanel.getContext('2d'); 658 sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context(); 659 sp.canvasPanelConfig(); 660 smartEventSubscribe(sp); 661} 662 663function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: any) { 664 sp.moveRangeToCenter(findEntry.startTime!, findEntry.dur!); 665 sp.queryAllTraceRow().forEach((item) => { 666 item.highlight = false; 667 }); 668 if (findEntry.type == 'cpu') { 669 findEntryTypeCpu(sp, findEntry); 670 } else if (findEntry.type == 'func') { 671 findEntryTypeFunc(sp, findEntry); 672 } else if (findEntry.type == 'thread||process') { 673 findEntryTypeThreadProcess(sp, findEntry); 674 } else if (findEntry.type == 'sdk') { 675 findEntryTypeSdk(sp, findEntry); 676 } 677 sp.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); 678} 679 680export function spSystemTraceShowStruct(sp:SpSystemTrace,previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex?: number){ 681 if (structs.length == 0) { 682 return 0; 683 } 684 let findIndex = spSystemTraceShowStructFindIndex(sp,previous,currentIndex,structs,retargetIndex); 685 let findEntry: any; 686 if (findIndex >= 0) { 687 findEntry = structs[findIndex]; 688 } else { 689 if (previous) { 690 for (let i = structs.length - 1; i >= 0; i--) { 691 let it = structs[i]; 692 if (it.startTime! + it.dur! < TraceRow.range!.startNS) { 693 findIndex = i; 694 break; 695 } 696 } 697 if (findIndex == -1) { 698 findIndex = structs.length - 1; 699 } 700 } else { 701 findIndex = structs.findIndex((it) => it.startTime! > TraceRow.range!.endNS); 702 if (findIndex == -1) { 703 findIndex = 0; 704 } 705 } 706 findEntry = structs[findIndex]; 707 } 708 moveRangeToCenterAndHighlight(sp, findEntry); 709 return findIndex; 710} 711function spSystemTraceShowStructFindIndex(sp: SpSystemTrace, previous: boolean, currentIndex: number, structs: Array<any>, retargetIndex: number | undefined) { 712 let findIndex = -1; 713 if (previous) { 714 if (retargetIndex) { 715 findIndex = retargetIndex - 1; 716 } else { 717 for (let i = structs.length - 1; i >= 0; i--) { 718 let it = structs[i]; 719 if ( 720 i < currentIndex 721 ) { 722 findIndex = i; 723 break; 724 } 725 } 726 } 727 } else { 728 if (currentIndex == -1) { 729 findIndex = 0; 730 } else { 731 findIndex = structs.findIndex((it, idx) => { 732 return ( 733 idx > currentIndex 734 ); 735 }); 736 } 737 } 738 return findIndex; 739} 740function findEntryTypeCpu(sp: SpSystemTrace, findEntry: any) { 741 CpuStruct.selectCpuStruct = findEntry; 742 CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; 743 sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row) => row.rowType === 'cpu-data').forEach((item) => { 744 if (item.rowId === `${findEntry.cpu}`) { 745 sp.rechargeCpuData( 746 findEntry, 747 item.dataListCache.find((it) => it.startTime > findEntry.startTime) 748 ); 749 item.fixedList = [findEntry]; 750 } 751 item.highlight = item.rowId == `${findEntry.cpu}`; 752 item.draw(true); 753 }); 754 sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); 755 sp.onClickHandler(TraceRow.ROW_TYPE_CPU); 756} 757function findEntryTypeFunc(sp: SpSystemTrace, findEntry: any) { 758 sp.observerScrollHeightEnable = true; 759 sp.moveRangeToCenter(findEntry.startTime!, findEntry.dur!); 760 sp.scrollToActFunc( 761 { 762 startTs: findEntry.startTime, 763 dur: findEntry.dur, 764 tid: findEntry.tid, 765 pid: findEntry.pid, 766 depth: findEntry.depth, 767 argsetid: findEntry.argsetid, 768 funName: findEntry.funName, 769 cookie: findEntry.cookie, 770 }, 771 true 772 ); 773} 774function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: any) { 775 let threadProcessRow = sp.rowsEL?.querySelectorAll<TraceRow<ThreadStruct>>('trace-row')[0]; 776 if (threadProcessRow) { 777 let filterRow = threadProcessRow.childrenList.filter( 778 (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType 779 )[0]; 780 filterRow!.highlight = true; 781 sp.closeAllExpandRows(findEntry.rowParentId); 782 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 783 let completeEntry = () => { 784 sp.hoverStructNull(); 785 sp.selectStructNull(); 786 sp.wakeupListNull(); 787 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 788 }; 789 if (filterRow!.isComplete) { 790 completeEntry(); 791 } else { 792 filterRow!.onComplete = completeEntry; 793 } 794 } 795} 796function findEntryTypeSdk(sp: SpSystemTrace, findEntry: any) { 797 let parentRow = sp.shadowRoot!.querySelector<TraceRow<any>>(`trace-row[row-type='sdk'][folder]`); 798 if (parentRow) { 799 let sdkRow = parentRow.childrenList.filter( 800 (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType 801 )[0]; 802 sdkRow!.highlight = true; 803 } 804 sp.hoverStructNull(); 805 sp.selectStructNull(); 806 sp.wakeupListNull(); 807 sp.onClickHandler(findEntry.rowType!); 808 sp.closeAllExpandRows(findEntry.rowParentId); 809 sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); 810} 811async function spSystemTraceInitBuffer(sp:SpSystemTrace,param:{buf?:ArrayBuffer;Url?:string},wasmConfigUri:string,progress:Function) { 812 if (param.buf) { 813 let configJson = ''; 814 try { 815 configJson = await fetch(wasmConfigUri).then((res) => res.text()); 816 } catch (e) { 817 error('getWasmConfigFailed', e); 818 } 819 let parseConfig = FlagsConfig.getSpTraceStreamParseConfig(); 820 let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress); 821 if (!status) { 822 return { status: false, msg: msg }; 823 } 824 SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap; 825 return null 826 }else{ 827 return null; 828 } 829} 830async function spSystemTraceInitUrl(sp:SpSystemTrace,param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) { 831 if (param.url) { 832 let { status, msg } = await threadPool.initServer(param.url, progress); 833 if (!status) { 834 return { status: false, msg: msg }; 835 }else{ 836 return null; 837 } 838 }else{ 839 return null; 840 } 841} 842export async function spSystemTraceInit(sp:SpSystemTrace,param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) { 843 progress('Load database', 6); 844 sp.rowsPaneEL!.scroll({top: 0, left: 0}); 845 let rsBuf = await spSystemTraceInitBuffer(sp,param,wasmConfigUri,progress); 846 if (rsBuf) { 847 return rsBuf; 848 } 849 let rsUrl = await spSystemTraceInitUrl(sp,param,wasmConfigUri,progress); 850 if (rsUrl) { 851 return rsUrl; 852 } 853 await sp.chartManager?.init(progress); 854 let rowId: string = ''; 855 sp.rowsEL?.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 856 if (it.name.includes('Ark Ts')) { 857 rowId = it.rowId!; 858 } 859 if (it.folder) it.addEventListener('expansion-change', sp.extracted(it)); 860 }); 861 progress('completed', 100); 862 info('All TraceRow Data initialized'); 863 sp.loadTraceCompleted = true; 864 sp.rowsEL!.querySelectorAll<TraceRow<any>>('trace-row').forEach((it) => { 865 if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) { 866 it.addTemplateTypes('Ark Ts'); 867 for (let child of it.childrenList) { 868 child.addTemplateTypes('Ark Ts'); 869 } 870 } 871 if (it.folder) { 872 let offsetYTimeOut: any = undefined; 873 it.addEventListener('expansion-change', expansionChangeHandler(sp,offsetYTimeOut)); 874 } 875 if (sp.loadTraceCompleted) { 876 sp.traceSheetEL?.displaySystemLogsData(); 877 } 878 sp.intersectionObserver?.observe(it); 879 }); 880 return { status: true, msg: 'success' }; 881} 882function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: any) { 883 return function (event: any) { 884 let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce( 885 (pre, cur) => pre + cur.clientHeight!, 0); 886 let offset = sp.rowsPaneEL!.scrollHeight - max; 887 sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset; 888 JankStruct.delJankLineFlag = false; 889 if (offsetYTimeOut) { 890 clearTimeout(offsetYTimeOut); 891 } 892 if (event.detail.expansion) { 893 offsetYTimeOut = setTimeout(() => { 894 sp.linkNodes.forEach((linkNode) => { 895 JankStruct.selectJankStructList?.forEach((selectStruct: any) => { 896 if (event.detail.rowId == selectStruct.pid) { 897 JankStruct.selectJankStruct = selectStruct; 898 JankStruct.hoverJankStruct = selectStruct; 899 } 900 }); 901 linkNodeHandler(linkNode, sp); 902 }); 903 }, 300); 904 } else { 905 if (JankStruct!.selectJankStruct) { 906 JankStruct.selectJankStructList?.push(<JankStruct>JankStruct!.selectJankStruct); 907 } 908 offsetYTimeOut = setTimeout(() => { 909 sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp)); 910 }, 300); 911 } 912 let refreshTimeOut = setTimeout(() => { 913 sp.refreshCanvas(true); 914 clearTimeout(refreshTimeOut); 915 }, 360); 916 } 917} 918function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace){ 919 if (linkNode[0].rowEL.collect) { 920 linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; 921 } else { 922 linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 923 } 924 linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; 925 if (linkNode[1].rowEL.collect) { 926 linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; 927 } else { 928 linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; 929 } 930 linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; 931} 932 933 934const eventMap = { 935 'cpu-data': 'Cpu', 936 'cpu-state': 'Cpu State', 937 'cpu-freq': 'Cpu Frequency', 938 'cpu-limit-freq': 'Cpu Freq Limit', 939 'process': 'Process', 940 'native-memory': 'Native Memory', 941 'thread': 'Thread', 942 'func': 'Func', 943 'mem': 'Memory', 944 'virtual-memory-cell': 'Virtual Memory', 945 'virtual-memory-group': 'Virtual Memory', 946 'fps': 'FPS', 947 'ability-monitor': 'Ability Monitor', 948 'cpu-ability': 'Cpu Ability', 949 'memory-ability': 'Memory Ability', 950 'disk-ability': 'DiskIO Ability', 951 'network-ability': 'Network Ability', 952 'sdk': 'Sdk', 953 'sdk-counter': 'SDK Counter', 954 'sdk-slice': 'Sdk Slice', 955 'energy': 'Energy', 956 'power-energy': 'Power Event', 957 'system-energy': 'System Event', 958 'anomaly-energy': 'Anomaly Event', 959 'clock-group': 'Clocks', 960 'clock': 'clock', 961 'irq-group': 'Irqs', 962 'irq': 'irq', 963 'hiperf': 'HiPerf (All)', 964 'hiperf-event': 'HiPerf Event', 965 'hiperf-report': 'HiPerf Report', 966 'hiperf-process': 'HiPerf Process', 967 'hiperf-thread': 'HiPerf Thread', 968 'js-memory': 'Js Memory', 969} 970export function spSystemTraceInitPointToEvent(sp: SpSystemTrace) { 971 sp.eventMap = eventMap; 972} 973