日志系统
架构升级说明
日志系统已独立重构为子包 @vue3-simple-electron/logger,位于 packages/logger。
设计理念
在 Monorepo 架构中,我们将日志模块独立拆分,主要基于以下架构考量:
- 解除配置耦合:采用依赖注入模式。它不关心日志存哪里,只提供
setup({ resolvePathFn })接口。具体路径由使用方(主进程)在启动时注入。 - 依赖隔离:只有本模块直接依赖底层日志库
electron-log。 - 多进程复用:主进程、渲染进程、Worker 均可统一接入。
日志配置
主进程注入
不需要再修改 logger 内部代码来适配路径,而是在主进程启动时进行配置:
javascript
// packages/main/src/main.js
const logger = require('@vue3-simple-electron/logger');
const { getLogFilePath } = require('./config/logger-config');
// 初始化日志服务,注入路径解析策略
logger.setup({
resolvePathFn: getLogFilePath,
level: app.isPackaged ? 'info' : 'debug',
});路径策略
logger-config.js 依然保留,用于定义路径生成策略,但不再与 logger 强耦合:
javascript
// packages/main/src/config/logger-config.js
/**
* 获取日志文件路径
* 日志按月分目录:logs/YYYY-MM/YYYY-MM-DD.log
*/
function getLogFilePath(date = new Date()) {
const dateStr = date.toISOString().split('T')[0];
const [year, month] = dateStr.split('-');
return path.join(getLogRootPath(), `${year}-${month}`, `${dateStr}.log`);
}使用方法
引入与调用
javascript
const logger = require('@vue3-simple-electron/logger');
// 普通日志
logger.info('这是一条普通日志', { userId: 123 });
// 错误日志
logger.error('发生错误', new Error('Database connection failed'));
// 调试日志
logger.debug('调试信息', variable);日志格式
默认格式配置在 packages/logger/index.js 中:
javascript
// 格式:[时间] [进程标签][级别] 内容
// 例如:[2024-02-05 10:00:00.123] [Main][INFO] 启动成功// 文件输出配置(仅主进程) electronLog.transports.file.level = 'debug'; electronLog.transports.file.maxSize = 1024 _ 1024 _ 10; // 10MB electronLog.transports.file.format = logFormat; electronLog.transports.file.resolvePathFn = () => getLogFilePath();
## 日志目录结构logs/ ├── 2025-11/ │ ├── 2025-11-01.log │ ├── 2025-11-02.log │ └── ... └── 2025-12/ ├── 2025-12-01.log ├── 2025-12-09.log └── ...
- 日志按月份分目录
- 每天一个日志文件
- 文件名格式:`YYYY-MM-DD.log`
## 日志级别
支持以下日志级别(从低到高):
| 级别 | 说明 | 使用场景 |
| --------- | -------- | ---------------- |
| `verbose` | 详细信息 | 调试时的详细输出 |
| `debug` | 调试信息 | 开发调试 |
| `info` | 一般信息 | 正常流程记录 |
| `warn` | 警告信息 | 潜在问题 |
| `error` | 错误信息 | 错误和异常 |
## 使用方法
### 基本使用
```javascript
const logger = require('./utils/logger');
// 信息日志
logger.info('应用启动成功');
// 警告日志
logger.warn('配置项缺失,使用默认值');
// 错误日志
logger.error('操作失败:', error);
// 调试日志
logger.debug('当前状态:', state);
// 详细日志
logger.verbose('详细信息:', details);带上下文的日志
javascript
// 记录对象信息
logger.info('用户登录:', { userId: 123, username: 'admin' });
// 记录错误堆栈
try {
// 操作
} catch (error) {
logger.error('操作失败:', error);
// 会自动记录 error.message 和 error.stack
}进程标识
日志会自动添加进程标识:
[2025-12-09 14:30:25.123] [Main][info] 主进程日志
[2025-12-09 14:30:25.456] [Renderer][info] 渲染进程日志日志清理
自动清理
系统提供日志自动清理功能,通过 LoggerClean 类实现:
javascript
const LoggerClean = require('./utils/logger-clean');
// 启动定时清理任务(每天凌晨 2:00 执行)
LoggerClean.getInstance().startScheduledCleanup();
// 停止定时任务
LoggerClean.getInstance().stopScheduledCleanup();
// 手动清理(删除超过 N 天的日志)
await LoggerClean.getInstance().cleanOldLogs(30); // 保留 30 天清理策略
- 定时清理: 每天凌晨 2:00 自动执行
- 保留期限: 默认保留 30 天的日志
- 清理范围: 按月份目录清理,空目录也会被删除
配置清理参数
可在配置文件中调整清理参数:
ini
# resources/config/config.ini
logRetentionDays = 30 # 日志保留天数输出位置
开发环境
- 控制台: 所有级别的日志
- 文件:
项目根目录/logs/YYYY-MM/YYYY-MM-DD.log
生产环境
- 控制台: 不输出(或仅输出 error)
- 文件:
应用安装目录/logs/YYYY-MM/YYYY-MM-DD.log
日志示例
启动日志
log
[2025-12-09 10:00:00.100] [Main][info] 应用程序启动
[2025-12-09 10:00:00.200] [Main][info] 开发环境配置完成
[2025-12-09 10:00:00.300] [Main][info] 初始化全局错误捕获系统
[2025-12-09 10:00:00.400] [Main][info] 开始注册 IPC 处理器
[2025-12-09 10:00:01.500] [Main][info] 所有 IPC 处理器注册完成 (1100ms)
[2025-12-09 10:00:01.600] [Main][info] 窗口加载模式: remote - 远程模式
[2025-12-09 10:00:02.000] [Main][info] 远程URL加载成功: http://localhost:5173错误日志
log
[2025-12-09 14:30:25.123] [Main][error] 未捕获的异常: Error: Something went wrong
at someFunction (main.js:123:45)
at anotherFunction (main.js:100:20)
...
[2025-12-09 14:30:25.456] [Renderer][error] 渲染进程错误: {
message: "Cannot read property 'value' of undefined",
stack: "TypeError: Cannot read property 'value' of undefined\n at ..."
}更新日志
log
[2025-12-09 15:00:00.000] [Main][info] 应用启动时检查更新: true
[2025-12-09 15:00:00.100] [Main][info] 正在检查更新...
[2025-12-09 15:00:01.200] [Main][info] 发现新版本: 1.2.0 -> 1.3.0
[2025-12-09 15:00:02.000] [Main][info] 开始下载更新: v1.3.0
[2025-12-09 15:00:10.000] [Main][info] 更新下载完成
[2025-12-09 15:00:11.000] [Main][info] 开始安装更新最佳实践
1. 合适的日志级别
javascript
// ✅ 推荐
logger.info('用户登录成功'); // 重要操作
logger.debug('加载配置:', config); // 调试信息
logger.error('数据库连接失败:', error); // 错误
// ❌ 不推荐
logger.error('用户登录成功'); // 不是错误,不应该用 error
logger.info(error); // 错误应该用 error 级别2. 包含上下文信息
javascript
// ✅ 推荐
logger.info('窗口加载模式:', { mode: 'remote', url });
logger.error('文件读取失败:', { path, error });
// ❌ 不推荐
logger.info('加载完成'); // 缺少上下文
logger.error('失败'); // 信息不明确3. 避免敏感信息
javascript
// ✅ 推荐
logger.info('用户认证成功:', { userId: user.id });
// ❌ 不推荐
logger.info('用户登录:', { username, password }); // 不要记录密码
logger.info('API请求:', { token }); // 不要记录完整 token4. 记录关键流程
javascript
// 应用启动
logger.info('应用程序启动');
// 关键操作
logger.info('开始加载窗口:', { mode, url });
logger.info('窗口加载成功');
// 资源清理
logger.info('开始清理资源');
logger.info('资源清理完成');性能考虑
1. 避免频繁日志
javascript
// ❌ 不推荐 - 高频日志
setInterval(() => {
logger.debug('定时器触发');
}, 100); // 每 100ms 一次,会产生大量日志
// ✅ 推荐 - 降低频率或使用合适的级别
setInterval(() => {
logger.verbose('定时器触发'); // 使用 verbose 级别
}, 1000); // 降低频率2. 大对象日志
javascript
// ❌ 不推荐
logger.debug('完整数据:', hugeObject); // 可能导致日志文件过大
// ✅ 推荐
logger.debug('数据摘要:', {
count: hugeObject.length,
firstItem: hugeObject[0],
});相关文件
packages/main/src/config/logger-config.js- 日志配置packages/main/src/utils/logger.js- 日志工具packages/main/src/utils/logger-clean.js- 日志清理工具