内容简介:在大家在根据日志追查问题的过程中,很多时候看到了某条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的信息如下图:
在图上我们可以看到,我们想要的信息
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 '[-]'; } } 复制代码
最终结果
最后我们每条打印的日志后面,都会跟上文件名和行数
有的同学可能担心,每次打log都抛一个异常,会不会对性能造成影响。
我在 getCallerFileNameAndLine
方法前后进行打点统计,平均执行时间在 2ms
左右,所以是可以忽略不计的。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 获取python文件扩展名和文件名方法
- IIS短文件名泄露漏洞
- Linux查找处理文件名后包含空格的文件(两种方法)
- [译] 深度:Linux kernel 支持 UTF-8 文件名
- Go日志,打印源码文件名和行号造成的性能开销
- Linux 5.10.3 发布,修复加密文件名重复的问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
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》 这本书的介绍吧!