Inspector#

安定性: 2 - Stable

ソースコード: 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#

安定性: 1 - Experimental

クラス: inspector.Session#

inspector.Session は、V8 インスペクタのバックエンドにメッセージをディスパッチし、メッセージの応答と通知を受信するために使用されます。

new inspector.Session()#

inspector.Session クラスの新しいインスタンスを作成します。インスペクタバックエンドにメッセージをディスパッチできるようになる前に、インスペクタセッションを session.connect() を通じて接続する必要があります。

Session を使用する場合、手動で Runtime.DiscardConsoleEntries コマンドを実行しない限り、コンソール API によって出力されたオブジェクトは解放されません。

イベント: 'inspectorNotification'#
  • 型: <Object> 通知メッセージオブジェクト

V8 インスペクタから何らかの通知を受信したときに発生します。

session.on('inspectorNotification', (message) => console.log(message.method));
// Debugger.paused
// Debugger.resumed 

注意: 同一スレッドセッションでのブレークポイントは推奨されません。ブレークポイントのサポートを参照してください。

特定メソッドの通知のみを購読することも可能です。

イベント: <inspector-protocol-method>#
  • 型: <Object> 通知メッセージオブジェクト

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()#

セッションをインスペクタのバックエンドに接続します。

session.connectToMainThread()#

セッションをメインスレッドのインスペクタバックエンドに接続します。この API がワーカースレッドで呼び出されなかった場合、例外がスローされます。

session.disconnect()#

セッションを直ちに閉じます。保留中のメッセージコールバックはすべてエラーで呼び出されます。再度メッセージを送信できるようにするには、session.connect() を呼び出す必要があります。再接続されたセッションは、有効化されたエージェントや設定されたブレークポイントなど、すべてのインスペクタの状態を失います。

session.post(method[, params])#

インスペクタのバックエンドにメッセージをポストします。

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);
}
// Output: { result: { type: 'number', value: 4, description: '4' } } 

V8 インスペクタプロトコルの最新バージョンは、Chrome DevTools Protocol Viewer で公開されています。

Node.js インスペクタは、V8 によって宣言されたすべての Chrome DevTools Protocol ドメインをサポートしています。Chrome DevTools Protocol ドメインは、アプリケーションの状態を検査し、ランタイムイベントをリッスンするために使用されるランタイムエージェントのいずれかと対話するためのインターフェースを提供します。

使用例#

デバッガの他に、様々な V8 プロファイラが DevTools プロトコルを介して利用可能です。

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');
// Invoke business logic under measurement here...

// some time later...
const { profile } = await session.post('Profiler.stop');

// Write profile to disk, upload, etc.
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); 

Callback API#

クラス: inspector.Session#

inspector.Session は、V8 インスペクタのバックエンドにメッセージをディスパッチし、メッセージの応答と通知を受信するために使用されます。

new inspector.Session()#

inspector.Session クラスの新しいインスタンスを作成します。インスペクタバックエンドにメッセージをディスパッチできるようになる前に、インスペクタセッションを session.connect() を通じて接続する必要があります。

Session を使用する場合、手動で Runtime.DiscardConsoleEntries コマンドを実行しない限り、コンソール API によって出力されたオブジェクトは解放されません。

イベント: 'inspectorNotification'#
  • 型: <Object> 通知メッセージオブジェクト

V8 インスペクタから何らかの通知を受信したときに発生します。

session.on('inspectorNotification', (message) => console.log(message.method));
// Debugger.paused
// Debugger.resumed 

注意: 同一スレッドセッションでのブレークポイントは推奨されません。ブレークポイントのサポートを参照してください。

特定メソッドの通知のみを購読することも可能です。

イベント: <inspector-protocol-method>;#
  • 型: <Object> 通知メッセージオブジェクト

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()#

セッションをインスペクタのバックエンドに接続します。

session.connectToMainThread()#

セッションをメインスレッドのインスペクタバックエンドに接続します。この API がワーカースレッドで呼び出されなかった場合、例外がスローされます。

