Skip to content

日志系统

架构升级说明

日志系统已独立重构为子包 @vue3-simple-electron/logger,位于 packages/logger

设计理念

在 Monorepo 架构中,我们将日志模块独立拆分,主要基于以下架构考量:

  1. 解除配置耦合:采用依赖注入模式。它不关心日志存哪里,只提供 setup({ resolvePathFn }) 接口。具体路径由使用方(主进程)在启动时注入。
  2. 依赖隔离:只有本模块直接依赖底层日志库 electron-log
  3. 多进程复用:主进程、渲染进程、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 }); // 不要记录完整 token

4. 记录关键流程

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 - 日志清理工具

相关文档

基于 MIT 许可发布