教你在Nodejs中如何获取当前函数的调用行数及文件名

栏目: Node.js · 发布时间: 5年前

内容简介:在大家在根据日志追查问题的过程中,很多时候看到了某条log信息想去找出处,但是实际上代码里面打相同类型的log地方可能不止一处,这时你就比较难去定位这行log到底是哪里打的。举个最极端的例子

自定义Egg.js的请求级别日志 这篇文章中,我们实现了自定义请求级别的日志模块。看上去功能是完整了,但好像还缺点什么。

大家在根据日志追查问题的过程中,很多时候看到了某条log信息想去找出处,但是实际上代码里面打相同类型的log地方可能不止一处,这时你就比较难去定位这行log到底是哪里打的。

举个最极端的例子

//home.js
class AppController extends app.Controller {
    async first() {
        this.ctx.swLog.info('in controller');
        await this.ctx.render('first.html');
    }
    
    async second(){
        this.ctx.swLog.info('in controller')
        await this.ctx.render('second.html');
    }
}
复制代码

上面的例子虽然比较极端,但是我们在代码中难免会碰到类似的情况。两个route对于的controller中都打印了相同的log,你在查日志的时候,是无法区分log到底是first里面打的还是second里面打的。

这个时候,我们就需要在日志打印的时候,同时也将调用日志时的文件名和代码行数记录下来一并打印,效果如下

[2018-11-02 19:25:09.665][22896][home.js:4][/] in controller
复制代码

开始动手

查了很久的Nodejs文档,发现Nodejs的api中并没有直接提供我们想到的信息,所以只能另找出路。

回忆我们以往的开发,这类的信息好像只有在Nodejs抛出异常的时候看到过。每当Nodejs抛出异常时,我们都能看到一堆异常调用的堆栈,里面就有我们想要的信息,我们从这开始入手。

我们先手动创造一个异常对象,并打印出来

function getException() {
    try {
        throw Error('');
    } catch (err) {
        return err;
    }
}
        
let err = getException();
console.log(err);
复制代码

console的信息如下图:

教你在Nodejs中如何获取当前函数的调用行数及文件名

在图上我们可以看到,我们想要的信息

教你在Nodejs中如何获取当前函数的调用行数及文件名

err对象在console的时候,会直接输出err对象中的stack属性,该属性是个字符串,我们可以通过一系列的字符串操作,拿到我们想要的文件名和行数。

接下来我们开始对日志模块代码进行改造,新增一个 getCallerFileNameAndLine 方法,如下:

getCallerFileNameAndLine(){
    function getException() {
            try {
                throw Error('');
            } catch (err) {
                return err;
            }
        }
        
    const err = getException();

    const stack = err.stack;
    const stackArr = stack.split('\n');
    let callerLogIndex = 0;
    for (let i = 0; i < stackArr.length; i++) {
        if (stackArr[i].indexOf('Map.Logger') > 0 && i + 1 < stackArr.length) {
            callerLogIndex = i + 1;
            break;
        }
    }

    if (callerLogIndex !== 0) {
        const callerStackLine = stackArr[callerLogIndex];
        return `[${callerStackLine.substring(callerStackLine.lastIndexOf(path.sep) + 1, callerStackLine.lastIndexOf(':'))}]`;
    } else {
        return '[-]';
    }
}

复制代码

最终结果

最后我们每条打印的日志后面,都会跟上文件名和行数

教你在Nodejs中如何获取当前函数的调用行数及文件名

有的同学可能担心,每次打log都抛一个异常,会不会对性能造成影响。

我在 getCallerFileNameAndLine 方法前后进行打点统计,平均执行时间在 2ms 左右,所以是可以忽略不计的。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Ruby

Programming Ruby

Dave Thomas、Chad Fowler、Andy Hunt / Pragmatic Bookshelf / 2004-10-8 / USD 44.95

Ruby is an increasingly popular, fully object-oriented dynamic programming language, hailed by many practitioners as the finest and most useful language available today. When Ruby first burst onto the......一起来看看 《Programming Ruby》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具