Отчёт о диагностике
Выдает 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",
"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",
"loopIdleTimeSeconds": 22644.8
}
],
"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-v14.x/docs/api/report.html