Отчет о диагностике
Создает JSON-отчет о диагностике, записанный в файл.
Отчет предназначен для использования в разработке, тестировании и производстве для захвата и сохранения информации для определения проблем. Он включает трассировки стека JavaScript и нативного кода, статистику кучи, информацию о платформе, использование ресурсов и т. д. При включенном параметре отчета отчеты о диагностике могут генерироваться при необработанных исключениях, фатальных ошибках и пользовательских сигналах, помимо вызова через API.
Ниже приведен пример полного отчета, сгенерированного при необработанном исключении, для справки.
{
"header": {
"reportVersion": 3,
"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
}
],
"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"
]
} copy Использование
node --report-uncaught-exception --report-on-signal \ --report-on-fatalerror app.js copy
-
--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из отчета о диагностике. По умолчанию это не установлено, и сетевые интерфейсы включаются.
Отчет также можно вызвать через вызов API из приложения JavaScript:
process.report.writeReport(); copy
Эта функция принимает необязательный дополнительный аргумент filename, который является именем файла, в который записывается отчет.
process.report.writeReport('./foo.json'); copy Эта функция принимает необязательный дополнительный аргумент err, который является объектом Error, который будет использоваться в качестве контекста для стека JavaScript, напечатанного в отчете. При использовании отчета для обработки ошибок в обработчике обратного вызова или исключения это позволяет отчёту включать местоположение первоначальной ошибки, а также место, где она была обработана.
try {
process.chdir('/non-existent-path');
} catch (err) {
process.report.writeReport(err);
}
// Any other code copy Если в writeReport() переданы и имя файла, и объект ошибки, объект ошибки должен быть вторым параметром.
try {
process.chdir('/non-existent-path');
} catch (err) {
process.report.writeReport(filename, err);
}
// Any other code copy Содержимое отчета о диагностике можно вернуть как объект 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)); copy
Эта функция принимает необязательный дополнительный аргумент err, который является объектом Error, который будет использоваться в качестве контекста для стека JavaScript, напечатанного в отчете.
const report = process.report.getReport(new Error('custom error'));
console.log(typeof report === 'object'); // true copy Версии 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 > copy
При записи отчета в stderr выводятся сообщения начала и окончания, а имя файла отчета возвращается вызывающей стороне. По умолчанию имя файла включает дату, время, PID и порядковый номер. Порядковый номер помогает сопоставить дамп отчета с состоянием среды выполнения, если он генерируется несколько раз для одного и того же процесса Node.js.
Отчет о диагностике имеет связанный с ним однозначный порядковый номер версии (report.header.reportVersion), уникально представляющий формат отчета. Номер версии увеличивается, когда добавляется или удаляется новый ключ, или тип данных значения изменяется. Определения версий отчета согласованы во всех выпусках LTS.
Настройка
Дополнительная конфигурация среды выполнения для генерации отчетов доступна через следующие свойства 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; copy
Конфигурация при инициализации модуля также доступна через переменные среды:
NODE_OPTIONS="--report-uncaught-exception \ --report-on-fatalerror --report-on-signal \ --report-signal=SIGUSR2 --report-filename=./report.json \ --report-directory=/home/nodeuser" copy
Подробная документация по 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/api/report.html