Отчёт о диагностике
Предоставляет отчёт о диагностике в формате 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-v16.x/docs/api/report.html