Spec-Zone.ru › Node.js

Диагностический отчет

История
Версия Изменения
v23.3.0, v22.13.0

Добавлена опция --report-exclude-env для исключения переменных среды из отчета.

v22.0.0, v20.13.0

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

Стабильность: 2 — Стабильно

Создает диагностическую сводку в формате JSON и записывает ее в файл.

Отчет предназначен для разработки, тестирования и использования в рабочей среде, чтобы собирать и сохранять информацию, необходимую для выявления причин проблем. Он включает трассировки стека JavaScript и нативного кода, статистику кучи, сведения о платформе, использовании ресурсов и т. д. Если включена опция создания отчета, диагностические отчеты можно создавать при необработанных исключениях, критических ошибках и получении сигналов от пользователя, а также программно с помощью вызовов API.

Ниже для справки приведен полный пример отчета, созданного при необработанном исключении.

{
  "header": {
    "reportVersion": 5,
    "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
    }
  ],
  "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_bytes": {
      "soft": "unlimited",
      "hard": "unlimited"
    },
    "file_size_blocks": {
      "soft": "unlimited",
      "hard": "unlimited"
    },
    "max_locked_memory_bytes": {
      "soft": "unlimited",
      "hard": 65536
    },
    "max_memory_size_bytes": {
      "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_bytes": {
      "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"
  ]
}
jsoncopy

Использование

node --report-uncaught-exception --report-on-signal \
--report-on-fatalerror app.js
bashcopy
  • --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 диагностического отчета. По умолчанию этот параметр не задан, и сетевые интерфейсы включаются в отчет.

  • --report-exclude-env Исключает environmentVariables из диагностического отчета. По умолчанию этот параметр не задан, и переменные среды включаются в отчет.

Создать отчет также можно с помощью вызова API из приложения JavaScript:

process.report.writeReport();
jscopy

Эта функция принимает необязательный дополнительный аргумент filename — имя файла, в который записывается отчет.

process.report.writeReport('./foo.json');
jscopy

Эта функция принимает необязательный дополнительный аргумент err, представляющий собой объект Error, который будет использоваться как контекст для стека JavaScript, выводимого в отчете. Если отчет используется для обработки ошибок в обратном вызове или обработчике исключений, это позволяет включить в отчет местоположение исходной ошибки и место ее обработки.

try {
  process.chdir('/non-existent-path');
} catch (err) {
  process.report.writeReport(err);
}
// Any other code
jscopy

Если в writeReport() переданы и имя файла, и объект ошибки, объект ошибки должен быть вторым параметром.

try {
  process.chdir('/non-existent-path');
} catch (err) {
  process.report.writeReport(filename, err);
}
// Any other code
jscopy

Содержимое диагностического отчета можно вернуть в виде объекта 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));
jscopy

Эта функция принимает необязательный дополнительный аргумент err, представляющий собой объект Error, который будет использоваться как контекст для стека JavaScript, выводимого в отчете.

const report = process.report.getReport(new Error('custom error'));
console.log(typeof report === 'object'); // true
jscopy

Версии API полезны для проверки состояния среды выполнения внутри приложения, чтобы при необходимости автоматически корректировать потребление ресурсов, балансировать нагрузку, выполнять мониторинг и т. д.

Отчет состоит из заголовка, содержащего тип события, дату, время, PID и версию Node.js; разделов с трассировками стека JavaScript и нативного кода; раздела со сведениями о куче V8; раздела со сведениями о дескрипторах 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
>
consolecopy

При записи отчета в stderr выводятся сообщения о начале и завершении, а вызывающей стороне возвращается имя файла отчета. Имя файла по умолчанию включает дату, время, PID и порядковый номер. Порядковый номер помогает связать дамп отчета с состоянием среды выполнения, если для одного и того же процесса Node.js создано несколько отчетов.

Версия отчета

Диагностическому отчету присваивается однозначный номер версии (report.header.reportVersion), уникально идентифицирующий формат отчета. Номер версии увеличивается при добавлении или удалении ключа либо изменении типа данных значения. Определения версий отчета согласованы между выпусками LTS.

История версий

Версия 5
История
Версия Изменения
v23.5.0, v22.13.0

Исправлены опечатки в единицах измерения лимита памяти.

В разделе userLimits ключи data_seg_size_kbytes, max_memory_size_kbytes и virtual_memory_kbytes заменены соответственно на data_seg_size_bytes, max_memory_size_bytes и virtual_memory_bytes, поскольку эти значения указываются в байтах.

{
  "userLimits": {
    // Skip some keys ...
    "data_seg_size_bytes": { // replacing data_seg_size_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    },
    // ...
    "max_memory_size_bytes": { // replacing max_memory_size_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    },
    // ...
    "virtual_memory_bytes": { // replacing virtual_memory_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    }
  }
}
jsoncopy
Версия 4
История
Версия Изменения
v23.3.0, v22.13.0

Добавлена опция --report-exclude-env для исключения переменных среды из отчета.

В tcp и конечные точки дескрипторов libuv udp добавлены новые поля ipv4 и ipv6. Примеры:

{
  "libuv": [
    {
      "type": "tcp",
      "is_active": true,
      "is_referenced": true,
      "address": "0x000055e70fcb85d8",
      "localEndpoint": {
        "host": "localhost",
        "ip4": "127.0.0.1", // new key
        "port": 48986
      },
      "remoteEndpoint": {
        "host": "localhost",
        "ip4": "127.0.0.1", // new key
        "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", // new key
        "port": 52266
      },
      "remoteEndpoint": {
        "host": "ip6-localhost",
        "ip6": "::1", // new key
        "port": 38573
      },
      "sendBufferSize": 2626560,
      "recvBufferSize": 131072,
      "fd": 25,
      "writeQueueSize": 0,
      "readable": false,
      "writable": false
    }
  ]
}
jsoncopy
Версия 3
История
Версия Изменения
v19.1.0, v18.13.0

Добавлены дополнительные сведения о памяти.

В раздел resourceUsage добавлены следующие ключи с данными об использовании памяти.

{
  "resourceUsage": {
    "rss": "35766272",
    "free_memory": "1598337024",
    "total_memory": "17179869184",
    "available_memory": "1598337024",
    "constrained_memory": "36624662528"
  }
}
jsoncopy
Версия 2
История
Версия Изменения
v13.9.0, v12.16.2

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

Добавлена поддержка Worker. Подробности см. в разделе Взаимодействие с рабочими потоками.

Версия 1

Это первая версия диагностического отчета.

Конфигурация

Дополнительную конфигурацию создания отчетов во время выполнения можно задать с помощью следующих свойств объекта 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;
jscopy

Конфигурацию при инициализации модуля также можно задать с помощью переменных среды:

NODE_OPTIONS="--report-uncaught-exception \
  --report-on-fatalerror --report-on-signal \
  --report-signal=SIGUSR2  --report-filename=./report.json \
  --report-directory=/home/nodeuser"
bashcopy

Документацию по конкретному 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