Registro de erros de rede (NEL, na sigla em inglês)

Introdução

A geração de registros de erros de rede (NEL, na sigla em inglês) é um mecanismo para coletar erros de rede do lado do cliente de uma origem.

Ela usa o cabeçalho de resposta HTTP NEL para informar ao navegador que precisa coletar erros de rede e, em seguida, se integra à API Reporting para informar os erros a um servidor.

Visão geral da API Reporting legada

Para usar a API Reporting legada, você precisará definir um cabeçalho de resposta HTTP Report-To. O valor é um objeto que descreve um grupo de endpoints para o navegador informar erros:

Report-To:
{
    "max_age": 10886400,
    "endpoints": [{
    "url": "https://analytics.provider.com/browser-errors"
    }]
}

Se o URL do endpoint estiver em uma origem diferente do site, ele será compatível com solicitações simuladas de CORS. (por exemplo, Access-Control-Allow-Origin: *; Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS; Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With).

No exemplo, enviar esse cabeçalho de resposta com sua página principal configura o navegador para informar avisos gerados pelo navegador ao endpoint https://analytics.provider.com/browser-errors por max_age segundos. É importante observar que todas as solicitações HTTP subsequentes feitas pela página (para imagens, scripts etc.) são ignoradas. A configuração é definida durante a resposta da página principal.

Explicação dos campos de cabeçalho

Cada configuração de endpoint contém um nome de group, um max_age e uma matriz de endpoints. Também é possível escolher se quer considerar subdomínios ao relatar erros usando o campo include_subdomains.

Field Tipo Descrição
group string Opcional. Se um nome group não for especificado, o endpoint receberá o nome "padrão".
max_age number Obrigatório. Um número inteiro não negativo que define o ciclo de vida do endpoint em segundos. Um valor de "0" fará com que o grupo de endpoints seja removido do cache de relatórios do user agent.
endpoints Matriz<Objeto> Obrigatório. Uma matriz de objetos JSON que especificam o URL real do seu coletor de relatórios.
include_subdomains boolean Opcional. Um booleano que ativa o grupo de endpoints para todos os subdomínios do host da origem atual. Se omitido ou algo diferente de "true", os subdomínios não serão informados ao endpoint.

O group é um nome exclusivo usado para associar uma string a um endpoint. Use esse nome em outros lugares que se integrem à API Reporting para se referir a um grupo de endpoints específico.

O campo max-age também é obrigatório e especifica por quanto tempo o navegador precisa usar o endpoint e informar erros a ele.

O campo endpoints é uma matriz que fornece recursos de failover e balanceamento de carga. Consulte a seção sobre Failover e balanceamento de carga. É importante observar que o navegador selecionará apenas um endpoint, mesmo que o grupo liste vários coletores em endpoints. Se você quiser enviar um relatório para vários servidores de uma só vez, seu back-end precisará encaminhar os relatórios.

Como o navegador envia relatórios?

O navegador agrupa relatórios periodicamente e os envia para os endpoints de relatórios configurados.

Para enviar relatórios, o navegador emite uma solicitação POST com Content-Type: application/reports+json e um corpo contendo a matriz de avisos/erros que foram capturados.

Quando o navegador envia relatórios?

Os relatórios são enviados fora de banda pelo app, ou seja, o navegador controla quando os relatórios são enviados aos seus servidores.

O navegador tenta entregar relatórios na fila no momento mais oportuno. Isso pode acontecer assim que eles estiverem prontos (para fornecer feedback oportuno ao desenvolvedor), mas o navegador também poderá atrasar a entrega se estiver ocupado processando trabalhos de prioridade mais alta ou se o usuário estiver em uma rede lenta e/ou congestionada no momento. O navegador também pode priorizar o envio de relatórios sobre uma origem específica primeiro, se o usuário for um visitante frequente.

Há pouca ou nenhuma preocupação de desempenho (por exemplo, contenção de rede com seu app) ao usar a API Reporting. Também não é possível controlar quando o navegador envia relatórios em fila.

Como configurar vários endpoints

Uma única resposta pode configurar vários endpoints de uma só vez enviando vários cabeçalhos Report-To:

Report-To: {
             "group": "default",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/browser-reports"
             }]
           }
Report-To: {
             "group": "network-errors-endpoint",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/network-errors"
             }]
           }

ou combinando-as em um único cabeçalho HTTP:

Report-To: {
             "group": "network-errors-endpoint",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/network-errors"
             }]
           },
           {
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/browser-errors"
             }]
           }

