Отчёт о диагностике
Предоставляет JSON-отчёт о диагностике, записанный в файл.
Отчёт предназначен для использования в разработке, тестировании и производстве, для сбора и сохранения информации для определения проблем. Он включает в себя трассировки стека JavaScript и нативного кода, статистику кучи, информацию о платформе, использование ресурсов и т. д. При включенном варианте отчёта, отчёты о диагностике могут быть инициированы при возникновении необработанных исключений, критических ошибок и пользовательских сигналах, помимо инициирования посредством API-вызовов.
Ниже приведен пример полного отчёта, сгенерированного при возникновении необработанного исключения, для справки.
{
"header": {
"reportVersion": 1,
"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",
"http_parser": "2.8.0",
"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": 6127616,
"totalCommittedMemory": 4357352,
"usedMemory": 3221136,
"availableMemory": 1521370240,
"memoryLimit": 1526909922,
"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": {
"userCpuSeconds": 0.069595,
"kernelCpuSeconds": 0.019163,
"cpuConsumptionPercent": 0.000000,
"maxRss": 18079744,
"pageFaults": {
"IORequired": 0,
"IONotRequired": 4610
},
"fsActivity": {
"reads": 0,
"writes": 0
}
},
"uvthreadResourceUsage": {
"userCpuSeconds": 0.068457,
"kernelCpuSeconds": 0.019127,
"cpuConsumptionPercent": 0.000000,
"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"
}
],
"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_kbytes": {
"soft": "unlimited",
"hard": "unlimited"
},
"file_size_blocks": {
"soft": "unlimited",
"hard": "unlimited"
},
"max_locked_memory_bytes": {
"soft": "unlimited",
"hard": 65536
},
"max_memory_size_kbytes": {
"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_kbytes": {
"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.
Отчёт также можно запустить с помощью вызова API из приложения JavaScript:
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 информацию о обработчиках, и раздела информации о платформе ОС, показывающего использование ЦП и памяти, и системные ограничения. Пример отчёта можно запустить с помощью 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.
Настройка
Дополнительная настройка среды выполнения генерации отчётов доступна через следующие свойства 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.
// 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';
Настройка при инициализации модуля также доступна через переменные среды:
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 documentation.
Взаимодействие с рабочими процессами
Worker потоки могут создавать отчёты таким же образом, как и основной поток.
Отчёты будут содержать информацию обо всех рабочих процессах, являющихся дочерними по отношению к текущему потоку, как часть раздела workers, при этом каждый рабочий процесс создаст отчёт в стандартном формате отчёта.
Поток, генерирующий отчёт, будет ждать завершения отчётов из потоков рабочих процессов. Однако задержка обычно будет низкой, поскольку как выполнение JavaScript, так и цикл событий прерываются для генерации отчёта.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v12.x/docs/api/report.html