Skip to content

日志系统

日志配置

基础配置

日志系统通过 logger-config.jslogger.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 }); // 不要记录完整 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 许可发布