美文网首页
【Electron + Vue】使用log4js

【Electron + Vue】使用log4js

作者: 焜_8899 | 来源:发表于2024-03-26 18:33 被阅读0次

    0. 背景

    Electron 的结构中包含两种类型的进程:主进程渲染器进程。通过源码运行项目时,在主进程中使用 console.log() 打印的信息会被输出到运行项目的终端窗口中,而渲染器进程的内容则会显示在网页开发者工具的控制台里。希望能统一到一个地方来显示日志。

    而且,有时候用 console.log() 会用得比较随意。所以还是想有一个专门的日志工具,使用它提供的功能。

    1. 安装

    可以使用 yarn 安装:

    yarn add log4js
    

    2. 引入

    无论是在主进程还是渲染器进程使用 log4js,都希望日志能显示到同一个地方。这可以通过进程间通信(IPC)来实现,需要用到预加载(preload)脚本

    首先,可以先为 log4js 创建一个专门的文件 src/utils/log.js,设计相关的接口:

    const log4js = require('log4js');
    
    const getLogger = (category, level = 'all') => {
        const logger = log4js.getLogger(category);
        logger.level = level;
        return logger;
    };
    
    export const trace = (event, category, message) => {
        getLogger(category).trace(message);
    };
    
    
    export const debug = (event, category, message) => {
        getLogger(category).debug(message);
    };
    
    
    export const info = (event, category, message) => {
        getLogger(category).info(message);
    };
    
    
    export const warn = (event, category, message) => {
        getLogger(category).warn(message);
    };
    
    
    export const error = (event, category, message) => {
        getLogger(category).error(message);
    };
    
    
    export const fatal = (event, category, message) => {
        getLogger(category).fatal(message);
    };
    
    
    export const mark = (event, category, message) => {
        getLogger(category).mark(message);
    };
    
    

    然后,在 src/main.js 文件中引入这些接口:

    +import {debug, error, fatal, info, mark, trace, warn} from "./utils/log";
     
     // ...
     
     // This method will be called when Electron has finished
     // initialization and is ready to create browser windows.
     // Some APIs can only be used after this event occurs.
    -app.on('ready', createWindow);
    +app.on('ready', () => {
    +  ipcMain.on('log4js:trace', trace);
    +  ipcMain.on('log4js:debug', debug);
    +  ipcMain.on('log4js:info', info);
    +  ipcMain.on('log4js:warn', warn);
    +  ipcMain.on('log4js:error', error);
    +  ipcMain.on('log4js:fatal', fatal);
    +  ipcMain.on('log4js:mark', mark);
    +
    +  createWindow();
    +});
    
    

    之后便可通过预加载脚本 src/preload.js 将接口暴露给渲染器进程:

    // See the Electron documentation for details on how to use preload scripts:
    // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
    const { contextBridge, ipcRenderer } = require('electron');
    
    contextBridge.exposeInMainWorld('getLogger', {
        trace: (category, message) => ipcRenderer.send('log4js:trace', category, message),
        debug: (category, message) => ipcRenderer.send('log4js:debug', category, message),
        info: (category, message) => ipcRenderer.send('log4js:info', category, message),
        warn: (category, message) => ipcRenderer.send('log4js:warn', category, message),
        error: (category, message) => ipcRenderer.send('log4js:error', category, message),
        fatal: (category, message) => ipcRenderer.send('log4js:fatal', category, message),
        mark: (category, message) => ipcRenderer.send('log4js:mark', category, message),
    });
    
    

    这样在主进程和渲染器进程中就都可以调用同样的日志接口了。

    3. 使用

    3.1 主进程

    例如有一个被主进程使用的 src/utils/syscall.js 文件,其中有个 ping() 方法,调用时想要记录一下日志:

    +import {info} from "./log";
    +
     const util = require('util');
     const exec = util.promisify(require('child_process').exec);
     
     export const ping = (event, target) => {
         const ipv4Pattern = /((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/;  // IPv4
         const domainNamePattern = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/;       // 域名
     
         if ((!ipv4Pattern.test(target)) && (!domainNamePattern.test(target))) {
             return Promise.reject(new Error(
                 target.toString() + ' is neither a valid IPv4 address nor a valid domain name.'
             ));
         }
     
    +    info(null, 'syscall.js', `ping ${target}`);
         return exec('ping ' + target);
    };
    
    

    控制台中会打印出:

    [2024-03-26T11:55:46.850] [INFO] syscall.js - ping 127.0.0.1
    

    3.2 渲染器进程

    假设有个 src/components/SampleComponent.vue 文件要记录日志:

     await window.syscall.ping(form.ip).then(() => {  // ping 目标地址
    +    window.getLogger.info('SampleComponent.vue', `ping ${form.ip} success`);
         // ...
     }).catch((error) => {
    +    window.getLogger.error('SampleComponent.vue', error.message);
         // ...
     });
    
    

    控制台会显示:

    [2024-03-26T11:55:49.957] [INFO] SampleComponent.vue - ping 127.0.0.1 success
    [2024-03-26T11:57:22.315] [ERROR] SampleComponent.vue - Error invoking remote method 'ping': Error: Command failed: ping 0.0.0.0
    

    4. 配置

    要修改 log4js 的配置,可以修改 src/utils/log.js 文件中 getLogger() 方法的内容。例如在将日志输出到控制台同时保存到文件。

    -const getLogger = (category, level = 'all') => {
    -    const logger = log4js.getLogger(category);
    -    logger.level = level;
    -    return logger;
    +const getLogger = (category, level = 'info') => {
    +    log4js.configure({
    +        appenders: {
    +            console: { type: 'console' },
    +            dateFile: {
    +                type: 'dateFile',
    +                filename: 'logs/log.log'
    +            }
    +        },
    +        categories: {
    +            default: { appenders: ['console', 'dateFile'], level: level }
    +        }
    +    });
    +    return log4js.getLogger(category);
     };
    

    相关文章

      网友评论

          本文标题:【Electron + Vue】使用log4js

          本文链接:https://www.haomeiwen.com/subject/tetjtjtx.html