From aad6fd78d5a129467386911b09eb35f575e89a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=98=89=E4=BC=9F?= <8473136@qq.com> Date: Wed, 8 Jan 2025 12:01:00 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=8A=20Improve=20the=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/api/config.ts | 82 +++++++-- electron/api/frpc.ts | 233 +++++++++++++++++++------ electron/api/github.ts | 314 ++++++++++++++++++++++++---------- electron/api/local.ts | 11 +- electron/api/proxy.ts | 49 +++++- electron/api/update.ts | 4 - electron/utils/desensitize.ts | 2 - electron/utils/log.ts | 7 +- 8 files changed, 520 insertions(+), 182 deletions(-) diff --git a/electron/api/config.ts b/electron/api/config.ts index 176645f..e4b5ccf 100644 --- a/electron/api/config.ts +++ b/electron/api/config.ts @@ -5,6 +5,7 @@ import { genIniConfig, genTomlConfig, stopFrpcProcess } from "./frpc"; import { clearProxy, insertProxy, listProxy } from "../storage/proxy"; import path from "path"; import fs from "fs"; +import { logDebug, logError, logInfo, LogModule, logWarn } from "../utils/log"; const log = require("electron-log"); const toml = require("@iarna/toml"); @@ -12,14 +13,18 @@ const { v4: uuidv4 } = require("uuid"); export const initConfigApi = win => { ipcMain.on("config.saveConfig", async (event, args) => { + logInfo(LogModule.APP, "Attempting to save configuration."); saveConfig(args, (err, numberOfUpdated, upsert) => { if (!err) { const start = args.systemSelfStart || false; - log.info("开启自启状态", start); + logDebug(LogModule.APP, "Startup status set to: " + start); app.setLoginItemSettings({ openAtLogin: start, //win openAsHidden: start //macOs }); + logInfo(LogModule.APP, "Configuration saved successfully."); + } else { + logError(LogModule.APP, `Error saving configuration: ${err}`); } event.reply("Config.saveConfig.hook", { err: err, @@ -30,7 +35,11 @@ export const initConfigApi = win => { }); ipcMain.on("config.getConfig", async (event, args) => { + logInfo(LogModule.APP, "Requesting configuration."); getConfig((err, doc) => { + if (err) { + logError(LogModule.APP, `Error retrieving configuration: ${err}`); + } event.reply("Config.getConfig.hook", { err: err, data: doc @@ -39,7 +48,11 @@ export const initConfigApi = win => { }); ipcMain.on("config.versions", event => { + logInfo(LogModule.APP, "Requesting version information."); listVersion((err, doc) => { + if (err) { + logError(LogModule.APP, `Error retrieving version information: ${err}`); + } event.reply("Config.versions.hook", { err: err, data: doc @@ -48,7 +61,11 @@ export const initConfigApi = win => { }); ipcMain.on("config.hasConfig", event => { + logInfo(LogModule.APP, "Checking if configuration exists."); getConfig((err, doc) => { + if (err) { + logError(LogModule.APP, `Error checking configuration: ${err}`); + } event.reply("Config.getConfig.hook", { err: err, data: doc @@ -57,15 +74,18 @@ export const initConfigApi = win => { }); ipcMain.on("config.exportConfig", async (event, args) => { + logInfo(LogModule.APP, "Attempting to export configuration."); const result = await dialog.showOpenDialog({ properties: ["openDirectory"] }); const outputDirectory = result.filePaths[0]; if (!outputDirectory) { - // 取消了 + logWarn(LogModule.APP, "Export canceled by user."); return; } - log.info(`导出目录 ${outputDirectory} 类型:${args}`); + log.info( + `Exporting configuration to directory ${outputDirectory} with type: ${args}` + ); getConfig((err1, config) => { if (!err1 && config) { listProxy((err2, proxys) => { @@ -85,33 +105,44 @@ export const initConfigApi = win => { configContent, // 配置文件内容 { flag: "w" }, err => { - if (!err) { - // callback(filename); + if (err) { + logError( + LogModule.APP, + `Error writing configuration file: ${err}` + ); event.reply("config.exportConfig.hook", { data: "导出错误", err: err }); + } else { + logInfo( + LogModule.APP, + "Configuration exported successfully." + ); + event.reply("Config.exportConfig.hook", { + data: { + configPath: configPath + } + }); } } ); - event.reply("Config.exportConfig.hook", { - data: { - configPath: configPath - } - }); + } else { + logError(LogModule.APP, `Error listing proxies: ${err2}`); } }); + } else { + logError(LogModule.APP, `Error retrieving configuration: ${err1}`); } }); }); const parseTomlConfig = (tomlPath: string) => { + logInfo(LogModule.APP, `Parsing TOML configuration from ${tomlPath}`); const importConfigPath = tomlPath; const tomlData = fs.readFileSync(importConfigPath, "utf-8"); - log.info(`读取到配置内容 ${tomlData}`); + logInfo(LogModule.APP, "Configuration content read successfully."); const sourceConfig = toml.parse(tomlData); - // log.info(`解析结果 ${sourceConfig}`); - // console.log(sourceConfig, "frpcConfig"); // 解析config const targetConfig: FrpConfig = { currentVersion: null, @@ -180,6 +211,7 @@ export const initConfigApi = win => { return rm; }); frpcProxys = [...frpcProxys, ...frpcProxys1]; + logInfo(LogModule.APP, "Parsed proxies from configuration."); } // 解析stcp的访问者 if (sourceConfig?.visitors && sourceConfig.visitors.length > 0) { @@ -209,17 +241,24 @@ export const initConfigApi = win => { return rm; }); frpcProxys = [...frpcProxys, ...frpcProxys2]; + logInfo(LogModule.APP, "Parsed visitors from configuration."); } if (targetConfig) { clearConfig(() => { + logInfo(LogModule.APP, "Clearing existing configuration."); saveConfig(targetConfig); + logInfo(LogModule.APP, "New configuration saved."); }); } if (frpcProxys && frpcProxys.length > 0) { clearProxy(() => { frpcProxys.forEach(f => { insertProxy(f, err => { - console.log("插入", f, err); + if (err) { + logError(LogModule.APP, `Error inserting proxy: ${err}`); + } else { + logInfo(LogModule.APP, `Inserted proxy: ${JSON.stringify(f)}`); + } }); }); }); @@ -227,6 +266,7 @@ export const initConfigApi = win => { }; ipcMain.on("config.importConfig", async (event, args) => { + logInfo(LogModule.APP, "Attempting to import configuration."); const result = await dialog.showOpenDialog(win, { properties: ["openFile"], filters: [ @@ -234,17 +274,22 @@ export const initConfigApi = win => { ] }); if (result.canceled) { + logWarn(LogModule.APP, "Import canceled by user."); return; } else { const filePath = result.filePaths[0]; const fileExtension = path.extname(filePath); // 获取文件后缀名 - log.info(`导入文件 ${filePath} ${fileExtension}`); + log.info(`Importing file ${filePath} with extension ${fileExtension}`); if (fileExtension === ".toml") { parseTomlConfig(filePath); event.reply("Config.importConfig.hook", { success: true }); } else { + logError( + LogModule.APP, + `Import failed, unsupported file format: ${fileExtension}` + ); event.reply("Config.importConfig.hook", { success: false, data: `导入失败,暂不支持 ${fileExtension} 格式文件` @@ -254,22 +299,25 @@ export const initConfigApi = win => { }); ipcMain.on("config.clearAll", async (event, args) => { + logInfo(LogModule.APP, "Clearing all configurations."); stopFrpcProcess(() => { clearConfig(); clearProxy(); clearVersion(); event.reply("Config.clearAll.hook", {}); + logInfo(LogModule.APP, "All configurations cleared."); }); }); ipcMain.on("config.openDataFolder", async (event, args) => { const userDataPath = app.getPath("userData"); + logInfo(LogModule.APP, "Attempting to open data folder."); shell.openPath(userDataPath).then(errorMessage => { if (errorMessage) { - console.error("Failed to open Logger:", errorMessage); + logError(LogModule.APP, `Failed to open data folder: ${errorMessage}`); event.reply("Config.openDataFolder.hook", false); } else { - console.log("Logger opened successfully"); + logInfo(LogModule.APP, "Data folder opened successfully."); event.reply("Config.openDataFolder.hook", true); } }); diff --git a/electron/api/frpc.ts b/electron/api/frpc.ts index bf635d1..4925b3a 100644 --- a/electron/api/frpc.ts +++ b/electron/api/frpc.ts @@ -3,11 +3,12 @@ import { getConfig } from "../storage/config"; import { listProxy } from "../storage/proxy"; import { getVersionById } from "../storage/version"; import treeKill from "tree-kill"; +import { logInfo, logError, LogModule, logDebug, logWarn } from "../utils/log"; const fs = require("fs"); const path = require("path"); const { exec, spawn } = require("child_process"); -const log = require("electron-log"); + export let frpcProcess = null; const runningCmd = { commandPath: null, @@ -15,11 +16,6 @@ const runningCmd = { }; let frpcStatusListener = null; -/** - * 获取选择版本的工作目录 - * @param versionId 版本ID - * @param callback - */ const getFrpcVersionWorkerPath = ( versionId: number, callback: (workerPath: string) => void @@ -56,10 +52,10 @@ export const genTomlConfig = (config: FrpConfig, proxys: Proxy[]) => { "\\\\" ); let toml = `${ - rangePort - ? `{{- range $_, $v := parseNumberRangePair "${m.localPort}" "${m.remotePort}" }}` - : "" -} + rangePort + ? `{{- range $_, $v := parseNumberRangePair "${m.localPort}" "${m.remotePort}" }}` + : "" + } [[${ (m.type === "stcp" || m.type === "xtcp" || m.type === "sudp") && m.stcpModel === "visitors" @@ -200,9 +196,9 @@ ${ : "" } ${ - config.tlsConfigEnable && config.tlsConfigKeyFile - ? `transport.tls.keyFile = "${config.tlsConfigKeyFile}"` - : "" + config.tlsConfigEnable && config.tlsConfigKeyFile + ? `transport.tls.keyFile = "${config.tlsConfigKeyFile}"` + : "" } ${ config.tlsConfigEnable && config.tlsConfigTrustedCaFile @@ -408,39 +404,65 @@ export const generateConfig = ( callback: (configPath: string) => void ) => { listProxy((err3, proxys) => { - if (!err3) { - const { currentVersion } = config; - let filename = null; - let configContent = ""; - const filtered = proxys - .map(m => { - if (m.status == null || m.status == undefined) { - m.status = true; - } - return m; - }) - .filter(f => f.status); - if (currentVersion < 124395282) { - // 版本小于v0.52.0 - filename = "frp.ini"; - configContent = genIniConfig(config, filtered); - } else { - filename = "frp.toml"; - configContent = genTomlConfig(config, filtered); - } - const configPath = path.join(app.getPath("userData"), filename); - log.info(`生成配置成功 配置路径:${configPath}`); - fs.writeFile( - configPath, // 配置文件目录 - configContent, // 配置文件内容 - { flag: "w" }, - err => { - if (!err) { - callback(filename); - } + if (err3) { + logError(LogModule.FRP_CLIENT, `Failed to list proxies: ${err3.message}`); + return; + } + + const { currentVersion } = config; + let filename = null; + let configContent = ""; + const filtered = proxys + .map(m => { + if (m.status == null || m.status == undefined) { + m.status = true; } + return m; + }) + .filter(f => f.status); + + if (currentVersion < 124395282) { + // 版本小于v0.52.0 + filename = "frp.ini"; + configContent = genIniConfig(config, filtered); + logInfo( + LogModule.FRP_CLIENT, + `Using INI format for configuration: ${filename}` + ); + } else { + filename = "frp.toml"; + configContent = genTomlConfig(config, filtered); + logInfo( + LogModule.FRP_CLIENT, + `Using TOML format for configuration: ${filename}` ); } + + const configPath = path.join(app.getPath("userData"), filename); + logInfo( + LogModule.FRP_CLIENT, + `Writing configuration to file: ${configPath}` + ); + + fs.writeFile( + configPath, // 配置文件目录 + configContent, // 配置文件内容 + { flag: "w" }, + err => { + if (err) { + logError( + LogModule.FRP_CLIENT, + `Failed to write configuration file: ${err.message}` + ); + } else { + logInfo( + LogModule.FRP_CLIENT, + `Configuration file written successfully: ${filename}` + ); + callback(filename); + } + } + ); }); }; @@ -451,7 +473,13 @@ export const generateConfig = ( * @param configPath */ const startFrpcProcess = (commandPath: string, configPath: string) => { - log.info(`启动frpc 目录:${app.getPath("userData")} 命令:${commandPath}`); + logInfo( + LogModule.FRP_CLIENT, + `Starting frpc process. Directory: ${app.getPath( + "userData" + )}, Command: ${commandPath}` + ); + const command = `${commandPath} -c ${configPath}`; frpcProcess = spawn(command, { cwd: app.getPath("userData"), @@ -459,21 +487,31 @@ const startFrpcProcess = (commandPath: string, configPath: string) => { }); runningCmd.commandPath = commandPath; runningCmd.configPath = configPath; + frpcProcess.stdout.on("data", data => { - log.debug(`启动输出:${data}`); + logDebug(LogModule.FRP_CLIENT, `Frpc process output: ${data}`); }); + frpcProcess.stdout.on("error", data => { - log.error(`启动错误:${data}`); + logError(LogModule.FRP_CLIENT, `Frpc process error: ${data}`); stopFrpcProcess(() => {}); }); + frpcStatusListener = setInterval(() => { const status = frpcProcessStatus(); - log.debug(`监听frpc子进程状态:${status} ${frpcStatusListener}`); + logDebug( + LogModule.FRP_CLIENT, + `Monitoring frpc process status: ${status}, Listener ID: ${frpcStatusListener}` + ); if (!status) { new Notification({ title: "Frpc Desktop", - body: "连接已断开,请前往日志查看原因" + body: "Connection lost, please check the logs for details." }).show(); + logError( + LogModule.FRP_CLIENT, + "Frpc process status check failed. Connection lost." + ); clearInterval(frpcStatusListener); } }, 3000); @@ -484,20 +522,58 @@ const startFrpcProcess = (commandPath: string, configPath: string) => { */ export const reloadFrpcProcess = () => { if (frpcProcess && !frpcProcess.killed) { + logDebug( + LogModule.FRP_CLIENT, + "Attempting to reload frpc process configuration." + ); getConfig((err1, config) => { if (!err1) { if (config) { generateConfig(config, configPath => { const command = `${runningCmd.commandPath} reload -c ${configPath}`; - log.info(`重载配置:${command}`); - exec(command, { - cwd: app.getPath("userData"), - shell: true - }); + logInfo( + LogModule.FRP_CLIENT, + `Reloading configuration: ${command}` + ); + exec( + command, + { + cwd: app.getPath("userData"), + shell: true + }, + (error, stdout, stderr) => { + if (error) { + logError( + LogModule.FRP_CLIENT, + `Error reloading configuration: ${error.message}` + ); + return; + } + logDebug( + LogModule.FRP_CLIENT, + `Configuration reload output: ${stdout}` + ); + if (stderr) { + logWarn( + LogModule.FRP_CLIENT, + `Configuration reload warnings: ${stderr}` + ); + } + } + ); }); + } else { + logWarn(LogModule.FRP_CLIENT, "No configuration found to reload."); } + } else { + logError(LogModule.FRP_CLIENT, `Error getting configuration: ${err1}`); } }); + } else { + logWarn( + LogModule.FRP_CLIENT, + "frpc process is not running or has been killed." + ); } }; @@ -508,16 +584,27 @@ export const stopFrpcProcess = (callback?: () => void) => { if (frpcProcess) { treeKill(frpcProcess.pid, (error: Error) => { if (error) { - log.error(`关闭frpc子进程失败 pid:${frpcProcess.pid} error:${error}`); + logError( + LogModule.FRP_CLIENT, + `Failed to stop frpc process with pid: ${frpcProcess.pid}. Error: ${error.message}` + ); callback(); } else { - log.info(`关闭frpc子进程成功`); + logInfo( + LogModule.FRP_CLIENT, + `Successfully stopped frpc process with pid: ${frpcProcess.pid}.` + ); frpcProcess = null; clearInterval(frpcStatusListener); callback(); } }); } else { + logWarn( + LogModule.FRP_CLIENT, + "Attempted to stop frpc process, but no process is running." + ); + logWarn(LogModule.FRP_CLIENT, "No frpc process to stop."); callback(); } }; @@ -527,14 +614,23 @@ export const stopFrpcProcess = (callback?: () => void) => { */ export const frpcProcessStatus = () => { if (!frpcProcess) { + logWarn(LogModule.FRP_CLIENT, "frpc process is not running."); return false; } try { // 发送信号给进程,如果进程存在,会正常返回 process.kill(frpcProcess.pid, 0); + logDebug( + LogModule.FRP_CLIENT, + `frpc process is running with pid: ${frpcProcess.pid}` + ); return true; } catch (error) { // 进程不存在,抛出异常 + logError( + LogModule.FRP_CLIENT, + `frpc process not found. Error: ${error.message}` + ); return false; } }; @@ -544,29 +640,47 @@ export const frpcProcessStatus = () => { * @param config */ export const startFrpWorkerProcess = async (config: FrpConfig) => { + logInfo(LogModule.FRP_CLIENT, "Starting frpc worker process..."); getFrpcVersionWorkerPath(config.currentVersion, (frpcVersionPath: string) => { if (frpcVersionPath) { + logInfo( + LogModule.FRP_CLIENT, + `Found frpc version path: ${frpcVersionPath}` + ); generateConfig(config, configPath => { const platform = process.platform; if (platform === "win32") { + logInfo(LogModule.FRP_CLIENT, "Starting frpc on Windows."); startFrpcProcess(path.join(frpcVersionPath, "frpc.exe"), configPath); } else { + logInfo( + LogModule.FRP_CLIENT, + "Starting frpc on non-Windows platform." + ); startFrpcProcess(path.join(frpcVersionPath, "frpc"), configPath); } }); + } else { + logError(LogModule.FRP_CLIENT, "frpc version path not found."); } }); }; export const initFrpcApi = () => { ipcMain.handle("frpc.running", async (event, args) => { + logDebug(LogModule.FRP_CLIENT, "Checking if frpc process is running..."); return frpcProcessStatus(); }); ipcMain.on("frpc.start", async (event, args) => { + logInfo(LogModule.FRP_CLIENT, "Received request to start frpc process."); getConfig((err1, config) => { if (!err1) { if (!config) { + logWarn( + LogModule.FRP_CLIENT, + "Configuration not found. Prompting user to set configuration." + ); event.reply( "Home.frpc.start.error.hook", "请先前往设置页面,修改配置后再启动" @@ -574,6 +688,10 @@ export const initFrpcApi = () => { return; } if (!config.currentVersion) { + logWarn( + LogModule.FRP_CLIENT, + "Current version not set in configuration. Prompting user." + ); event.reply( "Home.frpc.start.error.hook", "请先前往设置页面,修改配置后再启动" @@ -581,13 +699,18 @@ export const initFrpcApi = () => { return; } startFrpWorkerProcess(config); + } else { + logError(LogModule.FRP_CLIENT, `Error getting configuration: ${err1}`); } }); }); ipcMain.on("frpc.stop", () => { + logInfo(LogModule.FRP_CLIENT, "Received request to stop frpc process."); if (frpcProcess && !frpcProcess.killed) { stopFrpcProcess(() => {}); + } else { + logWarn(LogModule.FRP_CLIENT, "No frpc process to stop."); } }); }; diff --git a/electron/api/github.ts b/electron/api/github.ts index 45a6669..b19c9d5 100644 --- a/electron/api/github.ts +++ b/electron/api/github.ts @@ -12,6 +12,7 @@ const { download } = require("electron-dl"); const AdmZip = require("adm-zip"); const log = require("electron-log"); import frpReleasesJson from "../json/frp-releases.json"; +import { logInfo, logError, LogModule, logDebug, logWarn } from "../utils/log"; const versionRelation = { win32_x64: ["window", "amd64"], @@ -31,23 +32,45 @@ const frpArch = versionRelation[currArch]; const unTarGZ = (tarGzPath: string, targetPath: string) => { const tar = require("tar"); const unzip = zlib.createGunzip(); - log.debug(`开始解压tar.gz:${tarGzPath} 目标目录:${targetPath}`); + logInfo( + LogModule.APP, + `Starting to extract tar.gz: ${tarGzPath} to ${targetPath}` + ); + const readStream = fs.createReadStream(tarGzPath); if (!fs.existsSync(unzip)) { fs.mkdirSync(targetPath, { recursive: true }); + logInfo(LogModule.APP, `Created target directory: ${targetPath}`); } - readStream.pipe(unzip).pipe( - tar.extract({ - cwd: targetPath, - filter: filePath => path.basename(filePath) === "frpc" + + readStream.on("error", err => { + logError(LogModule.APP, `Error reading tar.gz file: ${err.message}`); + }); + + readStream + .pipe(unzip) + .on("error", err => { + logError(LogModule.APP, `Error during gunzip: ${err.message}`); }) - ); - const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz")); - log.debug(`解压完成 解压后目录:${frpcPath}`); - return frpcPath; - // .on("finish", () => { - // console.log("解压完成!"); - // }); + .pipe( + tar + .extract({ + cwd: targetPath, + filter: filePath => path.basename(filePath) === "frpc" + }) + .on("error", err => { + logError(LogModule.APP, `Error extracting tar file: ${err.message}`); + }) + ) + .on("finish", () => { + const frpcPath = path.join("frp", path.basename(tarGzPath, ".tar.gz")); + logInfo( + LogModule.APP, + `Extraction completed. Extracted directory: ${frpcPath}` + ); + }); + + return path.join("frp", path.basename(tarGzPath, ".tar.gz")); }; const unZip = (zipPath: string, targetPath: string) => { @@ -55,28 +78,37 @@ const unZip = (zipPath: string, targetPath: string) => { fs.mkdirSync(path.join(targetPath, path.basename(zipPath, ".zip")), { recursive: true }); + logInfo(LogModule.APP, `Created target directory: ${targetPath}`); + logInfo( + LogModule.APP, + `Created directory for zip extraction: ${path.basename(zipPath, ".zip")}` + ); } - log.debug(`开始解压zip:${zipPath} 目标目录:${targetPath}`); - /** - * unzipper解压 - */ - // fs.createReadStream(zipPath) - // .pipe(unzipper.Extract({ path: targetPath })) - // // 只解压frpc.exe - // // .pipe(unzipper.ParseOne('frpc')) - // // .pipe(fs.createWriteStream(path.join(targetPath, path.basename(zipPath, ".zip"), "frpc.exe"))) - // .on('finish', () => { - // console.log('File extracted successfully.'); - // }) - // .on('error', (err) => { - // console.error('Error extracting file:', err); - // }); + + logDebug( + LogModule.APP, + `Starting to unzip: ${zipPath} to target directory: ${targetPath}` + ); + logInfo(LogModule.APP, `Starting to extract zip file: ${zipPath}`); const zip = new AdmZip(zipPath); - zip.extractAllTo(targetPath, true); // 第二个参数为 true,表示覆盖已存在的文件 - const frpcPath = path.join("frp", path.basename(zipPath, ".zip")); - log.debug(`解压完成 解压后目录:${frpcPath}`); - return frpcPath; + try { + zip.extractAllTo(targetPath, true); // 第二个参数为 true,表示覆盖已存在的文件 + const frpcPath = path.join("frp", path.basename(zipPath, ".zip")); + logInfo( + LogModule.APP, + `Extraction completed. Extracted directory: ${frpcPath}` + ); + logDebug( + LogModule.APP, + `Unzip completed. Extracted directory: ${frpcPath}` + ); + return frpcPath; + } catch (error) { + logError(LogModule.APP, `Error extracting zip file: ${error.message}`); + } + + return null; }; export const initGitHubApi = () => { @@ -84,40 +116,68 @@ export const initGitHubApi = () => { let versions: FrpVersion[] = []; const getVersion = versionId => { - return versions.find(f => f.id === versionId); + logDebug( + LogModule.GITHUB, + `Attempting to get version with ID: ${versionId}` + ); + const version = versions.find(f => f.id === versionId); + if (version) { + logInfo(LogModule.GITHUB, `Version found: ${JSON.stringify(version)}`); + } else { + logWarn(LogModule.GITHUB, `No version found for ID: ${versionId}`); + } + return version; }; const getAdaptiveAsset = versionId => { const { assets } = getVersion(versionId); + if (!assets || assets.length === 0) { + logWarn(LogModule.GITHUB, `No assets found for version ID: ${versionId}`); + return null; + } + const asset = assets.find(f => { - // const a = versionRelation[currArch] const a = frpArch; if (a) { const flag = a.every(item => f.name.includes(item)); + if (flag) { + logInfo( + LogModule.GITHUB, + `Found matching asset: ${f.name} for version ID: ${versionId}` + ); + } return flag; } + logWarn( + LogModule.GITHUB, + `No architecture match found for asset: ${f.name}` + ); return false; }); - // if (asset) { - // log.info(`找到对应版本 ${asset.name}`); - // } + + if (!asset) { + logError( + LogModule.GITHUB, + `No adaptive asset found for version ID: ${versionId}` + ); + } return asset; }; /** - * 格式化字节信息 - * @param bytes 字节 - * @param decimals 小数位 + * Format byte information + * @param bytes Bytes + * @param decimals Decimal places * @returns */ const formatBytes = (bytes: number, decimals: number = 2): string => { if (bytes === 0) return "0 Bytes"; const k = 1024; // 1 KB = 1024 Bytes - const dm = decimals < 0 ? 0 : decimals; // 确保小数位数不小于 0 + const dm = decimals < 0 ? 0 : decimals; // Ensure decimal places are not less than 0 const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); // 计算单位索引 - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; // 返回格式化的字符串 + const i = Math.floor(Math.log(bytes) / Math.log(k)); // Calculate unit index + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; // Return formatted string }; /** @@ -127,8 +187,15 @@ export const initGitHubApi = () => { */ const handleApiResponse = (githubReleaseJsonStr: string) => { const downloadPath = path.join(app.getPath("userData"), "download"); + logInfo(LogModule.GITHUB, "Parsing GitHub release JSON response."); + versions = JSON.parse(githubReleaseJsonStr); if (versions) { + logInfo( + LogModule.GITHUB, + "Successfully parsed versions from GitHub response." + ); + const returnVersionsData = versions .filter(f => getAdaptiveAsset(f.id)) .map(m => { @@ -143,12 +210,25 @@ export const initGitHubApi = () => { m.download_completed = fs.existsSync(absPath); m.download_count = download_count; m.size = formatBytes(asset.size); + logInfo( + LogModule.GITHUB, + `Asset found: ${asset.name}, download count: ${download_count}` + ); + } else { + logWarn(LogModule.GITHUB, `No asset found for version ID: ${m.id}`); } return m; }); - // log.debug(`获取到frp版本:${JSON.stringify(returnVersionsData)}`) + logDebug( + LogModule.GITHUB, + `Retrieved FRP versions: ${JSON.stringify(returnVersionsData)}` + ); return returnVersionsData; } else { + logError( + LogModule.GITHUB, + "Failed to parse versions: No versions found in response." + ); return []; } }; @@ -172,7 +252,7 @@ export const initGitHubApi = () => { */ ipcMain.on("github.getFrpVersions", async (event, mirror: string) => { const mirrorUrl = conventMirrorUrl(mirror); - log.info("request mirror Url", mirrorUrl); + log.info("Requesting mirror URL: ", mirrorUrl); const request = net.request({ method: "get", url: `${mirrorUrl}/repos/fatedier/frp/releases?page=1&per_page=1000` @@ -180,7 +260,7 @@ export const initGitHubApi = () => { let githubReleaseJsonStr = null; request.on("response", response => { - log.info("request mirror Status Code", response.statusCode); + log.info("Received response with status code: ", response.statusCode); let responseData: Buffer = Buffer.alloc(0); response.on("data", (data: Buffer) => { responseData = Buffer.concat([responseData, data]); @@ -188,8 +268,16 @@ export const initGitHubApi = () => { response.on("end", () => { if (response.statusCode === 200) { githubReleaseJsonStr = responseData.toString(); + logInfo( + LogModule.GITHUB, + "Successfully retrieved GitHub release data." + ); } else { - log.info("use local json", response.statusCode); + logWarn( + LogModule.GITHUB, + "Failed to retrieve data, using local JSON instead. Status code: " + + response.statusCode + ); githubReleaseJsonStr = JSON.stringify(frpReleasesJson); } const versions = handleApiResponse(githubReleaseJsonStr); @@ -198,7 +286,10 @@ export const initGitHubApi = () => { }); request.on("error", error => { - log.info("error use local json", error); + logError( + LogModule.GITHUB, + "Error occurred while requesting GitHub releases: " + error + ); githubReleaseJsonStr = JSON.stringify(frpReleasesJson); const versions = handleApiResponse(githubReleaseJsonStr); event.reply("Download.frpVersionHook", versions); @@ -221,7 +312,11 @@ export const initGitHubApi = () => { url = "https://mirror.ghproxy.com/" + url; } - log.info(`开始下载frp url:${url} asset:${asset.name}`); + logDebug( + LogModule.GITHUB, + `Starting download for versionId: ${versionId}, mirror: ${mirror}, download URL: ${url}` + ); + // 数据目录 await download(BrowserWindow.getFocusedWindow(), url, { filename: `${asset.name}`, @@ -231,29 +326,54 @@ export const initGitHubApi = () => { id: versionId, progress: progress }); + logDebug( + LogModule.GITHUB, + `Download progress for versionId: ${versionId} is ${progress}%` + ); }, onCompleted: () => { log.info(`frp下载完成 url:${url} asset:${asset.name}`); + logInfo( + LogModule.GITHUB, + `Download completed for versionId: ${versionId}, asset: ${asset.name}` + ); + const targetPath = path.resolve( path.join(app.getPath("userData"), "frp") ); const ext = path.extname(asset.name); let frpcVersionPath = ""; - if (ext === ".zip") { - frpcVersionPath = unZip( - path.join( - path.join(app.getPath("userData"), "download"), - `${asset.name}` - ), - targetPath - ); - } else if (ext === ".gz" && asset.name.includes(".tar.gz")) { - frpcVersionPath = unTarGZ( - path.join( - path.join(app.getPath("userData"), "download"), - `${asset.name}` - ), - targetPath + + try { + if (ext === ".zip") { + frpcVersionPath = unZip( + path.join( + path.join(app.getPath("userData"), "download"), + `${asset.name}` + ), + targetPath + ); + logInfo( + LogModule.GITHUB, + `Unzipped file to path: ${frpcVersionPath}` + ); + } else if (ext === ".gz" && asset.name.includes(".tar.gz")) { + frpcVersionPath = unTarGZ( + path.join( + path.join(app.getPath("userData"), "download"), + `${asset.name}` + ), + targetPath + ); + logInfo( + LogModule.GITHUB, + `Untarred file to path: ${frpcVersionPath}` + ); + } + } catch (error) { + logError( + LogModule.GITHUB, + `Error during extraction: ${error.message}` ); } @@ -264,7 +384,13 @@ export const initGitHubApi = () => { event.reply("Config.versions.hook", { err, data: doc }); event.reply("Download.frpVersionDownloadOnCompleted", versionId); version.download_completed = true; + logInfo( + LogModule.GITHUB, + `Version ${versionId} has been inserted successfully.` + ); }); + } else { + logError(LogModule.GITHUB, `Error inserting version: ${err}`); } }); } @@ -276,17 +402,34 @@ export const initGitHubApi = () => { */ ipcMain.on("github.deleteVersion", async (event, args) => { const { absPath, id } = args; + logDebug( + LogModule.GITHUB, + `Attempting to delete version with ID: ${id} and path: ${absPath}` + ); if (fs.existsSync(absPath)) { deleteVersionById(id, () => { fs.unlinkSync(absPath); + logInfo( + LogModule.GITHUB, + `Successfully deleted version with ID: ${id}` + ); }); + } else { + logWarn( + LogModule.GITHUB, + `Version with ID: ${id} not found at path: ${absPath}` + ); } listVersion((err, doc) => { - event.reply("Config.versions.hook", { err, data: doc }); - event.reply("Download.deleteVersion.hook", { - err: null, - data: "删除成功" - }); + if (err) { + logError(LogModule.GITHUB, `Error listing versions: ${err}`); + } else { + event.reply("Config.versions.hook", { err, data: doc }); + event.reply("Download.deleteVersion.hook", { + err: null, + data: "删除成功" + }); + } }); }); @@ -294,6 +437,7 @@ export const initGitHubApi = () => { * 获取最后版本 */ ipcMain.on("github.getFrpcDesktopLastVersions", async event => { + logInfo(LogModule.GITHUB, "Requesting the latest version from GitHub."); const request = net.request({ method: "get", url: "https://api.github.com/repos/luckjiawei/frpc-desktop/releases/latest" @@ -304,26 +448,24 @@ export const initGitHubApi = () => { responseData = Buffer.concat([responseData, data]); }); response.on("end", () => { - versions = JSON.parse(responseData.toString()); - // const borderContent: Electron.WebContents = - // BrowserWindow.getFocusedWindow().webContents; - // const downloadPath = path.join(app.getPath("userData"), "download"); - // log.info(`开始获取frp版本 当前架构:${currArch} 对应frp架构:${frpArch}`) - // const returnVersionsData = versions - // .filter(f => getAdaptiveAsset(f.id)) - // .map(m => { - // const asset = getAdaptiveAsset(m.id); - // if (asset) { - // const absPath = `${downloadPath}/${asset.name}`; - // m.absPath = absPath; - // m.download_completed = fs.existsSync(absPath); - // } - // return m; - // }); - // log.debug(`获取到frp版本:${JSON.stringify(returnVersionsData)}`) - event.reply("github.getFrpcDesktopLastVersionsHook", versions); + try { + versions = JSON.parse(responseData.toString()); + logInfo( + LogModule.GITHUB, + "Successfully retrieved the latest version." + ); + event.reply("github.getFrpcDesktopLastVersionsHook", versions); + } catch (error) { + logError( + LogModule.GITHUB, + `Error parsing response data: ${error.message}` + ); + } }); }); + request.on("error", error => { + logError(LogModule.GITHUB, `Request error: ${error.message}`); + }); request.end(); }); }; diff --git a/electron/api/local.ts b/electron/api/local.ts index 87dad75..bad5b83 100644 --- a/electron/api/local.ts +++ b/electron/api/local.ts @@ -1,5 +1,5 @@ import {ipcMain} from "electron"; -import log from "electron-log"; +import { logDebug, logError, logInfo, LogModule, logWarn } from "electron/utils/log"; const {exec, spawn} = require("child_process"); @@ -15,19 +15,19 @@ export const initLocalApi = () => { : 'netstat -an | grep LISTEN'; ipcMain.on("local.getLocalPorts", async (event, args) => { - log.info("开始获取本地端口") + logInfo(LogModule.APP, "Starting to retrieve local ports"); // 执行命令 exec(command, (error, stdout, stderr) => { if (error) { - log.error(`getLocalPorts - error ${error.message}`) + logError(LogModule.APP, `getLocalPorts - error: ${error.message}`); return; } if (stderr) { - log.error(`getLocalPorts - stderr ${stderr}`) + logWarn(LogModule.APP, `getLocalPorts - stderr: ${stderr}`); return; } - log.debug(`sc ${stdout}`) + logDebug(LogModule.APP, `Command output: ${stdout}`); let ports = []; if (stdout) { if (process.platform === 'win32') { @@ -72,7 +72,6 @@ export const initLocalApi = () => { } return singe; }) - // .filter(f => f.indexOf('TCP') > 0 || f.indexOf('UDP') > 0) } else if (process.platform === 'linux') { ports = stdout.split('\n') diff --git a/electron/api/proxy.ts b/electron/api/proxy.ts index 0bfa26b..bed5d9b 100644 --- a/electron/api/proxy.ts +++ b/electron/api/proxy.ts @@ -8,10 +8,16 @@ import { updateProxyStatus } from "../storage/proxy"; import { reloadFrpcProcess } from "./frpc"; - +import { logError, logInfo, LogModule, logWarn } from "../utils/log"; export const initProxyApi = () => { ipcMain.on("proxy.getProxys", async (event, args) => { + logInfo(LogModule.APP, "Requesting to get proxies."); listProxy((err, documents) => { + if (err) { + logError(LogModule.APP, `Error retrieving proxies: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxies retrieved successfully."); + } event.reply("Proxy.getProxys.hook", { err: err, data: documents @@ -21,8 +27,12 @@ export const initProxyApi = () => { ipcMain.on("proxy.insertProxy", async (event, args) => { delete args["_id"]; + logInfo(LogModule.APP, "Inserting a new proxy."); insertProxy(args, (err, documents) => { - if (!err) { + if (err) { + logError(LogModule.APP, `Error inserting proxy: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxy inserted successfully."); reloadFrpcProcess(); } event.reply("Proxy.insertProxy.hook", { @@ -33,8 +43,12 @@ export const initProxyApi = () => { }); ipcMain.on("proxy.deleteProxyById", async (event, args) => { + logInfo(LogModule.APP, `Deleting proxy with ID: ${args._id}`); deleteProxyById(args, (err, documents) => { - if (!err) { + if (err) { + logError(LogModule.APP, `Error deleting proxy: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxy deleted successfully."); reloadFrpcProcess(); } event.reply("Proxy.deleteProxyById.hook", { @@ -45,7 +59,13 @@ export const initProxyApi = () => { }); ipcMain.on("proxy.getProxyById", async (event, args) => { + logInfo(LogModule.APP, `Requesting proxy with ID: ${args._id}`); getProxyById(args, (err, documents) => { + if (err) { + logError(LogModule.APP, `Error retrieving proxy: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxy retrieved successfully."); + } event.reply("Proxy.getProxyById.hook", { err: err, data: documents @@ -54,9 +74,16 @@ export const initProxyApi = () => { }); ipcMain.on("proxy.updateProxy", async (event, args) => { - if (!args._id) return; + if (!args._id) { + logWarn(LogModule.APP, "No proxy ID provided for update."); + return; + } + logInfo(LogModule.APP, `Updating proxy with ID: ${args._id}`); updateProxyById(args, (err, documents) => { - if (!err) { + if (err) { + logError(LogModule.APP, `Error updating proxy: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxy updated successfully."); reloadFrpcProcess(); } event.reply("Proxy.updateProxy.hook", { @@ -67,10 +94,16 @@ export const initProxyApi = () => { }); ipcMain.on("proxy.updateProxyStatus", async (event, args) => { - console.log("更新状态", args); - if (!args._id) return; + logInfo(LogModule.APP, `Updating status for proxy ID: ${args._id}`); + if (!args._id) { + logWarn(LogModule.APP, "No proxy ID provided for status update."); + return; + } updateProxyStatus(args._id, args.status, (err, documents) => { - if (!err) { + if (err) { + logError(LogModule.APP, `Error updating proxy status: ${err.message}`); + } else { + logInfo(LogModule.APP, "Proxy status updated successfully."); reloadFrpcProcess(); } event.reply("Proxy.updateProxyStatus.hook", { diff --git a/electron/api/update.ts b/electron/api/update.ts index 9d4554d..6c8df1d 100644 --- a/electron/api/update.ts +++ b/electron/api/update.ts @@ -2,7 +2,6 @@ import {app, dialog, autoUpdater, BrowserWindow} from "electron"; const log = require('electron-log'); - export const initUpdaterApi = (win: BrowserWindow) => { //更新测试打开 Object.defineProperty(app, 'isPackaged', { @@ -56,10 +55,7 @@ export const initUpdaterApi = (win: BrowserWindow) => { }) - autoUpdater.on('update-downloaded', () => { - console.log('update-downloaded') - dialog.showMessageBox({ type: 'info', title: '应用更新', diff --git a/electron/utils/desensitize.ts b/electron/utils/desensitize.ts index a77f0f4..ffe579b 100644 --- a/electron/utils/desensitize.ts +++ b/electron/utils/desensitize.ts @@ -2,9 +2,7 @@ export const maskSensitiveData = ( obj: Record, keysToMask: string[] ) => { - console.log("obj", obj); const maskedObj = JSON.parse(JSON.stringify(obj)); - console.log("masked", maskedObj); keysToMask.forEach(key => { if (maskedObj.hasOwnProperty(key)) { maskedObj[key] = "***"; diff --git a/electron/utils/log.ts b/electron/utils/log.ts index 9040e48..b72df27 100644 --- a/electron/utils/log.ts +++ b/electron/utils/log.ts @@ -3,10 +3,9 @@ import log from "electron-log"; export enum LogModule { APP = "app", FRP_CLIENT = "frpc client", - PROXY = "proxy", - DOWNLOAD = "download", - SETTING = "setting", - LOGGER = "logger" + LOGGER = "logger", + GITHUB = "github", + STORAGE = "", } // 设置日志级别