From b331b9421746f4d695f9609a0fa324e732387741 Mon Sep 17 00:00:00 2001 From: xuhong Date: Mon, 17 Jun 2024 15:08:59 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=88=A0=E9=99=A4log=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=87=BD=E6=95=B0=EF=BC=9B=202=E3=80=81=E8=A7=A3?= =?UTF-8?q?=E5=86=B3vector=E5=92=8Ctuple=E5=8F=98=E9=87=8F=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/gdb_expansion.ts | 98 +++++++------------------- src/backend/log.ts | 129 +++++++++++++++++++++++++++++++++++ src/backend/mi2/mi2.ts | 1 - src/mibase.ts | 7 +- 4 files changed, 158 insertions(+), 77 deletions(-) create mode 100644 src/backend/log.ts diff --git a/src/backend/gdb_expansion.ts b/src/backend/gdb_expansion.ts index f383a19..eb8b1c8 100644 --- a/src/backend/gdb_expansion.ts +++ b/src/backend/gdb_expansion.ts @@ -35,52 +35,6 @@ export function isExpandable(value: string): number { import * as fs from "fs"; import * as os from "os"; -const filePath = os.homedir() + '/logs.txt'; - - -const userHomeDir = os.homedir(); -const logQueue = []; // 日志队列 -let isWriting = false; // 是否正在写入日志 - -function writeLogToFile(log, filePath) { - return new Promise((resolve, reject) => { - fs.appendFile(filePath, log + '\n', (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - } - - function processLogQueue() { - if (logQueue.length === 0 || isWriting) { - return; // 如果队列为空或正在写入日志,则不进行处理 - } - - isWriting = true; // 设置正在写入日志的标志 - - const { log, filePath } = logQueue.shift(); // 从队列中取出第一个日志 - - writeLogToFile(log, filePath) - .then(() => { - console.log('日志已成功写入文件:', filePath); - }) - .catch((err) => { - console.error('无法写入日志文件:', err); - }) - .finally(() => { - isWriting = false; // 写入完成后,将正在写入日志的标志设置为false - processLogQueue(); // 继续处理队列中的下一个日志 - }); - } - - function addToLogQueue(log, filePath) { - return; - logQueue.push({ log, filePath }); // 将日志添加到队列中 - processLogQueue(); // 开始处理队列中的日志 - } function isJSON(str) { var jList = []; @@ -98,8 +52,6 @@ function writeLogToFile(log, filePath) { export function expandValue(variableCreate: Function, value: string, root: string = "", extra: any = undefined): any { - addToLogQueue("debug.output::expandValue=====xxxx1", filePath); - addToLogQueue(`debug.output::expandValue=====xxxx2 ${value}: ${JSON.stringify(extra)}`, filePath); let jsonVar = false; if(value.indexOf("=")!=-1){ @@ -165,9 +117,6 @@ export function expandValue(variableCreate: Function, value: string, root: strin //解析字典,json const parseTupleOrList = () => { - - addToLogQueue(`debug.output::parseTupleOrList=====xxxx10 ${value}`, filePath); - value = value.trim(); if (value[0] != '{') return undefined; @@ -192,7 +141,6 @@ export function expandValue(variableCreate: Function, value: string, root: strin const newValPos1 = value.indexOf("{"); const newValPos2 = value.indexOf(","); let newValPos = newValPos1; - addToLogQueue(`debug.output::parseTupleOrList=====xxxx10 ${value}:${eqPos}: ${newValPos}: ${newValPos2}`, filePath); if (newValPos2 != -1 && newValPos2 < newValPos1){ newValPos = newValPos2; @@ -246,8 +194,6 @@ export function expandValue(variableCreate: Function, value: string, root: strin }; const parsePrimitive = () => { - addToLogQueue(`debug.output::parsePrimitive=====xxxx20 ${value}`, filePath); - let primitive: any; let match; value = value.trim(); @@ -296,7 +242,9 @@ export function expandValue(variableCreate: Function, value: string, root: strin parseValue = () => { value = value.trim(); - addToLogQueue(`debug.output::parseValue=====xxxx3 ${value}`, filePath); + // if(value[0] == ','){ + // value = value.substr(1).trim(); + // } if (value[0] == '"'){ //解析字符串 return parseCString(); @@ -305,10 +253,13 @@ export function expandValue(variableCreate: Function, value: string, root: strin return parseTupleOrList(); } else if(value.startsWith("std::vector of length")){ - addToLogQueue(`debug.output::parseValue=====xxxx4 ${value}`, filePath); const eqPos = value.indexOf("="); - value = value.substr(eqPos).trim(); - addToLogQueue(`debug.output::parseValue=====xxxx5 ${value}`, filePath); + value = value.substr(eqPos+1).trim(); + return parseValue(); + } + else if(value.startsWith("std::tuple containing")){ + const eqPos = value.indexOf("="); + value = value.substr(eqPos+1).trim(); return parseValue(); } else{ @@ -317,8 +268,6 @@ export function expandValue(variableCreate: Function, value: string, root: strin }; parseResult = (pushToStack: boolean = false) => { - addToLogQueue(`debug.output::parseResult=====xxxx30 ${value}`, filePath); - value = value.trim(); const variableMatch = resultRegex.exec(value); if (!variableMatch) @@ -346,7 +295,6 @@ export function expandValue(variableCreate: Function, value: string, root: strin createValue = (name, val) => { let ref = 0; let evaluateName; - addToLogQueue(`debug.output::parseResult=====xxxx40 ${value}`, filePath); if (typeof val == "object") { ref = variableCreate(val); @@ -374,21 +322,21 @@ export function expandValue(variableCreate: Function, value: string, root: strin evaluateName = getNamespace(name); } - value = value.trim(); - if (value[0] == ',') - { - var tmp = value - tmp = tmp.substr(1).trim(); - tmp = tmp.trim(); - if(tmp[0] == '{' && jsonVar == true){ - tmp = ",anonymous union = " + tmp; - value = tmp; - } - else if(tmp.startsWith("")){ - value = tmp = tmp.substr("".length); - } + // value = value.trim(); + // if (value[0] == ',') + // { + // var tmp = value + // tmp = tmp.substr(1).trim(); + // tmp = tmp.trim(); + // if(tmp[0] == '{' && jsonVar == true){ + // tmp = ",anonymous union = " + tmp; + // value = tmp; + // } + // else if(tmp.startsWith("")){ + // value = tmp = tmp.substr("".length); + // } - } + // } return { name: name, diff --git a/src/backend/log.ts b/src/backend/log.ts new file mode 100644 index 0000000..a77a0ce --- /dev/null +++ b/src/backend/log.ts @@ -0,0 +1,129 @@ +const fs = require('fs'); +const path = require('path'); +var os = require('os'); + +const MAX_LOG_SIZE = 10 * 1024 * 1024; // 10 MB +const MAX_LOG_FILES = 7; + +const LOG_LEVEL = { + DEBUG: 'DEBUG', + INFO: 'INFO', + WARNING: 'WARNING', + ERROR: 'ERROR' +}; + +let SETLOGLEVEL = LOG_LEVEL.DEBUG; +let localPath = `${os.homedir()}/.debug`; +fs.mkdirSync(localPath, { recursive: true }); + +const logFilePath = path.join(localPath, 'log_1.txt'); + +// 输出通道 +function initializeLogFile() { + try { + // Check if log directory exists + if (!fs.existsSync(localPath)) { + fs.mkdirSync(localPath, { recursive: true }); + } + + // Get all existing log files + const existingLogs = fs.readdirSync(localPath).filter((file: string) => file.startsWith('log_') && file.endsWith('.txt')); + + // Remove excess log files if needed + while (existingLogs.length >= MAX_LOG_FILES) { + const oldestLogFile = getOldestLogFile(existingLogs); + const filePath = path.join(localPath, oldestLogFile); + fs.unlinkSync(filePath); + console.info(`Removed old log file: ${oldestLogFile}`); + existingLogs.splice(existingLogs.indexOf(oldestLogFile), 1); + } + + // Create new log file if it doesn't exist or if the current one exceeds the size limit + if (!fs.existsSync(logFilePath) || fs.statSync(logFilePath).size > MAX_LOG_SIZE) { + rotateLogFiles(); + } + } catch (error) { + console.error('Failed to initialize log file:', error); + } +} + +function getOldestLogFile(logFiles: string | any[]) { + let oldestFile = logFiles[0]; + let oldestFileCreationTime = fs.statSync(path.join(localPath, oldestFile)).birthtime; + for (let i = 1; i < logFiles.length; i++) { + const file = logFiles[i]; + const fileCreationTime = fs.statSync(path.join(localPath, file)).birthtime; + if (fileCreationTime < oldestFileCreationTime) { + oldestFile = file; + oldestFileCreationTime = fileCreationTime; + } + } + return oldestFile; +} + +function rotateLogFiles() { + try { + // Rename existing log files with incremented numbers + for (let i = MAX_LOG_FILES - 1; i > 0; i--) { + const sourceFilePath = path.join(localPath, `log_${i}.txt`); + const destinationFilePath = path.join(localPath, `log_${i + 1}.txt`); + if (fs.existsSync(sourceFilePath)) { + fs.renameSync(sourceFilePath, destinationFilePath); + console.info(`Renamed log file ${sourceFilePath} to ${destinationFilePath}`); + } + } + + // Create new log file + fs.writeFileSync(logFilePath, ''); + } catch (error) { + console.error('Failed to rotate log files:', error); + } +} + +// 初始化日志文件 +initializeLogFile(); + +// 日志输出函数 +function log(level: string, message: any) { + const timestamp = new Date().toISOString(); + const logMessage = `[${timestamp}] [${level}] ${message}`; + if (getLogLevelValue(level) >= getLogLevelValue(SETLOGLEVEL)) { + fs.appendFileSync(logFilePath, logMessage + '\n'); + if (fs.statSync(logFilePath).size > MAX_LOG_SIZE) { + rotateLogFiles(); + } + } +} + +// 记录调试级别的日志 +function debug(message: any) { + log(LOG_LEVEL.DEBUG, message); +} + +// 记录信息级别的日志 +function info(message: any) { + log(LOG_LEVEL.INFO, message); +} + +// 记录警告级别的日志 +function warning(message: any) { + log(LOG_LEVEL.WARNING, message); +} + +// 记录错误级别的日志 +function error(message: any) { + log(LOG_LEVEL.ERROR, message); +} + +function getLogLevelValue(level: string) { + return Object.keys(LOG_LEVEL).indexOf(level); +} + +module.exports = { + debug, + info, + warning, + error, + LOG_LEVEL, + SETLOGLEVEL +}; diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts index d9fed54..e0f10fc 100644 --- a/src/backend/mi2/mi2.ts +++ b/src/backend/mi2/mi2.ts @@ -971,7 +971,6 @@ export class MI2 extends EventEmitter implements IBackend { async getStackVariables(thread: number, frame: number): Promise { if (trace) this.log("stderr", "getStackVariables"); - if (!thread) { if (this.status == 'stopped') { this.currentThreadId = thread; diff --git a/src/mibase.ts b/src/mibase.ts index c3fd60c..ec861ed 100644 --- a/src/mibase.ts +++ b/src/mibase.ts @@ -23,7 +23,6 @@ const STACK_HANDLES_START = 1000; const VAR_HANDLES_START = 512 * 256 + 1000; const VARIABLES_TAG_REGISTER = 0xab; - export class MI2DebugSession extends DebugSession { protected variableHandles = new Handles(VAR_HANDLES_START); protected variableHandlesReverse: { [id: string]: number } = {}; @@ -510,16 +509,19 @@ export class MI2DebugSession extends DebugSession { } return varObj.isCompound() ? id : 0; }; + if (typeof id == "number") { let stack: Variable[]; try { const [threadId, level] = this.frameIdToThreadAndLevel(id); stack = await this.miDebugger.getStackVariables(threadId, level); + for (const variable of stack) { if (this.useVarObjects) { try { const varObjName = `var_${id}_${variable.name}`; let varObj: VariableObject; + try { const changes = await this.miDebugger.varUpdate(varObjName); const changelist = changes.result("changelist"); @@ -551,6 +553,7 @@ export class MI2DebugSession extends DebugSession { } } else { if (variable.valueStr !== undefined) { + let expanded = expandValue(createVariable, `{${variable.name}=${variable.valueStr})`, "", variable.raw); if (expanded) { if (typeof expanded[0] == "string") @@ -588,8 +591,10 @@ export class MI2DebugSession extends DebugSession { // TODO: this evals on an (effectively) unknown thread for multithreaded programs. variable = await this.miDebugger.evalExpression(JSON.stringify(id), 0, 0); try { + let variableValue = variable.result("value"); // 过滤掉 "\\000 " 部分 + variableValue = variableValue.replace(/ '\\000' ,/g, ""); let expanded = expandValue(createVariable, variableValue, id, variable); if (!expanded) {