概述 #
本应用实现了一个完整的日志记录和管理系统,用于记录应用运行过程中的关键信息、错误和用户操作。日志系统具有自动清理、用户友好的查看界面等特性。
系统架构 #
日志系统由两个核心模块组成:
- 日志记录模块 (
src-electron/log.js) - 负责日志的写入和管理 - 日志集成模块 (
src-electron/main.js) - 负责日志功能在主应用中的集成和用户界面
功能特性 #
1. 自动日志文件管理 #
- 按日期分文件:每天自动创建一个新的日志文件,格式为
YYYY-MM-DD.log - 自动清理:系统自动保留最近 7 天的日志文件,超过 7 天的日志文件将被自动删除
- 文件检查:每次写入前自动检查日志文件是否存在,不存在则自动创建
2. 便捷的用户访问 #
- 托盘菜单集成:在系统托盘右键菜单中提供日志查看选项
- 多种查看方式:
- 查看所有日志:打开日志文件夹,用户可查看所有历史日志
- 查看当天日志:直接打开当天的日志文件
- 智能文件检测:如果当天没有日志文件,会显示友好的提示信息
3. 渲染进程集成 #
- IPC 通信:通过
generate-log通道,渲染进程可以向主进程发送日志消息 - 全应用覆盖:前端 Vue 组件和后端 Electron 主进程都可以记录日志
核心实现 #
日志记录模块 (log.js) #
核心函数实现 #
1. 检查和创建日志文件
function checkLogFile() {
const filePath = `${logs}/${dayjs().format("YYYY-MM-DD")}.log`;
return new Promise((resolve, reject) => {
access(filePath, constants.F_OK, (err) => {
if (err) {
writeFile(filePath, "", (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
} else {
resolve();
}
});
});
}2. 写入日志消息
function log(message) {
const filePath = `${logs}/${dayjs().format("YYYY-MM-DD")}.log`;
return new Promise((resolve, reject) => {
checkLogFile()
.then(() => {
const logMessage = `${dayjs().format(
"YYYY/MM/DD HH:mm:ss"
)}: ${message}\n`;
appendFile(filePath, logMessage, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
})
.catch((err) => {
reject(err);
});
deleteOldLogs();
});
}3. 清理旧日志文件
function deleteOldLogs() {
const daysToKeep = 7;
const currentDate = dayjs();
return new Promise((resolve, reject) => {
readdir(logs, (err, files) => {
if (err) {
return reject("无法扫描目录: " + err);
}
files.forEach((file) => {
// 假设文件名中包含日期,例如:2024-03-01.log
const fileDate = dayjs(file.split(".")[0], "YYYY-MM-DD");
if (fileDate.isBefore(currentDate.subtract(daysToKeep, "days"))) {
const filePath = path.join(logs, file);
unlink(filePath, (err) => {
if (err) {
console.error("无法删除文件 " + filePath + ": " + err);
} else {
console.log("已删除文件: " + filePath);
}
});
}
});
resolve();
});
});
}4. 完整模块导出
const { app } = require("electron");
const {
access,
appendFile,
constants,
writeFile,
unlink,
readdir,
} = require("node:fs");
const dayjs = require("dayjs");
const path = require("path");
const logs = app.getPath("logs");
// 导出主函数
module.exports = log;特点:
- 使用
dayjs进行时间格式化 - 异步文件操作,避免阻塞主线程
- 每次写入都会触发旧日志清理
- 完整的错误处理机制
- 自动管理日志文件生命周期
托盘菜单集成 (main.js) #
托盘菜单实现 #
function createTray() {
tray = new Tray(join(__dirname, "logo.ico"));
const contextMenu = Menu.buildFromTemplate([
{
label: "日志",
submenu: [
{
label: "查看所有日志",
click: () => {
shell.openPath(app.getPath("logs"));
},
},
{
label: "查看当天日志",
click: () => {
const logFilePath = join(
app.getPath("logs"),
`${dayjs().format("YYYY-MM-DD")}.log`
);
if (existsSync(logFilePath)) {
shell.openPath(logFilePath);
} else {
dialog.showMessageBox({
type: "warning",
title: "日志文件不存在",
message: "日志文件不存在,请确认是否有日志文件生成",
buttons: ["确定"],
});
}
},
},
],
},
{
label: "显示",
click: () => {
mainWindow.show();
},
},
{
label: "退出",
click: () => {
log("应用退出");
app.isQuiting = true;
app.quit();
},
},
]);
tray.setToolTip("智衣通");
tray.setContextMenu(contextMenu);
tray.on("click", () => {
mainWindow.show();
});
}IPC 日志处理 #
// 处理来自渲染进程的日志请求
ipcMain.handle("generate-log", (event, message) => {
log(message);
});应用中的日志使用示例 #
// 引入日志模块
const log = require("./log");
// 应用启动时记录日志
app.on("ready", () => {
createWindow();
createTray();
log("应用启动成功");
});
// 自动更新过程中的日志记录
autoUpdater.on("checking-for-update", () => {
log("开始检查更新...");
});
autoUpdater.on("update-available", (info) => {
log(`发现新版本: ${info.version}`);
});
autoUpdater.on("error", (error) => {
log(`更新检查出错: ${error.message}`);
});使用方法 #
1. 在主进程中记录日志 #
const log = require("./log");
// 记录普通信息
log("应用启动成功");
// 记录错误信息
log(`更新检查出错: ${error.message}`);
// 记录用户操作
log("用户选择立即下载更新");2. 在渲染进程中记录日志 #
// 通过IPC发送日志消息到主进程
ipcRenderer.invoke("generate-log", "用户登录成功");3. 查看日志 #
用户可以通过以下方式查看日志:
通过托盘菜单:
- 右键点击系统托盘中的应用图标
- 选择"日志" → "查看所有日志"或"查看当天日志"
直接访问文件:
- 日志文件位置:
app.getPath('logs') - 文件命名格式:
YYYY-MM-DD.log
- 日志文件位置:
日志格式 #
每条日志记录包含以下信息:
YYYY/MM/DD HH:mm:ss: 日志消息内容示例:
2024/03/09 14:30:25: 应用启动成功
2024/03/09 14:30:26: 开始检查更新...
2024/03/09 14:30:28: 当前已是最新版本存储位置 #
日志文件存储在操作系统标准的日志目录中:
- Windows:
%USERPROFILE%\AppData\Roaming\{app-name}\logs - macOS:
~/Library/Logs/{app-name} - Linux:
~/.config/{app-name}/logs
维护策略 #
自动清理机制 #
- 触发时机:每次写入日志时
- 保留策略:保留最近 7 天的日志文件
- 清理逻辑:比较文件名中的日期与当前日期,自动删除过期文件
错误处理 #
- 文件创建失败:返回 Promise rejected 状态
- 写入失败:记录错误并通过 Promise 传递
- 目录扫描失败:在控制台输出错误信息
最佳实践 #
1. 日志内容建议 #
- 包含上下文:记录足够的上下文信息帮助问题定位
- 使用合适的级别:区分普通信息、警告和错误
- 避免敏感信息:不要记录密码、token 等敏感数据
2. 性能考虑 #
- 异步操作:所有文件操作都是异步的,不会阻塞 UI
- 适量记录:避免过度记录导致日志文件过大
- 自动清理:7 天自动清理策略平衡了调试需求和磁盘空间
3. 调试支持 #
- 开发环境:可以增加更详细的调试日志
- 生产环境:记录关键操作和错误信息
- 用户反馈:日志可以帮助用户报告问题时提供更多信息
扩展建议 #
- 日志级别:可以增加不同的日志级别(INFO、WARN、ERROR)
- 日志轮转:可以按文件大小进行日志轮转
- 远程日志:可以考虑将关键日志上传到远程服务器
- 日志分析:可以增加日志分析和统计功能
故障排除 #
常见问题 #
日志文件不存在
- 检查应用是否有写入权限
- 确认日志目录是否可访问
日志写入失败
- 检查磁盘空间是否充足
- 确认文件是否被其他程序占用
旧日志未清理
- 检查文件命名格式是否正确
- 确认日期解析逻辑是否正常工作