session.disconnect()#

セッションを直ちに閉じます。保留中のメッセージコールバックはすべてエラーで呼び出されます。再度メッセージを送信できるようにするには、session.connect() を呼び出す必要があります。再接続されたセッションは、有効化されたエージェントや設定されたブレークポイントなど、すべてのインスペクタの状態を失います。

session.post(method[, params][, callback])#

インスペクタのバックエンドにメッセージをポストします。応答が受信されると callback が通知されます。callback は、エラーとメッセージ固有の結果という2つのオプショナルな引数を受け入れる関数です。

session.post('Runtime.evaluate', { expression: '2 + 2' },
             (error, { result }) => console.log(result));
// Output: { type: 'number', value: 4, description: '4' } 

V8 インスペクタプロトコルの最新バージョンは、Chrome DevTools Protocol Viewer で公開されています。

Node.js インスペクタは、V8 によって宣言されたすべての Chrome DevTools Protocol ドメインをサポートしています。Chrome DevTools Protocol ドメインは、アプリケーションの状態を検査し、ランタイムイベントをリッスンするために使用されるランタイムエージェントのいずれかと対話するためのインターフェースを提供します。

V8 に HeapProfiler.takeHeapSnapshot または HeapProfiler.stopTrackingHeapObjects コマンドを送信する場合、reportProgresstrue に設定することはできません。

使用例#

