怎么用目前最好的工具来调试Node.js

原文出处 How to Debug Node.js with the Best Tools Available | @RisingStack

调试是一个在软件中查找和修复缺陷的过程,也是在所有语言中非常有挑战的一个任务。Node.js也不例外。

幸运的是,到目前为止找到这些问题的工具已经改善很多了。让我们来看一下你对你的Node.js应用中修复问题的方法有什见解!

我们将会从两个方面来深入地调试Node.js应用 - 第一个是打印(logging),这样你就可以时刻观察到所有从你生产环境的应用中发出的事件。在logging之后,下一个讨论的是你要怎么才能从你的开发环境中调试你的应用

点击来查看在Scale中所有Node.js的章节

在Node.js中打印信息

在应用执行的过程中打印信息可以知道应用的执行路径,从而有助于理解整个系统的活动进而诊断出bugs并修复它。

在构建Node.js应用的时候,你有很多途径来达到打印信息(logging)的目的。一些npm模块会自带打印消息(logging)的功能,当我们需要调试(https://www.npmjs.com/package/debug)的时候可以手动地打开它。对于自己的应用程序,你也应该有打印消息的功能。接下来我们来举例一下pino

在我们查看logging库之前, 先看看它们要满足哪些依赖

  • timestamps - 它可以使我们知道事件在什么时候发生,

  • formatting - 打印的消息对于程序员来说必需是易懂的,并且对于应用来说也是非常容易直观地转换的

  • log destination - 它应该总是规范输出,应用应该不需要关心它们自身的打印路径,

  • log levels - 打印事件会根据不同的严重程度来分级,但在大多数情况下,你不会关心它们。

Node.js里的debug模块

建议:使用在npm发布的模块

debug是一个轻型的实用的Node.js模块,它是@RisingStack在Node.js核心调试技术出现后发行的

点击转到Tweet

让我们看看它怎么让你的工作变得简单!想象一下你有一个会发送若干个服务请求的Node.js模块:

// index.js
const debugHttpIncoming = require('debug')('http:incoming')
const debugHttpOutgoing = require('debug')('http:outgoing')

let outgoingRequest = {  
  url: 'https://risingstack.com'
}

// sending some request
debugHttpOutgoing('sending request to %s', outgoingRequest.url)

let incomingRequest = {  
  body: '{"status": "ok"}'
}

// serving some request
debugHttpOutgoing('got JSON body %s', incomingRequest.body)

写完以上代码后,用下面的命令来启动:

`DEBUG=http:incoming,http:outgoing node index.js`

然后会输出下面内容:

Output of Node.js Debugging

当然调试模块也支持通配符*,你可以在启动应用前加上DEBUG=http:* node index.js 来显示我们之前得到的结果。

我们觉得应用调试很方便是因为在npm上的许多框架都内置了调试模块,(比如说Express或者Koa),在写这篇文章之前已经有超过14000个调试模块

pino 打印模块

建议:当你遇到性能优化问题的时候使用它

Pino 是一个非常快的Node.js打印模块,参考了bunyan在很多情况下,pino相对于其它框架会快6倍,比如像bunyan或者winston这样的框架。

benchWinston*10000:     2226.117ms  
benchBunyan*10000:      1355.229ms  
benchDebug*10000:       445.291ms  
benchLogLevel*10000:    322.181ms  
benchBole*10000:        291.727ms  
benchPino*10000:        269.109ms  
benchPinoExtreme*10000: 102.239ms

使用下面的代码来启动pino:

const pino = require('pino')()

pino.info('hello pino')  
pino.info('the answer is %d', 42)  
pino.error(new Error('an error'))

上面的代码片断会输出以下的log消息:

{"pid":28325,"hostname":"Gergelys-MacBook-Pro.local","level":30,"time":1492858757722,"msg":"hello pino","v":1}
{"pid":28325,"hostname":"Gergelys-MacBook-Pro.local","level":30,"time":1492858757724,"msg":"the answer is 42","v":1}
{"pid":28325,"hostname":"Gergelys-MacBook-Pro.local","level":50,"time":1492858757725,"msg":"an error","type":"Error","stack":"Error: an error\n    at Object.<anonymous> (/Users/gergelyke/Development/risingstack/node-js-at-scale-debugging/pino.js:5:12)\n    at Module._compile (module.js:570:32)\n    at Object.Module._extensions..js (module.js:579:10)\n    at Module.load (module.js:487:32)\n    at tryModuleLoad (module.js:446:12)\n    at Function.Module._load (module.js:438:3)\n    at Module.runMain (module.js:604:10)\n    at run (bootstrap_node.js:394:7)\n    at startup (bootstrap_node.js:149:9)\n    at bootstrap_node.js:509:3","v":1}

Node.js内置的调试模块

Node.js内置了一个独立的调试工具,通过TCP协议和自带的客户端来实现。你可以通过以下命令来启动它:

`$ node debug index.js`

这个调试工具并不是一个很出色的工具,它没有一个很友好的界面,但是还是可以用来做简单的监听功能。

你可以在你的代码中添加一行debugger来添加一个断点

const express = require('express')  
const app = express()

app.get('/', (req, res) => {  
  debugger
  res.send('ok')
})

通过这种方式你的脚本将会在那一行暂停下来,然后你可以用这个调试工具提供的方法来调试应用:

  • cont or c - continue execution,

  • next or n - step next,

  • step or s - step in,

  • out or o - step out,

  • repl - to evaluate script's context.

V8 为Node.js集成的监听器

V8集成的监视器使得我们可以使用Chrome Debugging Protocol 工具在Chrome DevTools中调试

当我们在启动应用前添加--inspect标志后V8监视器才会被启用。

`$ node --inspect index.js`

在多数情况下,输入下面的命令可以一行一行执行你的代码,使得你不会错过任何执行的语句。

`$ node --inspect-brk index.js`

我建议全屏地观看视频来学习更详细的内容!

怎么通过Visual Studio Code来调试Node.js

**在很多现代IDE中已经支持了调试应用,比如VS Code。它内置Node.js的调试器。

下面你会看到的是VS Code的调试界面,界面上有上下文变量面板、监听面板和函数调用栈面板和断点面板。

VS Code Debugging Layout

图片来源:Visual Studio Code

一个非常有用的特性是Visual Studio Code 调试工具能够添加条件的断点。我们可以在任何时候使用条件来启用或停止断点。

如果你要使用VS Code里更高级的调试功能,就需要去配置一份.vscode/launch.json的配置文件,里面定义了一系列的调试规则。通常默认的launch.json会如下所示:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceRoot}/index.js"
        },
        {
            "type": "node",
            "request": "attach",
            "name": "Attach to Port",
            "address": "localhost",
            "port": 5858
        }
    ]
}

想了解更多launch.json的配置说明,请查阅:https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes.

了解更多Visual Studio Code的调试信息,靖访问官方网站:https://code.visualstudio.com/docs/editor/debugging

接一来

If you have any questions about debugging, please let me know in the comments section. 如果你有任何关于调试的问题,请在评论区中让我知道。

在下一个章节中,我们会讨论怎么优化Node.js应用

Gergely Nemeth's 截图

Gergely Nemeth

Node.js和微服务, 由@Oneshotbudapest @nodebp @jsconfbp维护

Trace - Node.js 和微服务监听工具

node.js debugging debug node.js chrome devtools

关于我们:

我们的博客

请启用Javascript来阅读Disqus强大的评论功能