Sentry-javascript: Instruções para relatórios off-line?

Criado em 31 out. 2014  ·  27Comentários  ·  Fonte: getsentry/sentry-javascript

Olá, temos um aplicativo da web com recursos off-line implantado e seria ótimo usar o Sentry para o monitoramento do aplicativo. Já o usamos para o nosso back-end e funciona muito bem!

Infelizmente, não vejo suporte no raven js para isso, então acho que seríamos forçados a lançar nossa própria solução. Você pode confirmar isso? Quais seriam suas sugestões sobre como proceder? Você recomendaria tentar reutilizar alguma lógica de raven js?

Comentários muito úteis

Nossa solução:

Passe shouldSendCallback para o Raven init

Se não houver conexão, out logStorageService salvará os dados do evento

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

Fila tentando enviar logs

Queue dispara este código a cada 25 segundos, eventualmente entregando todos os eventos ao Sentry

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

Todos 27 comentários

Você consegue detectar se o usuário está offline?

Nesse caso, não seria impossível coletar eventos e colocá-los em fila. Quando o usuário ficar online novamente, envie-o através de Raven.captureException novamente.

Provavelmente posso ajudar com como isso funcionaria ou adicionar um gancho para ajudar nisso.

Ótimo, obrigado pela colaboração. Pude detectar o usuário online mesmo apenas testando a acessibilidade do Sentry. Para isso, eu poderia escutar os eventos de falha de transmissão, mas então como tentar novamente?

Sobre o uso de captureException , tudo bem, mas eu gostaria de manter o excelente manipulador que o raven fornece para exceções não tratadas. Eu precisaria adicionar alguma lógica intermediária entre a detecção de erro do raven e a transmissão de erro

Sim, deixe-me pensar sobre isso. Acho que há uma boa maneira de oferecer suporte a isso automaticamente no raven-js ou fornecer um gancho para fazê-lo. Eu acho isso justo.

Procuro a mesma funcionalidade também. Depois de examinar os documentos, parece que uma solução alternativa poderia ser usar shouldSendCallback , algo assim:

shouldSendCallback: function(data) {
  localStorage['queued-errors'] = (localStorage['queued-errors'] || []).push(data);
  return false;
}

Em seguida, escute a conectividade de rede e processe a fila usando Raven.captureException :

window.addEventListener('online', checkAndProcessQueue);

Isso está pegando carona um pouco, mas eu tenho um problema semelhante. Não podemos relatar erros quando o cliente perde a conexão com o host (embora eles não estejam necessariamente offline). Procurando, vejo que há um evento ravenFailure sendo disparado na janela, mas não consigo obter dados suficientes deste evento para realizar o que estou tentando fazer: repetir o envio do erro em caso de falha.

