ApliNi / blog

GNU General Public License v3.0
2 stars 0 forks source link

模仿类似 console.log 的打印效果, 获取字符串 #25

Open ApliNi opened 3 months ago

ApliNi commented 3 months ago

将控制台中的日志存储到文件. 由于先前使用 console.log 输出日志时经常需要打印 JS 对象, 在实现日志存储时也希望将这些易读的格式保存到文件中.

模仿 console.log 打印常见对象的格式. 分析:

在此基础上实现:

成品: https://github.com/ApliNi/blog/blob/main/utils/logger.js

效果: image image

// 图 2 测试代码
logger.mark(null, undefined, 1, NaN, Infinity, -Infinity, true, false, [], {}, /./, new Date(), new Error());

主要代码:


import { createWriteStream } from 'fs';

const config = {
    logFile: true,
    logFilePath: './data/latest.log',
};

const writeStream = config.logFile ? createWriteStream(config.logFilePath, {
    flags: 'a',    // 追加模式, 如果文件不存在则创建新文件
    encoding: 'utf8',
}) : {
    write: () => {},
};

export const logger = {

    _getTime(){
        const time = new Date();
        return `${time.getHours().toString().padStart(2, '0')}:${time.getMinutes().toString().padStart(2, '0')}:${time.getSeconds().toString().padStart(2, '0')}`;
    },

    _objectParse: (list, hierarchy = 1, isArray = false) => list.map(obj => {

        if(obj === null){
            return 'null';
        }else if(obj === undefined){
            return 'undefined';
        }

        const constructorName = obj?.constructor?.name || '';

        switch(constructorName){

            case 'String':
                if(isArray){
                    return JSON.stringify(obj);
                }
                return obj;

            case 'Array':
                const strArr = obj.map(item => logger._objectParse([item], hierarchy + 1, true)[0]);
                const length = strArr.map(li => li.length).reduce((a, b) => a + b, 0);

                if(length <= 80){
                    return `[ ${strArr.join(', ')} ]`;
                }

                const indent = ' '.repeat(2 * hierarchy);
                return `[\n${strArr.map(str => str.replace(/^([^\s])/gm, `${indent}$1`)).join(',\n')}\n]`;

            case 'Object':
                const str = JSON.stringify(obj, null, 2 * hierarchy);
                if(str.length <= 80){
                    return str.replace(/\s*\n\s*/g, ' ');
                }
                return str;

            default:
                // console.log(constructorName);
                if(constructorName.includes('Error')){
                    return `${obj.name}: ${obj.message}\n${obj.stack}`;
                }
                else if(obj?.toString){
                    return obj.toString();
                }
                else{
                    return JSON.stringify(obj);
                }
        };
    }),

    info(...log){
        const text = `[${logger._getTime()} INFO]: ${logger._objectParse(log).join(' ')}`;
        console.log(`\x1B[0m${text}\x1B[0m`);
        writeStream.write(`${text}\n`);
    },

    warn(...log){
        const text = `[${logger._getTime()} WARN]: ${logger._objectParse(log).join(' ')}`;
        console.log(`\x1B[93m${text}\x1B[0m`);
        writeStream.write(`${text}\n`);
    },
};