Node.js v25.0.0 文件
- Node.js v25.0.0
- 目錄
-
索引
- 斷言測試
- 非同步上下文跟蹤
- 非同步鉤子
- 緩衝區
- C++ 外掛
- 使用 Node-API 的 C/C++ 外掛
- C++ 嵌入器 API
- 子程序
- 叢集
- 命令列選項
- 控制檯
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷通道
- DNS
- 域
- 環境變數
- 錯誤
- 事件
- 檔案系統
- 全域性物件
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:moduleAPI - 模組:包
- 模組:TypeScript
- 網路
- 作業系統
- 路徑
- 效能鉤子
- 許可權
- 程序
- Punycode
- 查詢字串
- 逐行讀取
- REPL
- 報告
- 單一可執行檔案應用
- SQLite
- 流
- 字串解碼器
- 測試執行器
- 定時器
- TLS/SSL
- 跟蹤事件
- TTY
- UDP/資料報
- URL
- 實用工具
- V8
- 虛擬機器
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- 其他版本
- 選項
診斷報告#
生成 JSON 格式的診斷摘要,並寫入檔案。
該報告旨在用於開發、測試和生產環境,以捕獲並保留用於問題排查的資訊。它包括 JavaScript 和原生堆疊跟蹤、堆統計資訊、平臺資訊、資源使用情況等。啟用報告選項後,除了透過 API 呼叫以程式設計方式觸發外,還可以在未處理的異常、致命錯誤和使用者訊號上觸發診斷報告。
下面提供了一個在未捕獲異常時生成的完整示例報告,以供參考。
{
"header": {
"reportVersion": 5,
"event": "exception",
"trigger": "Exception",
"filename": "report.20181221.005011.8974.0.001.json",
"dumpEventTime": "2018-12-21T00:50:11Z",
"dumpEventTimeStamp": "1545371411331",
"processId": 8974,
"cwd": "/home/nodeuser/project/node",
"commandLine": [
"/home/nodeuser/project/node/out/Release/node",
"--report-uncaught-exception",
"/home/nodeuser/project/node/test/report/test-exception.js",
"child"
],
"nodejsVersion": "v12.0.0-pre",
"glibcVersionRuntime": "2.17",
"glibcVersionCompiler": "2.17",
"wordSize": "64 bit",
"arch": "x64",
"platform": "linux",
"componentVersions": {
"node": "12.0.0-pre",
"v8": "7.1.302.28-node.5",
"uv": "1.24.1",
"zlib": "1.2.11",
"ares": "1.15.0",
"modules": "68",
"nghttp2": "1.34.0",
"napi": "3",
"llhttp": "1.0.1",
"openssl": "1.1.0j"
},
"release": {
"name": "node"
},
"osName": "Linux",
"osRelease": "3.10.0-862.el7.x86_64",
"osVersion": "#1 SMP Wed Mar 21 18:14:51 EDT 2018",
"osMachine": "x86_64",
"cpus": [
{
"model": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
"speed": 2700,
"user": 88902660,
"nice": 0,
"sys": 50902570,
"idle": 241732220,
"irq": 0
},
{
"model": "Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz",
"speed": 2700,
"user": 88902660,
"nice": 0,
"sys": 50902570,
"idle": 241732220,
"irq": 0
}
],
"networkInterfaces": [
{
"name": "en0",
"internal": false,
"mac": "13:10:de:ad:be:ef",
"address": "10.0.0.37",
"netmask": "255.255.255.0",
"family": "IPv4"
}
],
"host": "test_machine"
},
"javascriptStack": {
"message": "Error: *** test-exception.js: throwing uncaught Error",
"stack": [
"at myException (/home/nodeuser/project/node/test/report/test-exception.js:9:11)",
"at Object.<anonymous> (/home/nodeuser/project/node/test/report/test-exception.js:12:3)",
"at Module._compile (internal/modules/cjs/loader.js:718:30)",
"at Object.Module._extensions..js (internal/modules/cjs/loader.js:729:10)",
"at Module.load (internal/modules/cjs/loader.js:617:32)",
"at tryModuleLoad (internal/modules/cjs/loader.js:560:12)",
"at Function.Module._load (internal/modules/cjs/loader.js:552:3)",
"at Function.Module.runMain (internal/modules/cjs/loader.js:771:12)",
"at executeUserCode (internal/bootstrap/node.js:332:15)"
]
},
"nativeStack": [
{
"pc": "0x000055b57f07a9ef",
"symbol": "report::GetNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, v8::Local<v8::String>, std::ostream&) [./node]"
},
{
"pc": "0x000055b57f07cf03",
"symbol": "report::GetReport(v8::FunctionCallbackInfo<v8::Value> const&) [./node]"
},
{
"pc": "0x000055b57f1bccfd",
"symbol": " [./node]"
},
{
"pc": "0x000055b57f1be048",
"symbol": "v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [./node]"
},
{
"pc": "0x000055b57feeda0e",
"symbol": " [./node]"
}
],
"javascriptHeap": {
"totalMemory": 5660672,
"executableMemory": 524288,
"totalCommittedMemory": 5488640,
"availableMemory": 4341379928,
"totalGlobalHandlesMemory": 8192,
"usedGlobalHandlesMemory": 3136,
"usedMemory": 4816432,
"memoryLimit": 4345298944,
"mallocedMemory": 254128,
"externalMemory": 315644,
"peakMallocedMemory": 98752,
"nativeContextCount": 1,
"detachedContextCount": 0,
"doesZapGarbage": 0,
"heapSpaces": {
"read_only_space": {
"memorySize": 524288,
"committedMemory": 39208,
"capacity": 515584,
"used": 30504,
"available": 485080
},
"new_space": {
"memorySize": 2097152,
"committedMemory": 2019312,
"capacity": 1031168,
"used": 985496,
"available": 45672
},
"old_space": {
"memorySize": 2273280,
"committedMemory": 1769008,
"capacity": 1974640,
"used": 1725488,
"available": 249152
},
"code_space": {
"memorySize": 696320,
"committedMemory": 184896,
"capacity": 152128,
"used": 152128,
"available": 0
},
"map_space": {
"memorySize": 536576,
"committedMemory": 344928,
"capacity": 327520,
"used": 327520,
"available": 0
},
"large_object_space": {
"memorySize": 0,
"committedMemory": 0,
"capacity": 1520590336,
"used": 0,
"available": 1520590336
},
"new_large_object_space": {
"memorySize": 0,
"committedMemory": 0,
"capacity": 0,
"used": 0,
"available": 0
}
}
},
"resourceUsage": {
"rss": "35766272",
"free_memory": "1598337024",
"total_memory": "17179869184",
"available_memory": "1598337024",
"maxRss": "36624662528",
"constrained_memory": "36624662528",
"userCpuSeconds": 0.040072,
"kernelCpuSeconds": 0.016029,
"cpuConsumptionPercent": 5.6101,
"userCpuConsumptionPercent": 4.0072,
"kernelCpuConsumptionPercent": 1.6029,
"pageFaults": {
"IORequired": 0,
"IONotRequired": 4610
},
"fsActivity": {
"reads": 0,
"writes": 0
}
},
"uvthreadResourceUsage": {
"userCpuSeconds": 0.039843,
"kernelCpuSeconds": 0.015937,
"cpuConsumptionPercent": 5.578,
"userCpuConsumptionPercent": 3.9843,
"kernelCpuConsumptionPercent": 1.5937,
"fsActivity": {
"reads": 0,
"writes": 0
}
},
"libuv": [
{
"type": "async",
"is_active": true,
"is_referenced": false,
"address": "0x0000000102910900",
"details": ""
},
{
"type": "timer",
"is_active": false,
"is_referenced": false,
"address": "0x00007fff5fbfeab0",
"repeat": 0,
"firesInMsFromNow": 94403548320796,
"expired": true
},
{
"type": "check",
"is_active": true,
"is_referenced": false,
"address": "0x00007fff5fbfeb48"
},
{
"type": "idle",
"is_active": false,
"is_referenced": true,
"address": "0x00007fff5fbfebc0"
},
{
"type": "prepare",
"is_active": false,
"is_referenced": false,
"address": "0x00007fff5fbfec38"
},
{
"type": "check",
"is_active": false,
"is_referenced": false,
"address": "0x00007fff5fbfecb0"
},
{
"type": "async",
"is_active": true,
"is_referenced": false,
"address": "0x000000010188f2e0"
},
{
"type": "tty",
"is_active": false,
"is_referenced": true,
"address": "0x000055b581db0e18",
"width": 204,
"height": 55,
"fd": 17,
"writeQueueSize": 0,
"readable": true,
"writable": true
},
{
"type": "signal",
"is_active": true,
"is_referenced": false,
"address": "0x000055b581d80010",
"signum": 28,
"signal": "SIGWINCH"
},
{
"type": "tty",
"is_active": true,
"is_referenced": true,
"address": "0x000055b581df59f8",
"width": 204,
"height": 55,
"fd": 19,
"writeQueueSize": 0,
"readable": true,
"writable": true
},
{
"type": "loop",
"is_active": true,
"address": "0x000055fc7b2cb180",
"loopIdleTimeSeconds": 22644.8
},
{
"type": "tcp",
"is_active": true,
"is_referenced": true,
"address": "0x000055e70fcb85d8",
"localEndpoint": {
"host": "localhost",
"ip4": "127.0.0.1",
"port": 48986
},
"remoteEndpoint": {
"host": "localhost",
"ip4": "127.0.0.1",
"port": 38573
},
"sendBufferSize": 2626560,
"recvBufferSize": 131072,
"fd": 24,
"writeQueueSize": 0,
"readable": true,
"writable": true
}
],
"workers": [],
"environmentVariables": {
"REMOTEHOST": "REMOVED",
"MANPATH": "/opt/rh/devtoolset-3/root/usr/share/man:",
"XDG_SESSION_ID": "66126",
"HOSTNAME": "test_machine",
"HOST": "test_machine",
"TERM": "xterm-256color",
"SHELL": "/bin/csh",
"SSH_CLIENT": "REMOVED",
"PERL5LIB": "/opt/rh/devtoolset-3/root//usr/lib64/perl5/vendor_perl:/opt/rh/devtoolset-3/root/usr/lib/perl5:/opt/rh/devtoolset-3/root//usr/share/perl5/vendor_perl",
"OLDPWD": "/home/nodeuser/project/node/src",
"JAVACONFDIRS": "/opt/rh/devtoolset-3/root/etc/java:/etc/java",
"SSH_TTY": "/dev/pts/0",
"PCP_DIR": "/opt/rh/devtoolset-3/root",
"GROUP": "normaluser",
"USER": "nodeuser",
"LD_LIBRARY_PATH": "/opt/rh/devtoolset-3/root/usr/lib64:/opt/rh/devtoolset-3/root/usr/lib",
"HOSTTYPE": "x86_64-linux",
"XDG_CONFIG_DIRS": "/opt/rh/devtoolset-3/root/etc/xdg:/etc/xdg",
"MAIL": "/var/spool/mail/nodeuser",
"PATH": "/home/nodeuser/project/node:/opt/rh/devtoolset-3/root/usr/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin",
"PWD": "/home/nodeuser/project/node",
"LANG": "en_US.UTF-8",
"PS1": "\\u@\\h : \\[\\e[31m\\]\\w\\[\\e[m\\] > ",
"SHLVL": "2",
"HOME": "/home/nodeuser",
"OSTYPE": "linux",
"VENDOR": "unknown",
"PYTHONPATH": "/opt/rh/devtoolset-3/root/usr/lib64/python2.7/site-packages:/opt/rh/devtoolset-3/root/usr/lib/python2.7/site-packages",
"MACHTYPE": "x86_64",
"LOGNAME": "nodeuser",
"XDG_DATA_DIRS": "/opt/rh/devtoolset-3/root/usr/share:/usr/local/share:/usr/share",
"LESSOPEN": "||/usr/bin/lesspipe.sh %s",
"INFOPATH": "/opt/rh/devtoolset-3/root/usr/share/info",
"XDG_RUNTIME_DIR": "/run/user/50141",
"_": "./node"
},
"userLimits": {
"core_file_size_blocks": {
"soft": "",
"hard": "unlimited"
},
"data_seg_size_bytes": {
"soft": "unlimited",
"hard": "unlimited"
},
"file_size_blocks": {
"soft": "unlimited",
"hard": "unlimited"
},
"max_locked_memory_bytes": {
"soft": "unlimited",
"hard": 65536
},
"max_memory_size_bytes": {
"soft": "unlimited",
"hard": "unlimited"
},
"open_files": {
"soft": "unlimited",
"hard": 4096
},
"stack_size_bytes": {
"soft": "unlimited",
"hard": "unlimited"
},
"cpu_time_seconds": {
"soft": "unlimited",
"hard": "unlimited"
},
"max_user_processes": {
"soft": "unlimited",
"hard": 4127290
},
"virtual_memory_bytes": {
"soft": "unlimited",
"hard": "unlimited"
}
},
"sharedObjects": [
"/lib64/libdl.so.2",
"/lib64/librt.so.1",
"/lib64/libstdc++.so.6",
"/lib64/libm.so.6",
"/lib64/libgcc_s.so.1",
"/lib64/libpthread.so.0",
"/lib64/libc.so.6",
"/lib64/ld-linux-x86-64.so.2"
]
}
用法#
node --report-uncaught-exception --report-on-signal \
--report-on-fatalerror app.js
-
--report-uncaught-exception啟用在未捕獲異常時生成報告。在檢查 JavaScript 堆疊以及原生堆疊和其他執行時環境資料時很有用。 -
--report-on-signal啟用在正在執行的 Node.js 程序接收到指定(或預定義)訊號時生成報告。(關於如何修改觸發報告的訊號,請參見下文。)預設訊號為SIGUSR2。當需要從另一個程式觸發報告時很有用。應用程式監控器可以利用此功能定期收集報告,並將豐富的內部執行時資料繪製到其檢視中。
Windows 不支援基於訊號的報告生成。
在正常情況下,無需修改觸發報告的訊號。但是,如果 SIGUSR2 已被用於其他目的,則此標誌有助於更改用於報告生成的訊號,並保留 SIGUSR2 用於所述目的的原始含義。
-
--report-on-fatalerror啟用在導致應用程式終止的致命錯誤(Node.js 執行時內部的錯誤,例如記憶體不足)時觸發報告。有助於檢查各種診斷資料元素,如堆、堆疊、事件迴圈狀態、資源消耗等,以分析致命錯誤的原因。 -
--report-compact以緊湊格式(單行 JSON)寫入報告,比專為人類閱讀設計的預設多行格式更容易被日誌處理系統使用。 -
--report-directory生成報告的位置。 -
--report-filename寫入報告的檔名。 -
--report-signal設定或重置用於報告生成的訊號(在 Windows 上不支援)。預設訊號為SIGUSR2。 -
--report-exclude-network從診斷報告中排除header.networkInterfaces並停用libuv.*.(remote|local)Endpoint.host中的反向 DNS 查詢。預設情況下此選項未設定,網路介面會被包含在內。 -
--report-exclude-env從診斷報告中排除environmentVariables。預設情況下此選項未設定,環境變數會被包含在內。
也可以透過 JavaScript 應用程式的 API 呼叫來觸發報告。
process.report.writeReport();
此函式接受一個可選的附加引數 filename,它是報告寫入檔案的名稱。
process.report.writeReport('./foo.json');
此函式接受一個可選的附加引數 err,它是一個 Error 物件,將用作報告中列印的 JavaScript 堆疊的上下文。當使用報告處理回撥或異常處理程式中的錯誤時,這允許報告包含原始錯誤的位置以及處理它的位置。
try {
process.chdir('/non-existent-path');
} catch (err) {
process.report.writeReport(err);
}
// Any other code
如果同時將檔名和錯誤物件傳遞給 writeReport(),則錯誤物件必須是第二個引數。
try {
process.chdir('/non-existent-path');
} catch (err) {
process.report.writeReport(filename, err);
}
// Any other code
診斷報告的內容可以透過 JavaScript 應用程式的 API 呼叫以 JavaScript 物件的形式返回。
const report = process.report.getReport();
console.log(typeof report === 'object'); // true
// Similar to process.report.writeReport() output
console.log(JSON.stringify(report, null, 2));
此函式接受一個可選的附加引數 err,它是一個 Error 物件,將用作報告中列印的 JavaScript 堆疊的上下文。
const report = process.report.getReport(new Error('custom error'));
console.log(typeof report === 'object'); // true
API 版本在從應用程式內部檢查執行時狀態時很有用,以便進行資源消耗、負載均衡、監控等的自我調整。
報告的內容包括一個頭部部分,包含事件型別、日期、時間、PID 和 Node.js 版本;包含 JavaScript 和原生堆疊跟蹤的部分;包含 V8 堆資訊的部分;包含 libuv 控制代碼資訊的部分;以及顯示 CPU 和記憶體使用情況及系統限制的作業系統平臺資訊部分。可以使用 Node.js REPL 觸發一個示例報告。
$ node
> process.report.writeReport();
Writing Node.js report to file: report.20181126.091102.8480.0.001.json
Node.js report completed
>
當報告被寫入時,開始和結束訊息會輸出到 stderr,並且報告的檔名會返回給呼叫者。預設檔名包括日期、時間、PID 和一個序列號。如果為同一個 Node.js 程序多次生成報告,序列號有助於將報告轉儲與執行時狀態關聯起來。
報告版本#
診斷報告有一個關聯的單位數版本號(report.header.reportVersion),唯一地代表報告的格式。當新增或刪除新鍵,或值的資料型別發生變化時,版本號會增加。報告版本定義在 LTS 版本之間保持一致。
版本歷史#
版本 5#
在 userLimits 部分中,將鍵 data_seg_size_kbytes、max_memory_size_kbytes 和 virtual_memory_kbytes 分別替換為 data_seg_size_bytes、max_memory_size_bytes 和 virtual_memory_bytes,因為這些值是以位元組為單位給出的。
{
"userLimits": {
// Skip some keys ...
"data_seg_size_bytes": { // replacing data_seg_size_kbytes
"soft": "unlimited",
"hard": "unlimited"
},
// ...
"max_memory_size_bytes": { // replacing max_memory_size_kbytes
"soft": "unlimited",
"hard": "unlimited"
},
// ...
"virtual_memory_bytes": { // replacing virtual_memory_kbytes
"soft": "unlimited",
"hard": "unlimited"
}
}
}
版本 4#
向 tcp 和 udp libuv 控制代碼端點添加了新欄位 ipv4 和 ipv6。示例:
{
"libuv": [
{
"type": "tcp",
"is_active": true,
"is_referenced": true,
"address": "0x000055e70fcb85d8",
"localEndpoint": {
"host": "localhost",
"ip4": "127.0.0.1", // new key
"port": 48986
},
"remoteEndpoint": {
"host": "localhost",
"ip4": "127.0.0.1", // new key
"port": 38573
},
"sendBufferSize": 2626560,
"recvBufferSize": 131072,
"fd": 24,
"writeQueueSize": 0,
"readable": true,
"writable": true
},
{
"type": "tcp",
"is_active": true,
"is_referenced": true,
"address": "0x000055e70fcd68c8",
"localEndpoint": {
"host": "ip6-localhost",
"ip6": "::1", // new key
"port": 52266
},
"remoteEndpoint": {
"host": "ip6-localhost",
"ip6": "::1", // new key
"port": 38573
},
"sendBufferSize": 2626560,
"recvBufferSize": 131072,
"fd": 25,
"writeQueueSize": 0,
"readable": false,
"writable": false
}
]
}
版本 3#
以下記憶體使用鍵已新增到 resourceUsage 部分。
{
"resourceUsage": {
"rss": "35766272",
"free_memory": "1598337024",
"total_memory": "17179869184",
"available_memory": "1598337024",
"constrained_memory": "36624662528"
}
}
版本 1#
這是診斷報告的第一個版本。
配置#
報告生成的額外執行時配置可透過 process.report 的以下屬性獲得:
reportOnFatalError 當為 true 時,在致命錯誤時觸發診斷報告。預設為 false。
reportOnSignal 當為 true 時,在接收到訊號時觸發診斷報告。這在 Windows 上不受支援。預設為 false。
reportOnUncaughtException 當為 true 時,在未捕獲的異常時觸發診斷報告。預設為 false。
signal 指定將用於攔截外部觸發器以生成報告的 POSIX 訊號識別符號。預設為 'SIGUSR2'。
filename 指定檔案系統中輸出檔案的名稱。stdout 和 stderr 具有特殊含義。使用它們將導致報告被寫入到相應的標準流中。在使用標準流的情況下,directory 中的值將被忽略。不支援 URL。預設為一個包含時間戳、PID 和序列號的複合檔名。
directory 指定報告將被寫入的檔案系統目錄。不支援 URL。預設為 Node.js 程序的當前工作目錄。
excludeNetwork 從診斷報告中排除 header.networkInterfaces。
// Trigger report only on uncaught exceptions.
process.report.reportOnFatalError = false;
process.report.reportOnSignal = false;
process.report.reportOnUncaughtException = true;
// Trigger report for both internal errors as well as external signal.
process.report.reportOnFatalError = true;
process.report.reportOnSignal = true;
process.report.reportOnUncaughtException = false;
// Change the default signal to 'SIGQUIT' and enable it.
process.report.reportOnFatalError = false;
process.report.reportOnUncaughtException = false;
process.report.reportOnSignal = true;
process.report.signal = 'SIGQUIT';
// Disable network interfaces reporting
process.report.excludeNetwork = true;
模組初始化時的配置也可以透過環境變數進行:
NODE_OPTIONS="--report-uncaught-exception \
--report-on-fatalerror --report-on-signal \
--report-signal=SIGUSR2 --report-filename=./report.json \
--report-directory=/home/nodeuser"
具體的 API 文件可以在 process API 文件部分找到。
與工作執行緒的互動#
Worker 執行緒可以像主執行緒一樣建立報告。
報告將作為 workers 部分的一部分,包含有關當前執行緒的任何子工作執行緒的資訊,每個工作執行緒都會以標準報告格式生成一份報告。
正在生成報告的執行緒將等待工作執行緒的報告完成。然而,這方面的延遲通常很低,因為正在執行的 JavaScript 和事件迴圈都會被中斷以生成報告。