1/* 2 * Copyright (C) 2024 Shenzhen Kaihong Digital Industry Development 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 { BaseStruct, dataFilterHandler, drawLoadingFrame, drawString, isFrameContainPoint, Render } from './ProcedureWorkerCommon'; 17import { TraceRow } from '../../component/trace/base/TraceRow'; 18import { SpSystemTrace } from '../../component/SpSystemTrace'; 19import { HangType } from '../../component/chart/SpHangChart'; 20 21/// Render类 用于处理Hang子泳道的绘制逻辑 22export class HangRender extends Render { 23 renderMainThread( 24 hangReq: { 25 context: CanvasRenderingContext2D; 26 useCache: boolean; 27 type: string; 28 index: number; 29 }, 30 row: TraceRow<HangStruct>, 31 ): void { 32 HangStruct.index = hangReq.index; 33 let hangList = row.dataList; 34 let hangFilter = row.dataListCache; 35 let filterConfig = { 36 startKey: 'startNS', 37 durKey: 'dur', 38 startNS: TraceRow.range?.startNS ?? 0, 39 endNS: TraceRow.range?.endNS ?? 0, 40 totalNS: TraceRow.range?.totalNS ?? 0, 41 frame: row.frame, 42 paddingTop: 2, 43 useCache: hangReq.useCache || !(TraceRow.range?.refresh ?? false), 44 }; 45 dataFilterHandler(hangList, hangFilter, filterConfig); 46 drawLoadingFrame(hangReq.context, hangFilter, row); 47 hangReq.context.beginPath(); 48 let find = false; 49 for (let re of hangFilter) { 50 HangStruct.draw(hangReq.context, re); 51 if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { 52 HangStruct.hoverHangStruct = re; 53 find = true; 54 } 55 } 56 if (!find && row.isHover) { 57 HangStruct.hoverHangStruct = undefined; 58 } 59 hangReq.context.closePath(); 60 } 61} 62 63export function HangStructOnClick(clickRowType: string, sp: SpSystemTrace, scrollCallback: Function): Promise<unknown> { 64 return new Promise((resolve, reject) => { 65 if ((clickRowType === TraceRow.ROW_TYPE_HANG || clickRowType === TraceRow.ROW_TYPE_HANG_INNER) && HangStruct.hoverHangStruct) { 66 HangStruct.selectHangStruct = HangStruct.hoverHangStruct; 67 sp.traceSheetEL?.displayHangData(HangStruct.selectHangStruct, sp, scrollCallback); 68 sp.timerShaftEL?.modifyFlagList(undefined); 69 reject(new Error()); 70 } else { 71 resolve(null); 72 } 73 }); 74} 75 76/// BaseStruct类 存储每个Hang事件详细信息 管理Hang色块绘制细节 77export class HangStruct extends BaseStruct { 78 static hoverHangStruct: HangStruct | undefined; 79 static selectHangStruct: HangStruct | undefined; 80 static index = 0; 81 id: number | undefined; 82 startNS: number | undefined; 83 dur: number | undefined; 84 tid: number | undefined; 85 pid: number | undefined; 86 // 手动补充 按时间分类 87 type: HangType | undefined; 88 // 手动补充 89 pname: string | undefined; 90 // 手动补充 在tab页中需要手动解析内容 91 content: string | undefined; 92 name: string | undefined; 93 94 static getFrameColor(data: HangStruct): string { 95 return ({ 96 'Instant': '#559CFF', 97 'Circumstantial': '#E8BE44', 98 'Micro': '#FEB354', 99 'Severe': '#FC7470', 100 '': '', 101 })[data.type!]; 102 } 103 104 static draw(ctx: CanvasRenderingContext2D, data: HangStruct): void { 105 if (data.frame) { 106 ctx.fillStyle = HangStruct.getFrameColor(data); 107 ctx.strokeStyle = HangStruct.getFrameColor(data); 108 109 ctx.globalAlpha = 1; 110 ctx.lineWidth = 1; 111 112 if (data === HangStruct.hoverHangStruct) { 113 ctx.globalAlpha = 0.7; 114 } 115 116 ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); 117 if (data.frame.width > 10) { 118 ctx.fillStyle = '#000'; 119 drawString(ctx, `${data.type || ''}`, 1, data.frame, data); 120 } 121 122 if (data === HangStruct.selectHangStruct && HangStruct.equals(HangStruct.selectHangStruct, data)) { 123 ctx.strokeStyle = '#000'; 124 ctx.lineWidth = 2; 125 ctx.strokeRect( 126 data.frame.x + 1, 127 data.frame.y + 1, 128 data.frame.width - 2, 129 data.frame.height - 2, 130 ); 131 } 132 133 ctx.globalAlpha = 1; 134 } 135 } 136 137 static isHover(data: HangStruct): boolean { 138 return data === HangStruct.hoverHangStruct || data === HangStruct.selectHangStruct; 139 } 140 static equals(d1: HangStruct, d2: HangStruct): boolean { 141 return ( 142 d1 && 143 d2 && 144 d1.pid === d2.pid && 145 d1.tid === d2.tid && 146 d1.pname === d2.pname && 147 d1.startNS === d2.startNS && 148 d1.dur === d2.dur && 149 d1.type === d2.type && 150 d1.id === d2.id && 151 d1.name === d2.name 152 ); 153 } 154} 155