Nodejs中獲取當(dāng)前函數(shù)被調(diào)用的行數(shù)及文件名詳解
背景
在自定義Egg.js的請求級別日志這篇文章中,我們實現(xiàn)了自定義請求級別的日志模塊??瓷先スδ苁峭暾?,但好像還缺點什么。
大家在根據(jù)日志追查問題的過程中,很多時候看到了某條log信息想去找出處,但是實際上代碼里面打相同類型的log地方可能不止一處,這時你就比較難去定位這行l(wèi)og到底是哪里打的。
舉個最極端的例子
//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,你在查日志的時候,是無法區(qū)分log到底是first里面打的還是second里面打的。
這個時候,我們就需要在日志打印的時候,同時也將調(diào)用日志時的文件名和代碼行數(shù)記錄下來一并打印,效果如下
[2018-11-02 19:25:09.665][22896][home.js:4][/] in controller
開始動手
查了很久的Nodejs文檔,發(fā)現(xiàn)Nodejs的api中并沒有直接提供我們想到的信息,所以只能另找出路。
回憶我們以往的開發(fā),這類的信息好像只有在Nodejs拋出異常的時候看到過。每當(dāng)Nodejs拋出異常時,我們都能看到一堆異常調(diào)用的堆棧,里面就有我們想要的信息,我們從這開始入手。
我們先手動創(chuàng)造一個異常對象,并打印出來
function getException() {
try {
throw Error('');
} catch (err) {
return err;
}
}
let err = getException();
console.log(err);
console的信息如下圖:

在圖上我們可以看到,我們想要的信息

err對象在console的時候,會直接輸出err對象中的stack屬性,該屬性是個字符串,我們可以通過一系列的字符串操作,拿到我們想要的文件名和行數(shù)。
接下來我們開始對日志模塊代碼進(jìn)行改造,新增一個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 '[-]';
}
}
最終結(jié)果
最后我們每條打印的日志后面,都會跟上文件名和行數(shù)

有的同學(xué)可能擔(dān)心,每次打log都拋一個異常,會不會對性能造成影響。
我在getCallerFileNameAndLine方法前后進(jìn)行打點統(tǒng)計,平均執(zhí)行時間在2ms左右,所以是可以忽略不計的。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
node.js通過axios實現(xiàn)網(wǎng)絡(luò)請求的方法
下面小編就為大家分享一篇node.js通過axios實現(xiàn)網(wǎng)絡(luò)請求的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03
深入了解 Node的多進(jìn)程服務(wù)實現(xiàn)
本文主要介紹了Node的多進(jìn)程服務(wù)實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
修改Nodejs內(nèi)置的npm默認(rèn)配置路徑方法
今天小編就為大家分享一篇修改Nodejs內(nèi)置的npm默認(rèn)配置路徑方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05

