Skip to content

Relatório de diagnóstico

[Estável: 2 - Estável]

Estável: 2 Estabilidade: 2 - Estável

[Histórico]

VersãoAlterações
v23.3.0Adicionada a opção --report-exclude-env para excluir variáveis de ambiente da geração do relatório.
v22.0.0, v20.13.0Adicionada a opção --report-exclude-network para excluir operações de rede que podem diminuir a velocidade da geração de relatórios em alguns casos.

Fornece um resumo de diagnóstico em formato JSON, gravado em um arquivo.

O relatório destina-se ao uso em desenvolvimento, teste e produção, para capturar e preservar informações para a determinação de problemas. Ele inclui rastros de pilha JavaScript e nativos, estatísticas de heap, informações da plataforma, uso de recursos etc. Com a opção de relatório ativada, os relatórios de diagnóstico podem ser acionados em exceções não tratadas, erros fatais e sinais do usuário, além de acionar programaticamente por meio de chamadas de API.

Um exemplo completo de relatório gerado em uma exceção não capturada é fornecido abaixo como referência.

json
{
  "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"
  ]
}

Uso

bash
node --report-uncaught-exception --report-on-signal \
--report-on-fatalerror app.js
  • --report-uncaught-exception Habilita a geração de relatórios sobre exceções não capturadas. Útil ao inspecionar a pilha JavaScript em conjunto com a pilha nativa e outros dados do ambiente de execução.
  • --report-on-signal Habilita a geração de relatórios ao receber o sinal especificado (ou predefinido) para o processo Node.js em execução. (Veja abaixo como modificar o sinal que aciona o relatório.) O sinal padrão é SIGUSR2. Útil quando um relatório precisa ser acionado de outro programa. Monitores de aplicativos podem aproveitar esse recurso para coletar relatórios em intervalos regulares e plotar um conjunto rico de dados internos de tempo de execução em suas visualizações.

A geração de relatórios baseada em sinal não é suportada no Windows.

Em circunstâncias normais, não há necessidade de modificar o sinal de acionamento do relatório. No entanto, se SIGUSR2 já estiver sendo usado para outros fins, essa sinalização ajuda a alterar o sinal para a geração de relatórios e preservar o significado original de SIGUSR2 para esses fins.

  • --report-on-fatalerror Habilita o acionamento do relatório em erros fatais (erros internos na execução do Node.js, como falta de memória) que levam ao encerramento do aplicativo. Útil para inspecionar vários elementos de dados de diagnóstico, como heap, pilha, estado do loop de eventos, consumo de recursos etc., para entender o erro fatal.
  • --report-compact Escreve relatórios em um formato compacto, JSON de uma única linha, mais facilmente consumível por sistemas de processamento de log do que o formato multi-linha padrão projetado para consumo humano.
  • --report-directory Local onde o relatório será gerado.
  • --report-filename Nome do arquivo para o qual o relatório será escrito.
  • --report-signal Define ou redefina o sinal para geração de relatório (não suportado no Windows). O sinal padrão é SIGUSR2.
  • --report-exclude-network Exclui header.networkInterfaces e desativa as consultas de DNS reverso em libuv.*.(remote|local)Endpoint.host do relatório de diagnóstico. Por padrão, isso não está definido e as interfaces de rede estão incluídas.
  • --report-exclude-env Exclui environmentVariables do relatório de diagnóstico. Por padrão, isso não está definido e as variáveis de ambiente estão incluídas.

Um relatório também pode ser acionado por meio de uma chamada de API de um aplicativo JavaScript:

js
process.report.writeReport()

Esta função recebe um argumento adicional opcional filename, que é o nome de um arquivo no qual o relatório será escrito.

js
process.report.writeReport('./foo.json')

Esta função recebe um argumento adicional opcional err, que é um objeto Error que será usado como contexto para a pilha JavaScript impressa no relatório. Ao usar o relatório para lidar com erros em um retorno de chamada ou um manipulador de exceção, isso permite que o relatório inclua a localização do erro original, bem como onde ele foi tratado.

