我找了很多个插件,发现都好难用,npm哪里的说明等于没有,你根本不知道他哪些配置参数怎么弄,百度的文章真的是五花八门,不是抄就是缺胳膊短腿, 想来想去还是自己写好了。

日志的格式我是仿 koa-logger,我感觉他这个样式还不错,但是他这个插件只能console输出,如果是测试环境,还行,但是上线后作为日志保存,就不太行。

我尝试去用他的方法去保存,会乱码,编码我也设置为utf8了,所以无解啊。(超蛋疼有没有)

预览

相对来说还是比较简单。

原理

通过中间件的形式,正常请求和发生错误,为此,我们需要创建一个全局的错误处理中间件,在这个里面我们触发自己写的日志方法。

const logger = require("./libs/logger");

//全局错误处理
server.use(async (ctx, next) => {
    try {
        await next();

        //日志
        logger(ctx);
    } catch (e) {

        //日志
        logger(ctx, e);
    }
});

我们可以看到,我们将ctx对象和e对象传入了,有e的话就是报错了,没有就是正常。

然后我们创建一个模块logger.js

const fs = require("promise-fs");
const path = require("path");
const {
    log_path
} = require("../config");
const moment = require("moment");


const option = {
    flag: "a"
};

//定时删除文件 7day
setInterval(async () => {
    try {
        const dirArr = await fs.readdir(log_path);
        // [ '2020-09-05.log', '2020-09-06.log' ]
        if (dirArr.length) {
            dirArr.forEach(async dir => {
                //如果这个文件已经超过七天了就删除
                const currentTime = moment().format("YYYY-MM-DD");
                const outTime = moment(dir.split(".")[0]).add(7, "d").format("YYYY-MM-DD");

                if (moment(outTime).isBefore(currentTime)) {
                    await fs.unlink(path.join(log_path, dir));
                }
            });
        }
    } catch (e) {
        console.log("自动删除日志文件失败", e);
    }
}, 7 * 24 * 60 * 60 * 1000);




module.exports = async function(ctx, error) {
    //解构
    const {
        request,
        response
    } = ctx;
    //文件路径
    const filePath = path.join(log_path, `${moment().format("YYYY-MM-DD")}.log`);
    //信息
    let message = `>> ${request.method} ${request.url} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
    //是否有错误
    if (!error) {
        //信息
        message += `<< ${request.method} ${response.status} ${response.message} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
    } else {
        //信息
        message += `<< ${request.method} ${response.status} ${response.message} error: ${error.message} ${moment().format("YYYY-MM-DD HH:mm:ss")} \r\n`;
    }

    //写入
    await fs.writeFile(filePath, message, option);
}

使用了promise-fs,他的方法和fs差不多,不过是promise封装,然后还使用了path进行地址拼接,从config配置文件里读取日志的目录,使用了moment 用于时间操作。

fs模块支持第三个参数为配置,默认是覆盖文件模糊,我们改为a模式,这样就是追加模式。

然后就是对ctx对象的信息进行提取,然后合成一个字符,然后fs写入。

难点可能就是自动清理日志文件了。

我设置7天清理一次,先读取目录,获取一个目录下所有文件名的数组,通过split获取到文件名,文件名是时间。

然后通过moment 的方法,判断过期时间是否在当前时间之前。

比如15号是否在23号之前,15号是过期时间,在他之前肯定就是已经过期了,需要删除,然后我们进行删除。

需要注意一下就是这个重复定时间时间不要设置太短,你设置个10ms,肯定会报错的,因为文件可能刚删除了,你又来删除,速度太快也是不行的。

分类: Node 标签: nodekoa

评论

暂无评论数据

暂无评论数据

目录