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 { TraceRow } from '../../component/trace/base/TraceRow'; 17import { drawLoadingFrame, ns2x, Rect, Render } from './ProcedureWorkerCommon'; 18 19import { BaseStruct } from '../../bean/BaseStruct'; 20import { ColorUtils } from '../../component/trace/base/ColorUtils'; 21 22const LOG_STRUCT_HEIGHT = 7; 23const Y_PADDING = 2; 24 25export class LogRender extends Render { 26 renderMainThread( 27 req: { 28 useCache: boolean; 29 context: CanvasRenderingContext2D; 30 type: string; 31 }, 32 row: TraceRow<LogStruct> 33 ): void { 34 let logList = row.dataList; 35 let logFilter = row.dataListCache; 36 filterLogData( 37 logList, 38 logFilter, 39 TraceRow.range!.startNS, 40 TraceRow.range!.endNS, 41 TraceRow.range!.totalNS, 42 row.frame, 43 req.useCache || !TraceRow.range!.refresh 44 ); 45 drawLoadingFrame(req.context, row.dataListCache, row); 46 req.context.beginPath(); 47 for (let re of logFilter) { 48 LogStruct.draw(req.context, re); 49 } 50 req.context.closePath(); 51 } 52} 53 54export function filterLogData( 55 logList: Array<LogStruct>, 56 logFilter: Array<LogStruct>, 57 startNS: number, 58 endNS: number, 59 totalNS: number, 60 frame: any, 61 use: boolean 62): void { 63 if (use && logFilter.length > 0) { 64 for (let i = 0, len = logFilter.length; i < len; i++) { 65 if ((logFilter[i].startTs || 0) + (logFilter[i].dur || 0) >= startNS && (logFilter[i].startTs || 0) <= endNS) { 66 LogStruct.setLogFrame(logFilter[i], 0, startNS, endNS, totalNS, frame); 67 } else { 68 logFilter[i].frame = undefined; 69 } 70 } 71 return; 72 } 73 logFilter.length = 0; 74 setLogFilter(logList, logFilter, startNS, endNS, totalNS, frame); 75} 76function setLogFilter( 77 logList: Array<LogStruct>, 78 logFilter: Array<LogStruct>, 79 startNS: number, 80 endNS: number, 81 totalNS: number, 82 frame: any 83) { 84 if (logList) { 85 let allTypeDataMap: Map<number, Array<LogStruct>> = new Map(); 86 for (let index: number = 0; index < logList.length; index++) { 87 let itemLog: LogStruct = logList[index]; 88 if ((itemLog.startTs ?? 0) + (itemLog.dur ?? 0) >= startNS && (itemLog.startTs ?? 0) <= endNS) { 89 let currentDepth = itemLog.depth ?? 0; 90 if (allTypeDataMap.has(currentDepth)) { 91 let newDataList = allTypeDataMap.get(currentDepth); 92 if (newDataList && newDataList.length > 0) { 93 let preData = newDataList[newDataList.length - 1]; 94 let pre = ns2x(preData.startTs ?? 0, startNS, endNS, totalNS, frame); 95 let current = ns2x(itemLog.startTs || 0, startNS, endNS, totalNS, frame); 96 if (current - pre > 1) { 97 LogStruct.setLogFrame(itemLog, 0, startNS, endNS, totalNS, frame); 98 newDataList!.push(itemLog); 99 } 100 } 101 } else { 102 LogStruct.setLogFrame(itemLog, 0, startNS, endNS, totalNS, frame); 103 allTypeDataMap.set(currentDepth, [itemLog]); 104 } 105 } 106 } 107 for (let index = 0; index < 5; index++) { 108 if (allTypeDataMap.has(index)) { 109 let newVar = allTypeDataMap.get(index); 110 if (newVar) { 111 logFilter.push(...newVar); 112 } 113 } 114 } 115 } 116} 117 118export class LogStruct extends BaseStruct { 119 static hoverLogStruct: LogStruct | undefined; 120 static selectLogStruct: LogStruct | undefined; 121 //日志等级对应颜色,debug、info、warn、error、fatal 122 id: number | undefined; 123 pid: number | undefined; 124 tid: number | undefined; 125 processName: string | undefined; 126 startTs: number | undefined; 127 level: string | undefined; 128 tag: string | undefined; 129 context: string | undefined; 130 originTime: string | undefined; 131 depth: number | undefined; 132 dur: number | undefined; 133 134 static setLogFrame( 135 logNode: LogStruct, 136 padding: number, 137 startNS: number, 138 endNS: number, 139 totalNS: number, 140 frame: any 141 ): void { 142 let x1: number, x2: number; 143 if ((logNode.startTs || 0) > startNS && (logNode.startTs || 0) <= endNS) { 144 x1 = ns2x(logNode.startTs || 0, startNS, endNS, totalNS, frame); 145 } else { 146 x1 = 0; 147 } 148 if ((logNode.startTs || 0) + (logNode.dur || 0) > startNS && (logNode.startTs || 0) + (logNode.dur || 0) <= endNS) { 149 x2 = ns2x((logNode.startTs || 0) + (logNode.dur || 0), startNS, endNS, totalNS, frame); 150 } else { 151 x2 = frame.width; 152 } 153 if (!logNode.frame) { 154 logNode.frame = new Rect(0, 0, 0, 0); 155 } 156 let getV: number = x2 - x1 < 1 ? 1 : x2 - x1; 157 logNode.frame!.x = Math.floor(x1); 158 logNode.frame!.y = logNode.depth! * LOG_STRUCT_HEIGHT; 159 logNode.frame!.width = Math.ceil(getV); 160 logNode.frame!.height = LOG_STRUCT_HEIGHT; 161 } 162 163 static draw(ctx: CanvasRenderingContext2D, logData: LogStruct): void { 164 if (logData.depth === undefined || logData.depth === null) { 165 return; 166 } 167 if (logData.frame) { 168 ctx.globalAlpha = 1; 169 ctx.fillStyle = ColorUtils.getHilogColor(logData.depth); 170 ctx.fillRect(logData.frame.x, logData.frame.y, logData.frame.width, LOG_STRUCT_HEIGHT - Y_PADDING); 171 } 172 } 173 174 static isSelected(data: LogStruct): boolean { 175 return ( 176 LogStruct.selectLogStruct !== undefined && 177 LogStruct.selectLogStruct.startTs === data.startTs && 178 LogStruct.selectLogStruct.depth === data.depth 179 ); 180 } 181} 182