デバッガの他に、様々な V8 プロファイラが DevTools プロトコルを介して利用可能です。

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', () => {
    // Invoke business logic under measurement here...

    // some time later...
    session.post('Profiler.stop', (err, { profile }) => {
      // Write profile to disk, upload, etc.
      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()#

残りのすべての接続を閉じようと試み、すべてが閉じるまでイベントループをブロックします。すべての接続が閉じられると、インスペクタを非アクティブ化します。

inspector.console#

  • 型: <Object> リモートのインスペクタコンソールにメッセージを送信するためのオブジェクト。
require('node:inspector').console.log('a message'); 

インスペクタコンソールは、Node.js コンソールと API のパリティを持っていません。

inspector.open([port[, host[, wait]]])#

  • port <number> インスペクタ接続をリッスンするポート。オプショナル。デフォルト: CLI で指定されたもの。
  • host <string> インスペクタ接続をリッスンするホスト。オプショナル。デフォルト: CLI で指定されたもの。
  • wait <boolean> クライアントが接続するまでブロックします。オプショナル。デフォルト: false
  • 戻り値: <Disposable> inspector.close() を呼び出す Disposable。

ホストとポートでインスペクタを有効にします。node --inspect=[[host:]port] と同等ですが、Node が起動した後にプログラム的に実行できます。

waittrue の場合、クライアントがインスペクトポートに接続し、フロー制御がデバッガクライアントに渡されるまでブロックします。

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://node.dokyumento.jp/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://:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a
For help, see: https://node.dokyumento.jp/en/docs/inspector
ws://:3000/51cf8d0e-3c36-4c59-8efd-54519839e56a

$ node -p 'inspector.url()'
undefined 

inspector.waitForDebugger()#

クライアント(既存または後で接続されたもの)が Runtime.runIfWaitingForDebugger コマンドを送信するまでブロックします。

アクティブなインスペクタがない場合、例外がスローされます。

DevTools との連携#

安定性: 1.1 - Active development

node:inspector モジュールは、Chrome DevTools Protocol をサポートする devtools と連携するための API を提供します。実行中の Node.js インスタンスに接続された DevTools フロントエンドは、インスタンスから発行されたプロトコルイベントをキャプチャし、デバッグを容易にするためにそれに応じて表示できます。以下のメソッドは、接続されているすべてのフロントエンドにプロトコルイベントをブロードキャストします。メソッドに渡される params は、プロトコルに応じてオプショナルになる場合があります。

// The `Network.requestWillBeSent` event will be fired.
inspector.Network.requestWillBeSent({
  requestId: 'request-id-1',
  timestamp: Date.now() / 1000,
  wallTime: Date.now(),
  request: {
    url: 'https://node.dokyumento.jp/en',
    method: 'GET',
  },
}); 

inspector.Network.dataReceived([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.dataReceived イベントを接続されたフロントエンドにブロードキャストするか、指定されたリクエストに対して Network.streamResourceContent コマンドがまだ呼び出されていない場合はデータをバッファリングします。

また、レスポンスデータを取得するために Network.getResponseBody コマンドを有効にします。

inspector.Network.dataSent([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

リクエストデータを取得するために Network.getRequestPostData コマンドを有効にします。

inspector.Network.requestWillBeSent([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.requestWillBeSent イベントを接続されたフロントエンドにブロードキャストします。このイベントは、アプリケーションが HTTP リクエストを送信しようとしていることを示します。

inspector.Network.responseReceived([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.responseReceived イベントを接続されたフロントエンドにブロードキャストします。このイベントは、HTTP レスポンスが利用可能であることを示します。

inspector.Network.loadingFinished([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.loadingFinished イベントを接続されたフロントエンドにブロードキャストします。このイベントは、HTTP リクエストの読み込みが完了したことを示します。

inspector.Network.loadingFailed([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.loadingFailed イベントを接続されたフロントエンドにブロードキャストします。このイベントは、HTTP リクエストの読み込みに失敗したことを示します。

inspector.Network.webSocketCreated([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.webSocketCreated イベントを接続されたフロントエンドにブロードキャストします。このイベントは、WebSocket 接続が開始されたことを示します。

inspector.Network.webSocketHandshakeResponseReceived([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.webSocketHandshakeResponseReceived イベントを接続されたフロントエンドにブロードキャストします。このイベントは、WebSocket のハンドシェイク応答が受信されたことを示します。

inspector.Network.webSocketClosed([params])#

この機能は --experimental-network-inspection フラグが有効な場合のみ利用可能です。

Network.webSocketClosed イベントを接続されたフロントエンドにブロードキャストします。このイベントは、WebSocket 接続が閉じられたことを示します。

inspector.NetworkResources.put#

安定性: 1.1 - Active Development

この機能は --experimental-inspector-network-resource フラグが有効な場合のみ利用可能です。

inspector.NetworkResources.put メソッドは、Chrome DevTools Protocol (CDP) を介して発行された loadNetworkResource リクエストに対するレスポンスを提供するために使用されます。これは通常、ソースマップが URL で指定され、Chrome などの DevTools フロントエンドがソースマップを取得するためにリソースを要求したときにトリガーされます。

このメソッドにより、開発者はそのような CDP リクエストに応答して提供されるリソースコンテンツを事前に定義できます。

const inspector = require('node:inspector');
// By preemptively calling put to register the resource, a source map can be resolved when
// a loadNetworkResource request is made from the frontend.
async function setNetworkResources() {
  const mapUrl = 'https://:3000/dist/app.js.map';
  const tsUrl = 'https://:3000/src/app.ts';
  const distAppJsMap = await fetch(mapUrl).then((res) => res.text());
  const srcAppTs = await fetch(tsUrl).then((res) => res.text());
  inspector.NetworkResources.put(mapUrl, distAppJsMap);
  inspector.NetworkResources.put(tsUrl, srcAppTs);
};
setNetworkResources().then(() => {
  require('./dist/app');
}); 

詳細については、公式の CDP ドキュメントを参照してください: Network.loadNetworkResource

ブレークポイントのサポート#

Chrome DevTools Protocol の Debugger ドメインは、inspector.Session がプログラムにアタッチし、コードをステップ実行するためのブレークポイントを設定することを可能にします。

しかし、session.connect() によって接続された同一スレッドの inspector.Session でブレークポイントを設定することは避けるべきです。なぜなら、アタッチされて一時停止されるプログラムがまさにデバッガ自身だからです。代わりに、ワーカースレッドで session.connectToMainThread() を使ってメインスレッドに接続してブレークポイントを設定するか、WebSocket 接続を介して Debugger プログラムで接続してみてください。