Conheça a integridade do seu código com a API ReportingObserver

Encontre APIs descontinuadas nos seus apps de produção.

O ReportingObserver informa quando seu site usa uma API descontinuada ou se depara com uma intervenção do navegador. A funcionalidade básica foi lançada originalmente no Chrome 69. A partir do Chrome 84, ele pode ser usado em workers.

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    console.log(report.type, report.url, report.body);
  }
}, {buffered: true});

observer.observe();

Use o callback para enviar relatórios a um back-end ou provedor de análise para análise.

Por que isso é útil? Até essa API, os avisos de descontinuação e intervenção só estavam disponíveis no DevTools como mensagens do Console. As intervenções, em particular, são acionadas apenas por várias restrições do mundo real, como condições do dispositivo e da rede. Portanto, talvez você nunca veja essas mensagens ao desenvolver/testar um site localmente. ReportingObserver oferece uma solução para esse problema. Quando os usuários encontram problemas em potencial, os desenvolvedores da Web podem ser notificados sobre eles.

Contexto

Algum tempo atrás, escrevi uma postagem do blog (Observar seu app da Web) porque achei fascinante quantas APIs existem para monitorar as "coisas" que acontecem em um app da Web. Por exemplo, existem APIs que podem observar informações sobre o DOM: ResizeObserver, IntersectionObserver, MutationObserver. PerformanceObserver captura medidas de performance. E métodos como window.onerror e window.onunhandledrejection até nos informam quando algo dá errado.

No entanto, há outros tipos de avisos que não são capturados pelas APIs atuais. Quando o site usa uma API descontinuada ou se depara com uma intervenção do navegador, o DevTools é o primeiro a informar sobre ela:

Avisos do Console do DevTools sobre descontinuações e intervenções.
Avisos iniciados pelo navegador no Console do DevTools.

É natural que o window.onerror capture esses avisos. Ela não faz isso. Isso ocorre porque window.onerror não é acionado para avisos gerados diretamente pelo próprio user agent. Ele é acionado em erros de tempo de execução (exceções de JavaScript e erros de sintaxe) causados pela execução do código.

ReportingObserver retira a folga. Ele oferece uma maneira programática de receber notificações sobre alertas emitidos pelo navegador, como descontinuações e intervenções. Você pode usá-lo como uma ferramenta de relatórios e perder menos sono se perguntando se os usuários estão enfrentando problemas inesperados no seu site ativo.

A API

A ReportingObserver não é diferente das outras APIs Observer, como IntersectionObserver e ResizeObserver. Você dá a ela um retorno de chamada, que fornece informações. A informação recebida pelo callback é uma lista de problemas que a página causou:

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    // → report.type === 'deprecation'
    // → report.url === 'https://reporting-observer-api-demo.glitch.me'
    // → report.body.id === 'XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload'
    // → report.body.message === 'Synchronous XMLHttpRequest is deprecated...'
    // → report.body.lineNumber === 11
    // → report.body.columnNumber === 22
    // → report.body.sourceFile === 'https://reporting-observer-api-demo.glitch.me'
    // → report.body.anticipatedRemoval === <JS_DATE_STR> or null
  }
});

observer.observe();

Relatórios filtrados

É possível pré-filtrar os relatórios para observar apenas determinados tipos. No momento, há dois tipos de relatório: 'deprecation' e 'intervention'.

const observer = new ReportingObserver((reports, observer) => {
  …
}, {types: ['deprecation']});

Relatórios armazenados em buffer

Use a opção buffered: true quando quiser ver os relatórios que foram gerados antes da criação da instância do observador:

const observer = new ReportingObserver((reports, observer) => {
  …
}, {types: ['intervention'], buffered: true});

Essa opção é ótima para situações como o carregamento lento de uma biblioteca que usa um ReportingObserver. O observador é adicionado com atraso, mas você não perde nada que aconteceu anteriormente no carregamento de página.

Parar de observar

Pare de observar usando o método disconnect():

observer.disconnect();

Exemplos

Relatar as intervenções do navegador a um provedor de análise

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    sendReportToAnalytics(JSON.stringify(report.body));
  }
}, {types: ['intervention'], buffered: true});

observer.observe();

Receba uma notificação quando as APIs forem removidas

const observer = new ReportingObserver((reports, observer) => {
  for (const report of reports) {
    if (report.type === 'deprecation') {
      sendToBackend(`Using a deprecated API in ${report.body.sourceFile} which will be
                     removed on ${report.body.anticipatedRemoval}. Info: ${report.body.message}`);
    }
  }
});

observer.observe();

Conclusão

O ReportingObserver oferece outra maneira de descobrir e monitorar possíveis problemas no seu app da Web. É até mesmo uma ferramenta útil para entender a integridade da sua base de código (ou a falta dela). Enviar relatórios para um back-end, saber sobre problemas reais, atualizar código, lucrar!

Trabalho futuro

No futuro, minha esperança é que a ReportingObserver se torne a API real para detectar todos os tipos de problemas em JavaScript. Imagine uma API para capturar tudo o que dá errado no seu app:

Outros recursos:

Imagem principal por Sieuwert Otterloo em Unsplash (links em inglês).