2017-07-30 150 views
3

得到了一箇舊的應用程序,它使用console.log打印了很多消息,但我找不到在哪個文件和行中調用console.log如何獲取Nodejs中顯示的console.log行號?

有沒有辦法掛鉤到應用程序並顯示文件名和行號?

+0

,你必須檢查,並在每個文件 搜索使用控制檯.log()到'log'東西是一件壞事,你應該使用適當的記錄器功能(你是否擁有或獲得一個npm包)。 Console.log()應該在dev中用來顯示一個變量值。 – sheplu

回答

0

要找到您想要擺脫的日誌語句的臨時攻擊,您自己重寫console.log並不難。

var log = console.log; 
 
console.log = function() { 
 
    log.apply(console, arguments); 
 
    // Print the stack trace 
 
    console.trace(); 
 
}; 
 

 

 
// Somewhere else... 
 
function foo(){ 
 
    console.log('Foobar'); 
 
} 
 
foo();

,將打印像

Foobar 
Trace 
at Console.console.log (index.js:4:13) 
at foo (index.js:10:13) 
at Object.<anonymous> (index.js:12:1) 
... 

大量的噪音,在那裏,但在調用堆棧,at foo (index.js:10:13)第二行,應該指向你在正確的地方。

+0

另一種選擇是直接使用'console.trace('Foobar');'這將是一行清理器,並且您可以節省一個非常好的功能 – Piyin

5

每次通話都有完整的堆棧跟蹤有點吵。我剛剛提高了@ noppa的解決方案只打印發起者:

['log', 'warn', 'error'].forEach((methodName) => { 
    const originalMethod = console[methodName]; 
    console[methodName] = (...args) => { 
    let initiator = 'unknown place'; 
    try { 
     throw new Error(); 
    } catch (e) { 
     if (typeof e.stack === 'string') { 
     let isFirst = true; 
     for (const line of e.stack.split('\n')) { 
      const matches = line.match(/^\s+at\s+(.*)/); 
      if (matches) { 
      if (!isFirst) { // first line - current function 
          // second line - caller (what we are looking for) 
       initiator = matches[1]; 
       break; 
      } 
      isFirst = false; 
      } 
     } 
     } 
    } 
    originalMethod.apply(console, [...args, '\n', ` at ${initiator}`]); 
    }; 
}); 

它還修補等方法(有用的NodeJS,因爲warnerror不要用堆棧跟蹤來作爲在Chrome)。

所以您的控制檯看起來是這樣的:

Loading settings.json 
    at fs.readdirSync.filter.forEach (.../settings.js:21:13) 
Server is running on http://localhost:3000 or http://127.0.0.1:3000 
    at Server.app.listen (.../index.js:67:11) 
+0

,這很好用! –

+1

順便說一下,使用https://github.com/marak/colors.js/並進行此更改:「at $ {initiator}'.green]」確實爲您的產品線提供了顏色的可讀性差別 –

0

我發現Dmitry Druganov's answer真的很不錯,但我想它在Windows 10(與節點8.9.4),並沒有很好地工作。它打印的完整路徑,像:

Loading settings.json 
    at fs.readdirSync.filter.forEach (D:\Users\Piyin\Projects\test\settings.js:21:13) 
Server is running on http://localhost:3000 or http://127.0.0.1:3000 
    at Server.app.listen (D:\Users\Piyin\Projects\test\index.js:67:11) 

所以我把說的答案,做出這些改進(從我的角度來看):

  • 假設堆棧跟蹤的重要行是第一個是Error,第二個是你放置這個腳本的地方
  • 刪除當前腳本文件夾路徑(由__dirname給出,在我的情況下爲D:\Users\Piyin\Projects\test)。注:對於這項工作很好,劇本應該是項目的主要的Javascript
  • 實際的日誌之前刪除起始at
  • 將文件信息
  • 格式的信息Class.method at path/to/file:line:column

這就是:

['log','warn','error'].forEach((methodName) => { 
    const originalMethod = console[methodName]; 
    console[methodName] = (...args) => { 
    try { 
     throw new Error(); 
    } catch (error) { 
     originalMethod.apply(
     console, 
     [ 
      error 
      .stack // Grabs the stack trace 
      .split('\n')[2] // Grabs third line 
      .trim() // Removes spaces 
      .substring(3) // Removes three first characters ("at ") 
      .replace(__dirname, '') // Removes script folder path 
      .replace(/\s\(./, ' at ') // Removes first parentheses and replaces it with " at " 
      .replace(/\)/, '') // Removes last parentheses 
     ), 
      '\n', 
      ...args 
     ] 
    ); 
    } 
    }; 
}); 

而這裏的新的輸出:

fs.readdirSync.filter.forEach at settings.js:21:13 
Loading settings.json 
Server.app.listen at index.js:67:11 
Server is running on http://localhost:3000 or http://127.0.0.1:3000 

這裏的精縮逐手代碼(240個字節):如果你想找到哪裏是你的console.log

['log','warn','error'].forEach(a=>{let b=console[a];console[a]=(...c)=>{try{throw new Error}catch(d){b.apply(console,[d.stack.split('\n')[2].trim().substring(3).replace(__dirname,'').replace(/\s\(./,' at ').replace(/\)/,''),'\n',...c])}}});