js
try {
  process.chdir('/non-existent-path')
} catch (err) {
  process.report.writeReport(err)
}
// Qualquer outro código

Se ambos os objetos filename e error forem passados para writeReport(), o objeto error deve ser o segundo parâmetro.

js
try {
  process.chdir('/non-existent-path')
} catch (err) {
  process.report.writeReport(filename, err)
}
// Qualquer outro código

O conteúdo do relatório de diagnóstico pode ser retornado como um objeto JavaScript por meio de uma chamada de API de um aplicativo JavaScript:

js
const report = process.report.getReport()
console.log(typeof report === 'object') // true

// Similar à saída process.report.writeReport()
console.log(JSON.stringify(report, null, 2))

Esta função recebe um argumento adicional opcional err, que é um objeto Error que será usado como contexto para a pilha JavaScript impressa no relatório.

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

As versões da API são úteis ao inspecionar o estado de tempo de execução de dentro do aplicativo, na expectativa de autoajustar o consumo de recursos, balanceamento de carga, monitoramento etc.

O conteúdo do relatório consiste em uma seção de cabeçalho contendo o tipo de evento, data, hora, PID e versão do Node.js, seções contendo rastreios de pilha JavaScript e nativos, uma seção contendo informações de heap V8, uma seção contendo informações de manipulação libuv e uma seção de informações da plataforma do SO mostrando o uso da CPU e memória e limites do sistema. Um exemplo de relatório pode ser acionado usando o Node.js REPL:

bash
$ node
> process.report.writeReport();
Writing Node.js report to file: report.20181126.091102.8480.0.001.json
Node.js report completed
>

Quando um relatório é escrito, mensagens de início e fim são enviadas para stderr e o nome do arquivo do relatório é retornado para o chamador. O nome do arquivo padrão inclui a data, hora, PID e um número de sequência. O número de sequência ajuda a associar o despejo do relatório ao estado de tempo de execução se gerado várias vezes para o mesmo processo Node.js.

Versão do Relatório

O relatório de diagnóstico possui um número de versão de um único dígito associado (report.header.reportVersion), representando exclusivamente o formato do relatório. O número da versão é incrementado quando uma nova chave é adicionada ou removida, ou quando o tipo de dados de um valor é alterado. As definições da versão do relatório são consistentes entre as versões LTS.

Histórico de versões

Versão 5

[Histórico]

VersãoAlterações
v23.5.0Corrigidos erros de digitação nas unidades de limite de memória.

Substitua as chaves data_seg_size_kbytes, max_memory_size_kbytes e virtual_memory_kbytes por data_seg_size_bytes, max_memory_size_bytes e virtual_memory_bytes, respectivamente, na seção userLimits, pois esses valores são fornecidos em bytes.

