日志系统
日志配置
基础配置
日志系统通过 logger-config.js 和 logger.js 进行配置:
javascript
// packages/main/src/config/logger-config.js
const path = require('path');
const { app } = require('electron');
/**
* 获取日志根目录
*/
function getLogRootPath() {
const basePath = app?.isPackaged
? path.dirname(app.getPath('exe')) // 生产环境:应用安装目录
: path.dirname(path.dirname(path.dirname(path.dirname(__dirname)))); // 开发环境:项目根目录
return path.join(basePath, 'logs');
}
/**
* 获取日志文件路径
* 日志按月分目录: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
// packages/main/src/utils/logger.js
const electronLog = require('electron-log');
// 日志格式:[时间] [进程类型][级别] 内容
const logFormat = `[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [${processLabel}][{level}] {text}`;
// 控制台输出配置
electronLog.transports.console.level = 'debug';
electronLog.transports.console.format = logFormat;
// 文件输出配置(仅主进程)
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- 日志清理工具