Electron ipc实践: 实现简单的日志集中处理

453 阅读2分钟

electron.png

Electorn由一个主线程(main), 调动多个渲染进程(renderer), 其中涉及到进程间通信ipc,我个人理解很像顶层window与多个iframe之间的通讯。 推荐使用electron-better-ipc,提供更好的封装和语义化的api。

有一些公共的事件,或者需要统一处理的业务,虽然是在渲染页面触发的,但是可以选择通过ipc传递给主线程统一处理,避免这种比较底层的代码散落在各个渲染进程。ipc提供了一个新的思路! 可以多尝试(虽然有些大量数据的不适用)。

记录部分作为运行日志的代码

import { ipcMain, ipcRenderer } from 'electron-better-ipc';
import fsPromises from 'node:fs/promises';
import path from 'path';
import dayjs from 'dayjs';

// 声明数据结构
type ILogData = {
    level: 'ERROR' | 'DEBUG', // 这里的类型借鉴了log4js
    name: string; // 主要描述错误的模块位置,函数名,请求名
    data: any; // 携带的信息,err对象等
};

// 主线程监听事件
ipcMain.on('save-log', async(_event, logData: ILogData) => {
    await commitLog(logData);
});
ipcMain.on('save-log', async (_event, logData: ILogData) => {
  await saveLog(logData);
});
ipcMain.on('clear-log', async (_event, p?: string) => {
  await clearLog(p);
});

以下是具体实现

// 上报日志
const commitLog = async (logData: ILogData) => {
  const { level, name, data } = logData;
  await saveLog(logData);
  /** 这里是后端或者钉钉机器人的接口 */
  await comit2Robot(level, name, data);
};

// 保存日志文件
const saveLog = async (logData: ILogData) => {
  try {
    const { level, name, overload } = logData;
    if (!level || !name) return;
    const logPath = path.join(dataFolderPath, 'logger', dayjs().format(YMD));
    const filePath = path.join(
      dataFolderPath,
      'logger',
      dayjs().format(YMD),
      `[${level}] ${name}.txt`,
    ); // 以事件名+类型作为文件名

    (logData as any).time = dayjs().format('HH-mm-ss'); // 额外添加时间字段
    const txt = `${JSON.stringify(logData)}\n\n`;

    fsPromises
      .access(filePath)
      .then(async () => {
        // 如果文件存在: 覆盖 或 追加
        if (overload) {
          await fsPromises.writeFile(filePath, txt, {
            encoding: 'utf-8',
            flag: 'w',
          });
        } else {
          await fsPromises.appendFile(filePath, txt, {
            encoding: 'utf-8',
          });
        }
      })
      .catch(async () => {
        // 如果文件不存在, 则先创建再写入。
        await fsPromises.mkdir(logPath, { recursive: true });
        await fsPromises.writeFile(filePath, txt, {
          encoding: 'utf-8',
          flag: 'a',
        });
      });
  } catch (error) {
    console.log('保存日志失败');
    console.warn(error);
  }
};