json
{
  "userLimits": {
    // Ignorar algumas chaves ...
    "data_seg_size_bytes": {
      // substituindo data_seg_size_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    },
    // ...
    "max_memory_size_bytes": {
      // substituindo max_memory_size_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    },
    // ...
    "virtual_memory_bytes": {
      // substituindo virtual_memory_kbytes
      "soft": "unlimited",
      "hard": "unlimited"
    }
  }
}

Versão 4

[Histórico]

VersãoAlterações
v23.3.0Adicionada a opção --report-exclude-env para excluir variáveis de ambiente da geração do relatório.

Os novos campos ipv4 e ipv6 foram adicionados aos endpoints de manipulação libuv tcp e udp. Exemplos:

json
{
  "libuv": [
    {
      "type": "tcp",
      "is_active": true,
      "is_referenced": true,
      "address": "0x000055e70fcb85d8",
      "localEndpoint": {
        "host": "localhost",
        "ip4": "127.0.0.1", // nova chave
        "port": 48986
      },
      "remoteEndpoint": {
        "host": "localhost",
        "ip4": "127.0.0.1", // nova chave
        "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", // nova chave
        "port": 52266
      },
      "remoteEndpoint": {
        "host": "ip6-localhost",
        "ip6": "::1", // nova chave
        "port": 38573
      },
      "sendBufferSize": 2626560,
      "recvBufferSize": 131072,
      "fd": 25,
      "writeQueueSize": 0,
      "readable": false,
      "writable": false
    }
  ]
}

Versão 3

[Histórico]

VersãoAlterações
v19.1.0, v18.13.0Adicionadas mais informações de memória.

As seguintes chaves de uso de memória foram adicionadas à seção resourceUsage.

json
{
  "resourceUsage": {
    "rss": "35766272",
    "free_memory": "1598337024",
    "total_memory": "17179869184",
    "available_memory": "1598337024",
    "constrained_memory": "36624662528"
  }
}

Versão 2

[Histórico]

VersãoAlterações
v13.9.0, v12.16.2Os workers agora estão incluídos no relatório.

Adicionado suporte para Worker. Consulte a seção Interação com workers para mais detalhes.

Versão 1

Esta é a primeira versão do relatório de diagnóstico.

Configuração

Configuração adicional de tempo de execução da geração de relatórios está disponível por meio das seguintes propriedades de process.report:

reportOnFatalError aciona o relatório de diagnóstico em erros fatais quando true. O padrão é false.

reportOnSignal aciona o relatório de diagnóstico em sinal quando true. Isso não é suportado no Windows. O padrão é false.

reportOnUncaughtException aciona o relatório de diagnóstico em exceção não capturada quando true. O padrão é false.

signal especifica o identificador de sinal POSIX que será usado para interceptar gatilhos externos para a geração de relatórios. O padrão é 'SIGUSR2'.

filename especifica o nome do arquivo de saída no sistema de arquivos. Um significado especial é atribuído a stdout e stderr. O uso destes resultará na gravação do relatório nos fluxos padrão associados. Nos casos em que os fluxos padrão são usados, o valor em directory é ignorado. URLs não são suportadas. O padrão é um nome de arquivo composto que contém timestamp, PID e número de sequência.

directory especifica o diretório do sistema de arquivos onde o relatório será escrito. URLs não são suportadas. O padrão é o diretório de trabalho atual do processo Node.js.

excludeNetwork exclui header.networkInterfaces do relatório de diagnóstico.

js
// Acionar relatório somente em exceções não capturadas.
process.report.reportOnFatalError = false
process.report.reportOnSignal = false
process.report.reportOnUncaughtException = true

// Acionar relatório para erros internos e sinal externo.
process.report.reportOnFatalError = true
process.report.reportOnSignal = true
process.report.reportOnUncaughtException = false

// Alterar o sinal padrão para 'SIGQUIT' e habilitá-lo.
process.report.reportOnFatalError = false
process.report.reportOnUncaughtException = false
process.report.reportOnSignal = true
process.report.signal = 'SIGQUIT'

// Desabilitar relatórios de interfaces de rede
process.report.excludeNetwork = true

A configuração na inicialização do módulo também está disponível por meio de variáveis de ambiente:

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

Documentação específica da API pode ser encontrada na seção documentação da API do processo.

Interação com workers

[Histórico]

VersãoAlterações
v13.9.0, v12.16.2Workers agora são incluídos no relatório.

As threads Worker podem criar relatórios da mesma forma que a thread principal.

Os relatórios incluirão informações sobre quaisquer Workers que sejam filhos da thread atual como parte da seção workers, com cada Worker gerando um relatório no formato de relatório padrão.

A thread que está gerando o relatório aguardará o término dos relatórios das threads Worker. No entanto, a latência para isso geralmente será baixa, pois tanto a execução de JavaScript quanto o loop de eventos são interrompidos para gerar o relatório.