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

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

内容简介:在大家在根据日志追查问题的过程中,很多时候看到了某条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 左右,所以是可以忽略不计的。


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

查看所有标签

猜你喜欢:

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

函数式算法设计珠玑

函数式算法设计珠玑

Richard Bird / 苏统华、孙芳媛、郝文超、徐琴 / 机械工业出版社 / 2017-4-1 / 69.00

本书采用完全崭新的方式介绍算法设计。全书由30个珠玑构成,每个珠玑单独列为一章,用于解决一个特定编程问题。这些问题的出处五花八门,有的来自游戏或拼图,有的是有趣的组合任务,还有的是散落于数据压缩及字串匹配等领域的更为熟悉的算法。每个珠玑以使用函数式编程语言Haskell对问题进行描述作为开始,每个解答均是诉诸于函数式编程法则从问题表述中计算得到。本书适用于那些喜欢学习算法设计思想的函数式编程人员、......一起来看看 《函数式算法设计珠玑》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

html转js在线工具
html转js在线工具

html转js在线工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具