Spec-Zone.ru › Node.js

Отчет о диагностике

Устойчивость: 2 - Стабильно
История
Версия Изменения
v22.0.0

Добавлен параметр --report-exclude-network для исключения сетевых операций, которые могут замедлить генерацию отчета в некоторых случаях.

Создает 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.

Взаимодействие с рабочими потоками

История
Версия Изменения
v13.9.0, v12.16.2

Рабочие потоки теперь включаются в отчет.

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API