背景
在“定制Egg.js的请求级日志”一文中,我们实现了一个定制的请求级日志模块。功能看似齐全,但似乎还存在一些不足。
在根据日志追踪问题的过程中,人们经常会看到一条日志消息,想找出地方,但实际上代码中可能不止一个地方键入了相同类型的日志,所以你很难定位日志是在哪里键入的。
举个最极端的例子
//home.jsclass AppController扩展了app。控制器{ async first(){ this . CTX . swlog . info(' in controller ');wait this . CTX . render(' first . html ');} async second(){ this . CTX . swlog . info(' in controller ')等待this . CTX . render(' second . html ');}}虽然上面的例子比较极端,但是我们在代码中难免会遇到类似的情况。路由的两个控制器都打印了相同的日志。当您检查日志时,您无法判断日志是第一次键入还是第二次键入。此时,我们需要在打印日志时记录调用日志时的文件名和代码行数。效果如下
控制器中的[2018-11-02 19:25:09.665][22896][home . js :4][/]
开始
在长期搜索Nodejs文档后,发现Nodejs api并没有直接提供我们想到的信息,只好另辟蹊径。回顾我们过去的发展,这种信息似乎只有在Nodejs抛出异常的时候才能看到。每当Nodejs抛出一个异常时,我们就可以看到一堆带有我们想要的信息的异常调用。让我们从这里开始。我们首先手动创建一个异常对象并将其打印出来
函数getException(){ try { throw Error(“”);} catch(err){ return err;}}让err=GetException();console . log(err);控制台的信息如下:
在地图上,我们可以看到我们想要的信息
当err对象在控制台中时,它将直接输出err对象中的堆栈属性,这是一个字符串。我们可以通过一系列字符串操作获得文件名和所需的行数。
接下来,我们开始通过添加一个getCallerFileNameAndLine方法来改造日志模块代码,如下所示:
getcallerfilenamelandline(){函数getException(){ try { throw Error(“”);} catch(err){ return err;} } const err=GetException();const stack=err.stackconst Stackar=stack . split(' n ');让callerLogIndex=0;for(设I=0;I stack ar . length;i ) { if (stackArr[i]。的索引('映射。logger ')0 I 1 stackar . length){ callerLogIndex=I 1;打破;} } if (callerLogIndex!==0){ const callerStackLine=stack karr[callerLogIndex];返回`[$ { callerstackline . substring(callerstackline . last indexof(path . sep)1,callerstackline . last indexof(' : '))}]`;} else { return '[-]';}}最终结果
最后,在每次打印日志后,我们将跟上文件名和行数
有些学生可能担心每次登录都会抛出异常,影响成绩。我做了getCallerFileNameAndLine方法前后的打点统计,平均执行时间约为2ms,可以忽略。
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。