检查器
源代码: lib/inspector.js
node:inspector
模块提供了一个与 V8 检查器交互的 API。
它可以使用以下方式访问:
import * as inspector from 'node:inspector/promises'
const inspector = require('node:inspector/promises')
或者
import * as inspector from 'node:inspector'
const inspector = require('node:inspector')
Promises API
添加到: v19.0.0
类: inspector.Session
- 继承自: <EventEmitter>
inspector.Session
用于将消息分派到 V8 检查器后端,并接收消息响应和通知。
new inspector.Session()
新增于:v8.0.0
创建一个新的 inspector.Session
类实例。在将消息分发到检查器后端之前,需要通过 session.connect()
连接检查器会话。
使用 Session
时,除非我们手动执行 Runtime.DiscardConsoleEntries
命令,否则控制台 API 输出的对象不会被释放。
事件:'inspectorNotification'
新增于:v8.0.0
- <对象> 通知消息对象
当接收到来自 V8 检查器的任何通知时发出。
session.on('inspectorNotification', message => console.log(message.method))
// Debugger.paused
// Debugger.resumed
也可以只订阅具有特定方法的通知:
事件:<inspector-protocol-method>
; {#event-<inspector-protocol-method>;}
新增于:v8.0.0
- <对象> 通知消息对象
当接收到方法字段设置为 \<inspector-protocol-method\>
值的检查器通知时发出。
以下代码片段为 'Debugger.paused'
事件安装了一个监听器,并在程序执行暂停(例如,通过断点)时打印程序暂停的原因:
session.on('Debugger.paused', ({ params }) => {
console.log(params.hitBreakpoints)
})
// [ '/the/file/that/has/the/breakpoint.js:11:0' ]
session.connect()
新增于:v8.0.0
将会话连接到检查器后端。
session.connectToMainThread()
新增于:v12.11.0
将会话连接到主线程检查器后端。如果此 API 不是在 Worker 线程上调用的,则会抛出异常。
session.disconnect()
新增于:v8.0.0
立即关闭会话。所有挂起的消息回调都将调用错误。需要调用 session.connect()
才能再次发送消息。重新连接的会话将丢失所有检查器状态,例如已启用的代理或已配置的断点。
session.post(method[, params])
新增于:v19.0.0
将消息发布到检查器后端。
import { Session } from 'node:inspector/promises'
try {
const session = new Session()
session.connect()
const result = await session.post('Runtime.evaluate', { expression: '2 + 2' })
console.log(result)
} catch (error) {
console.error(error)
}
// 输出:{ result: { type: 'number', value: 4, description: '4' } }
最新版本的 V8 检查器协议发布在 Chrome DevTools 协议查看器 上。
Node.js 检查器支持 V8 声明的所有 Chrome DevTools 协议域。Chrome DevTools 协议域提供了一个接口,用于与用于检查应用程序状态和监听运行时事件的其中一个运行时代理进行交互。
示例用法
除了调试器之外,还可以通过 DevTools 协议使用各种 V8 分析器。
CPU 分析器
以下示例演示了如何使用 CPU 分析器:
import { Session } from 'node:inspector/promises'
import fs from 'node:fs'
const session = new Session()
session.connect()
await session.post('Profiler.enable')
await session.post('Profiler.start')
// 在此处调用要测量的业务逻辑...
// 一段时间后...
const { profile } = await session.post('Profiler.stop')
// 将概要文件写入磁盘,上传等。
fs.writeFileSync('./profile.cpuprofile', JSON.stringify(profile))
堆分析器
以下示例演示了如何使用 堆分析器:
import { Session } from 'node:inspector/promises'
import fs from 'node:fs'
const session = new Session()
const fd = fs.openSync('profile.heapsnapshot', 'w')
session.connect()
session.on('HeapProfiler.addHeapSnapshotChunk', m => {
fs.writeSync(fd, m.params.chunk)
})
const result = await session.post('HeapProfiler.takeHeapSnapshot', null)
console.log('HeapProfiler.takeHeapSnapshot done:', result)
session.disconnect()
fs.closeSync(fd)
回调 API
类: inspector.Session
- 继承自: <EventEmitter>
inspector.Session
用于将消息分派到 V8 检查器后端,并接收消息响应和通知。
new inspector.Session()
新增于: v8.0.0
创建一个新的 inspector.Session
类实例。在将消息分派到检查器后端之前,需要通过 session.connect()
连接检查器会话。
使用 Session
时,除非我们手动执行 Runtime.DiscardConsoleEntries
命令,否则控制台 API 输出的对象不会被释放。
事件: 'inspectorNotification'
新增于: v8.0.0
- <Object> 通知消息对象
当接收到来自 V8 检查器的任何通知时发出。
session.on('inspectorNotification', message => console.log(message.method))
// Debugger.paused
// Debugger.resumed
也可以只订阅具有特定方法的通知:
事件: <inspector-protocol-method>
; {#event-<inspector-protocol-method>;_1}
新增于: v8.0.0
- <对象> 通知消息对象
当接收到一个其 method 字段设置为 <inspector-protocol-method>
值的检查器通知时发出。
以下代码片段在一个 'Debugger.paused'
事件上安装了一个监听器,并在程序执行暂停(例如,通过断点)时打印程序暂停的原因:
session.on('Debugger.paused', ({ params }) => {
console.log(params.hitBreakpoints)
})
// [ '/the/file/that/has/the/breakpoint.js:11:0' ]
session.connect()
新增于: v8.0.0
将会话连接到检查器后端。
session.connectToMainThread()
新增于: v12.11.0
将会话连接到主线程检查器后端。如果此 API 不是在 Worker 线程上调用的,则会抛出异常。
session.disconnect()
新增于:v8.0.0
立即关闭会话。所有挂起的消息回调都将以错误的方式调用。需要调用 session.connect()
才能再次发送消息。重新连接的会话将丢失所有检查器状态,例如启用的代理或配置的断点。
session.post(method[, params][, callback])
[历史记录]
版本 | 变更 |
---|---|
v18.0.0 | 将无效回调传递给 callback 参数现在抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK 。 |
v8.0.0 | 新增于:v8.0.0 |
向检查器后端发布消息。收到响应后将通知 callback
。callback
是一个函数,它接受两个可选参数:错误和特定于消息的结果。
session.post('Runtime.evaluate', { expression: '2 + 2' }, (error, { result }) => console.log(result))
// 输出:{ type: 'number', value: 4, description: '4' }
最新版本的 V8 检查器协议发布在 Chrome DevTools 协议查看器 上。
Node.js 检查器支持 V8 声明的所有 Chrome DevTools 协议域。Chrome DevTools 协议域提供了一个接口,用于与用于检查应用程序状态并监听运行时事件的运行时代理之一进行交互。
向 V8 发送 HeapProfiler.takeHeapSnapshot
或 HeapProfiler.stopTrackingHeapObjects
命令时,不能将 reportProgress
设置为 true
。
使用示例
除了调试器之外,还可以通过 DevTools 协议使用各种 V8 Profiler。
CPU 性能分析器
以下示例展示了如何使用 CPU 性能分析器:
const inspector = require('node:inspector')
const fs = require('node:fs')
const session = new inspector.Session()
session.connect()
session.post('Profiler.enable', () => {
session.post('Profiler.start', () => {
// 在此处调用需要测量的业务逻辑...
// 一段时间后...
session.post('Profiler.stop', (err, { profile }) => {
// 将性能分析结果写入磁盘、上传等。
if (!err) {
fs.writeFileSync('./profile.cpuprofile', JSON.stringify(profile))
}
})
})
})
堆内存分析器
以下示例展示了如何使用 堆内存分析器:
const inspector = require('node:inspector')
const fs = require('node:fs')
const session = new inspector.Session()
const fd = fs.openSync('profile.heapsnapshot', 'w')
session.connect()
session.on('HeapProfiler.addHeapSnapshotChunk', m => {
fs.writeSync(fd, m.params.chunk)
})
session.post('HeapProfiler.takeHeapSnapshot', null, (err, r) => {
console.log('HeapProfiler.takeHeapSnapshot done:', err, r)
session.disconnect()
fs.closeSync(fd)
})
常用对象
inspector.close()
[历史记录]
版本 | 变更 |
---|---|
v18.10.0 | 此 API 已在 Worker 线程中公开。 |
v9.0.0 | v9.0.0 版本中添加 |
尝试关闭所有剩余的连接,阻塞事件循环直到所有连接都关闭。一旦所有连接都关闭,则停用检查器。
inspector.console
- <对象> 用于向远程检查器控制台发送消息的对象。
require('node:inspector').console.log('a message')
检查器控制台与 Node.js 控制台的 API 不完全一致。
inspector.open([port[, host[, wait]]])
[历史记录]
版本 | 变更 |
---|---|
v20.6.0 | inspector.open() 现在返回一个 Disposable 对象。 |
port
<数字> 检查器连接监听的端口。可选。默认值: 命令行中指定的端口。host
<字符串> 检查器连接监听的主机。可选。默认值: 命令行中指定的主机。wait
<布尔值> 阻塞直到客户端连接。可选。默认值:false
。- 返回值: <Disposable> 一个调用
inspector.close()
的 Disposable 对象。
在主机和端口上激活检查器。等同于 node --inspect=[[host:]port]
,但可以在 Node.js 启动后以编程方式执行。
如果 wait
为 true
,则会阻塞直到客户端连接到检查器端口并且流控制已传递到调试器客户端。
有关 host
参数的使用,请参阅安全警告。
inspector.url()
返回活动调试器的 URL,如果没有则返回 undefined
。
$ node --inspect -p 'inspector.url()'
Debugger listening on ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34
For help, see: https://nodejs.org/en/docs/inspector
ws://127.0.0.1:9229/166e272e-7a30-4d09-97ce-f1c012b43c34
$ node --inspect=localhost:3000 -p 'inspector.url()'
Debugger listening on ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a
For help, see: https://nodejs.org/en/docs/inspector
ws://localhost:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a
$ node -p 'inspector.url()'
undefined
inspector.waitForDebugger()
新增于: v12.7.0
阻塞直到客户端(已存在或稍后连接)发送 Runtime.runIfWaitingForDebugger
命令。
如果没有活动的调试器,则会抛出异常。
与 DevTools 集成
node:inspector
模块提供了一个与支持 Chrome DevTools 协议的 DevTools 集成的 API。连接到正在运行的 Node.js 实例的 DevTools 前端可以捕获实例发出的协议事件并相应地显示它们,以方便调试。以下方法将协议事件广播到所有连接的前端。传递给方法的 params
可以是可选的,具体取决于协议。
// 将触发 `Network.requestWillBeSent` 事件。
inspector.Network.requestWillBeSent({
requestId: 'request-id-1',
timestamp: Date.now() / 1000,
wallTime: Date.now(),
request: {
url: 'https://nodejs.org/en',
method: 'GET',
},
})
inspector.Network.requestWillBeSent([params])
新增于:v22.6.0, v20.18.0
params
<对象>
此功能仅在启用 --experimental-network-inspection
标志时可用。
将 Network.requestWillBeSent
事件广播到已连接的前端。此事件表示应用程序即将发送 HTTP 请求。
inspector.Network.responseReceived([params])
新增于:v22.6.0, v20.18.0
params
<Object>
此功能仅在启用 --experimental-network-inspection
标志时可用。
将 Network.responseReceived
事件广播到已连接的前端。此事件表示 HTTP 响应可用。
inspector.Network.loadingFinished([params])
新增于:v22.6.0, v20.18.0
params
<Object>
此功能仅在启用 --experimental-network-inspection
标志时可用。
将 Network.loadingFinished
事件广播到已连接的前端。此事件表示 HTTP 请求已完成加载。
inspector.Network.loadingFailed([params])
新增于:v22.7.0, v20.18.0
params
<对象>
此功能仅在启用 --experimental-network-inspection
标志时可用。
将 Network.loadingFailed
事件广播到已连接的前端。此事件指示 HTTP 请求加载失败。
断点支持
Chrome DevTools 协议 Debugger
域 允许 inspector.Session
附加到程序并设置断点以单步执行代码。
但是,应避免使用由 session.connect()
连接的同线程 inspector.Session
设置断点,因为正在附加和暂停的程序正是调试器本身。相反,请尝试通过 session.connectToMainThread()
连接到主线程并在工作线程中设置断点,或者通过 WebSocket 连接使用 Debugger 程序进行连接。