Диагностический отчет
Создает диагностическую сводку в формате JSON и записывает ее в файл.
Отчет предназначен для использования при разработке, тестировании и в рабочей среде, чтобы собирать и сохранять информацию для выявления причин проблем. Он включает трассировки стека JavaScript и нативного кода, статистику кучи, сведения о платформе, использовании ресурсов и т. д. Если параметр отчета включен, диагностические отчеты можно создавать при необработанных исключениях, критических ошибках и пользовательских сигналах, а также программно с помощью вызовов API.
Ниже для справки приведен полный пример отчета, созданного при неперехваченном исключении.
{
"header": {
"reportVersion": 4,
"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
},
{
"type": "tcp",
"is_active": true,
"is_referenced": true,
"address": "0x000055e70fcd68c8",
"localEndpoint": {
"host": "ip6-localhost",
"ip6": "::1",
"port": 52266
},
"remoteEndpoint": {
"host": "ip6-localhost",
"ip6": "::1",
"port": 38573
},
"sendBufferSize": 2626560,
"recvBufferSize": 131072,
"fd": 25,
"writeQueueSize": 0,
"readable": false,
"writable": false
}
],
"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и отключает обратные DNS-запросы вlibuv.*.(remote|local)Endpoint.hostдиагностического отчета. По умолчанию этот параметр не задан, и сетевые интерфейсы включаются в отчет.
Создать отчет также можно вызовом 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; раздела со сведениями об объектах handle libuv; а также раздела со сведениями об операционной системе и платформе, в котором показаны использование ЦП и памяти и системные ограничения. Пример отчета можно создать с помощью REPL Node.js:
$ 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/dist/latest-v20.x/docs/api/report.html