Vejo algumas abordagens possíveis para isso:

  1. Uma opção por instância ou por mensagem retry , que pode especificar com que frequência tentar enviar eventos novamente, quantas vezes tentar antes de desistir, etc.
  2. Um callback / callback (s) nos métodos captureException(), sendMessage () `, etc. que é / são acionados em caso de sucesso / falha
  3. Prometendo esses métodos (meh)
  4. Acionar eventos (onde?) Em caso de falha e fornecer contexto suficiente nos dados do evento para tentar um reenvio desse evento

Você provavelmente deve ter um recurso de armazenamento offline para que as mensagens de erro possam ser enviadas posteriormente. Possivelmente, mesmo após o usuário fechar o aplicativo e, posteriormente, reabri-lo enquanto estiver online. Semelhante a uma abordagem "offline primeiro":
http://offlinefirst.org/

Eu enfrentei o mesmo problema. No início, eu queria resolvê-lo da mesma forma que estou resolvendo o problema do google-analytics offline com um service worker . A abordagem é bem explicada pelo Google aqui .

No entanto, ao direcionar para Cordova, o Service Worker pode não estar disponível.
E uma solução _hacky_ é necessária. Eu inventei este:

https://gist.github.com/oliviertassinari/73389727fe58373eef7b63d2d2c5ce5d

import raven from 'raven-js';
import config from 'config';

const SENTRY_DSN = 'https://[email protected]/YYYY';

function sendQueue() {
  const sentryOffline = JSON.parse(window.localStorage.sentryOffline);

  if (sentryOffline.length > 0) {
    raven._send(sentryOffline[0]);
  }
}

// ... 

Eu concordo com @webberig. Na verdade, fiquei um pouco surpreso por isso já não fazer parte do raven, já que é bastante impressionante em muitos outros aspectos legais. Dependendo da arquitetura de um aplicativo, pode haver uma porcentagem não trivial de erros que são o RESULTADO de estar offline. Ser capaz de relatar sobre isso é muito crítico em muitas implementações.

Portanto, meu voto é que isso seja incorporado e automático. Quando ocorre um erro no envio da mensagem para o sentinela, a mensagem deve ser armazenada e tentada novamente mais tarde (seja em um cronômetro, em um evento ou mesmo apenas na próxima transmissão de mensagem se você quiser mantê-la simples).

Além disso, o que significa o rótulo "DDN"?

Na verdade, fiquei um pouco surpreso por isso já não fazer parte do raven, já que é bastante impressionante em muitos outros aspectos legais. Dependendo da arquitetura de um aplicativo, pode haver uma porcentagem não trivial de erros que são o RESULTADO de estar offline.

Totalmente justo. Mas não tenho certeza se isso deve ser feito por padrão. Existem muitos cenários em que, se um script não carregar, o aplicativo não funcionará de qualquer maneira. E eu diria que a maioria dos aplicativos simplesmente não funcionam off-line e não esperam que funcionem. Se isso é uma boa prática ou não, é outra coisa.

É por isso que não registramos erros de AJAX por padrão, embora uma boa parte dos usuários do Raven tenha escrito um código para fazer isso. Mas vamos tentar tornar mais fácil fazer isso _se você quiser_. E eu gostaria de fazer a mesma coisa aqui.

Além disso, o que significa o rótulo "DDN"?

Não tenho certeza. @mattrobenolt?

É necessária uma decisão de design. :)

Não tenho certeza se isso deve ser feito por padrão.

Sim, isso faz sentido.

Mas tentaremos tornar isso mais fácil se você quiser. E eu gostaria de fazer a mesma coisa aqui.

Portanto, no interesse de ajudar a tomar uma decisão de design, aqui estão algumas idéias:

Se estou entendendo a documentação corretamente, a opção transport config permite basicamente assumir o controle da última parte do pipeline onde o Sentry envia os dados para o servidor e se tornar responsável por fazer essa transmissão acontecer. Nesse caso, parece o melhor lugar para conectar uma fila offline. Em vez de enviar os dados para o servidor, envie-os para uma fila que faz upload para o servidor em segundo plano. Isso seria se alguém estivesse escrevendo seu próprio código para fazer isso acontecer.

Em uma linha semelhante, seria simples o suficiente também expor uma opção de configuração ( includeOffline ?) Que substituiria o transporte HTTP padrão por uma fila oficial com capacidade offline enrolada Raven?

  • Para compatibilidade do navegador, talvez armazene a fila em localStorage e faça com que verifique a conexão em um tempo limite.
  • Para melhor desempenho e estabilidade, talvez você aproveite os service workers para gerenciar a fila de forma que os erros possam ser carregados mesmo após o fechamento da página. Mas é um pouco presunçoso que uma biblioteca de utilitários esteja criando seus próprios service workers neste momento?

essa funcionalidade agora foi construída de alguma forma para raven?

@Freundschaft Não, ainda não. Pelo que entendi, por enquanto você terá que substituir a opção transport ou usar shouldSendCallback para construir uma fila para envio posterior.

@cudasteve obrigado!
alguém conseguiu uma implementação de amostra funcional? senão vou tentar escrever um e postar aqui

@Freundschaft isso seria muito útil. estamos enfrentando o mesmo problema

++ 1 por favor

+1

+1

Nossa solução:

Passe shouldSendCallback para o Raven init

Se não houver conexão, out logStorageService salvará os dados do evento

var options = {
    ...
    shouldSendCallback: function(data) {
        if (connectionStatus.check() && Raven.isSetup()) {
            return true;
        } else {
            // store log data somewhere
            logStorageService.set(data);
            return false;
        }
    }
    ...
};

Raven.config(SENTRY_KEY, options).install();

Fila tentando enviar logs

Queue dispara este código a cada 25 segundos, eventualmente entregando todos os eventos ao Sentry

queue.enqueue(function () {
                    logStorageService
                        .getKeys()
                        .then(function (keys) {
                            if (keys && keys[0]) {
                                logStorageService
                                    .get(keys[0])
                                    .then(function (log) {
                                        Raven.captureMessage('', log);
                                        logStorageService.remove(keys[0]);
                                    });
                            }
                            ...
                        });
                });

Alguns exemplos acima mostraram uma chamada para uma função "privada". No entanto, não consigo chamar Raven._sendProcessedPayload ou Raven._send .

Olhando para o seu código-fonte, não tenho certeza de como Raven () está sendo construído como um objeto. Não vejo "novo Raven ()" em lugar nenhum.

Como posso chamar essas funções?

Esqueça, o problema só aconteceu quando raven.min.js e não raven.js modo que responde a essa pergunta.

Então, eu procurei o nome minimizado para a função _sendProcessedPayload e aqui está o que acabei com o meu código (por enquanto):

  /**
   * HACK: Using a private function that gets minified!
   * Pinned Raven-js to version 3.8.1.
   */
  Raven._sendProcessedPayload = Raven._sendProcessedPayload || Raven.Y;

  ...

  function processQueue(items) {
    // Stop if we're not online.
    if (!canSend())
      return;
    // Process the given items or get them from the queue.
    items = items || queue.getItems();
    if (!items || items.length < 1)
      return;
    // First in, first out.
    var next = items.shift();
    // Send the next item.
    Raven._sendProcessedPayload(next, function processed(error) {
      // If no errors, save the queue and process more items.
      if (!error) {
        queue.save(items);
        processQueue(items);
      }
    });
  }

  function shouldSend(data) {
    if (canSend())
      return true;
    if (data.extra.retry)
      return false;
    data.extra.retry = true;
    queue.add(data);
    return false;
  }

  ...

  setInterval(processQueue, OFFLINE_QUEUE_TIMEOUT);

Isso está longe do ideal devido ao horrendo HACK e também porque mais erros poderiam ser capturados enquanto estou processando esta fila, então eles seriam enviados fora de ordem ...

Nota final sobre isso para hoje: Acho que você deve tornar _sendProcessedPayload público. Ele começa exatamente onde _send sai quando shouldSendCallback retorna falso, então é a escolha óbvia para chamar se você quiser repetir um envio ...

No entanto, não gosto que modifique a carga útil. Portanto, não é o método ideal.

Este recurso já foi adicionado à biblioteca.

Eu precisei disso hoje, pois tenho um recurso compatível com offline. Eu armazeno todos os meus próprios dados usando o indexdb, mas seria bom ter uma funcionalidade offline pronta para usar para o Sentry. Se ele pudesse usar seu próprio banco de dados local para armazenar eventos e mudanças periódicas / na rede, tentar enviar e limpar o banco de dados que seria muito útil.

Se eu armazenar exceções para enviar mais tarde quando estiver online, há uma maneira de definir o carimbo de data / hora nas exceções para indicar que elas não aconteceram agora, quando estou enviando-as para o sentinela, mas em algum ponto do passado? Acho que poderia simplesmente adicioná-lo no extra, mas seria bom poder definir o carimbo de data / hora real.

Não vejo essa opção em captureException

Esta página foi útil?
0 / 5 - 0 avaliações