Depois que você envia o cabeçalho Report-To, o navegador armazena os endpoints em cache de acordo com os valores de max_age e envia todos os avisos/erros desagradáveis do console para os URLs.

Failover e balanceamento de carga

Na maioria das vezes, você configurará um coletor de URL por grupo. No entanto, como os relatórios podem gerar uma boa quantidade de tráfego, a especificação inclui recursos de failover e balanceamento de carga inspirados no registro SRV do DNS.

O navegador fará o possível para entregar um relatório a no máximo endpoint em um grupo. É possível atribuir um weight aos endpoints para distribuir a carga. Cada endpoint recebe uma fração específica do tráfego do relatório. Os endpoints também podem receber um priority para configurar coletores substitutos.

Os coletores substitutos só são testados quando há falha nos uploads dos coletores principais.

Exemplo: crie um coletor substituto em https://backup.com/reports:

Report-To: {
             "group": "endpoint-1",
             "max_age": 10886400,
             "endpoints": [
               {"url": "https://example.com/reports", "priority": 1},
               {"url": "https://backup.com/reports", "priority": 2}
             ]
           }

Como configurar o registro de erros de rede

Configuração

Para usar a NEL, configure o cabeçalho Report-To com um coletor que use um grupo nomeado:

Report-To: {
    ...
  }, {
    "group": "network-errors",
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://analytics.provider.com/networkerrors"
    }]
  }

Em seguida, envie o cabeçalho de resposta NEL para começar a coletar erros. Como a NEL é ativada para uma origem, você só precisa enviar o cabeçalho uma vez. Tanto NEL quanto Report-To serão aplicados a solicitações futuras para a mesma origem e continuarão coletando erros de acordo com o valor de max_age usado para configurar o coletor.

O valor do cabeçalho precisa ser um objeto JSON que contenha os campos max_age e report_to. Use o último para fazer referência ao nome do grupo do coletor de erros de rede:

GET /index.html HTTP/1.1
NEL: {"report_to": "network-errors", "max_age": 2592000}

Sub-recursos

Exemplo: se example.com carregar foobar.com/cat.gif e esse recurso não for carregado:

  • O coletor de NEL de foobar.com foi notificado
  • O coletor de NEL de example.com não foi notificado.

A regra geral é que o NEL reproduz registros do lado do servidor, recém-gerados no cliente.

Como example.com não tem visibilidade dos registros do servidor de foobar.com, ele também não tem visibilidade dos relatórios de NEL.

Configurações do relatório de depuração

Se você não encontrar relatórios no servidor, acesse chrome://net-export/. Essa página é útil para verificar se tudo está configurado corretamente e se os relatórios estão sendo enviados corretamente.

E o ReportingObserver?

O ReportingObserver é um mecanismo de denúncias relacionado, mas diferente. Ele é baseado em chamadas JavaScript. Ele não é adequado para a geração de registros de erros de rede, já que erros de rede não podem ser interceptados via JavaScript.

Exemplo de servidor

Veja abaixo um exemplo de servidor de nó que usa o Express. Ele mostra como configurar a geração de relatórios para erros de rede e cria um manipulador dedicado para capturar o resultado.

const express = require('express');

const app = express();
app.use(
  express.json({
    type: ['application/json', 'application/reports+json'],
  }),
);
app.use(express.urlencoded());

app.get('/', (request, response) => {
  // Note: report_to and not report-to for NEL.
  response.set('NEL', `{"report_to": "network-errors", "max_age": 2592000}`);

  // The Report-To header tells the browser where to send network errors.
  // The default group (first example below) captures interventions and
  // deprecation reports. Other groups, like the network-error group, are referenced by their "group" name.
  response.set(
    'Report-To',
    `{
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://reporting-observer-api-demo.glitch.me/reports"
    }],
  }, {
    "group": "network-errors",
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://reporting-observer-api-demo.glitch.me/network-reports"
    }]
  }`,
  );

  response.sendFile('./index.html');
});

function echoReports(request, response) {
  // Record report in server logs or otherwise process results.
  for (const report of request.body) {
    console.log(report.body);
  }
  response.send(request.body);
}

app.post('/network-reports', (request, response) => {
  console.log(`${request.body.length} Network error reports:`);
  echoReports(request, response);
});

const listener = app.listen(process.env.PORT, () => {
  console.log(`Your app is listening on port ${listener.address().port}`);
});

Leia mais