Sentry-javascript: ¿Instrucciones para informes sin conexión?

Creado en 31 oct. 2014  ·  27Comentarios  ·  Fuente: getsentry/sentry-javascript

Hola, tenemos una aplicación web con capacidades sin conexión implementadas, y sería genial usar Sentry para el monitoreo de la aplicación. ¡Ya lo usamos para nuestro back-end y funciona muy bien!

Desafortunadamente, no veo soporte en raven js para esto, así que creo que nos veríamos obligados a implementar nuestra propia solución. ¿Puedes confirmar esto? ¿Cuáles serían sus sugerencias sobre cómo proceder? ¿Recomendaría intentar reutilizar algo de lógica de raven js?

Comentario más útil

Nuestra solución:

Pase shouldSendCallback a Raven init

Si no hay conexión, logStorageService guardará los datos del 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();

Cola intentando enviar registros

La cola dispara este código cada 25 segundos, y finalmente entrega todos los eventos a 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 comentarios

¿Puedes detectar si el usuario está desconectado?

Si es así, no sería imposible recopilar eventos y ponerlos en cola. Cuando el usuario vuelva a estar en línea, envíelo a través de Raven.captureException nuevamente.

Probablemente pueda ayudar con cómo funcionaría o agregar un gancho para ayudar con esto.

Genial, gracias por la colaboración. Pude detectar que el usuario estaba en línea incluso solo probando la accesibilidad de Sentry. Para esto, podría escuchar los eventos de falla de transmisión, pero ¿cómo volver a intentarlo?

Acerca del uso de captureException , eso estaría bien, pero me gustaría mantener el excelente controlador que Raven proporciona para excepciones no controladas. Necesitaría agregar una lógica intermedia entre la detección de errores de cuervo y la transmisión de errores

Sí, déjame pensar en esto. Creo que hay una buena manera de que podamos admitir esto automáticamente en raven-js o proporcionar un gancho para hacerlo. Creo que eso es justo.

También busco la misma funcionalidad. Después de examinar los documentos, parece que una solución podría ser usar shouldSendCallback , algo como esto:

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

Y luego escuche la conectividad de la red y procese la cola usando Raven.captureException :

window.addEventListener('online', checkAndProcessQueue);

Esto es un poco a cuestas, pero tengo un problema similar. No podemos informar errores cuando el cliente pierde la conexión con el host (aunque no necesariamente están fuera de línea). Al dar vueltas, veo que se está ravenFailure un evento

Veo algunos enfoques posibles para esto:

  1. Una opción retry por instancia o por mensaje, que puede especificar con qué frecuencia reintentar el envío de eventos, cuántas veces intentar antes de darse por vencido, etc.
  2. Una devolución de llamada / devolución de llamada (s) en los métodos captureException(), sendMessage () `, etc.que se activan en caso de éxito / fracaso
  3. Prometiendo esos métodos (meh)
  4. Activar eventos (¿dónde?) En caso de falla y proporcionar suficiente contexto en los datos del evento para intentar un reenvío de ese evento

Probablemente debería tener una instalación de almacenamiento fuera de línea para que los mensajes de error se puedan enviar más adelante. Posiblemente incluso después de que el usuario cierre la aplicación y luego la vuelva a abrir mientras está en línea. Similar a un enfoque "primero sin conexión":
http://offlinefirst.org/

Me he enfrentado al mismo problema. Al principio, quería resolverlo de manera similar a cómo estoy resolviendo el problema de Google Analytics sin conexión con un trabajador del servicio . El enfoque está bien explicado por Google aquí .

Sin embargo, cuando se dirige a Cordova, es posible que Service Worker no esté disponible.
Y se necesita una solución _hacky_. Se me ocurrió 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]);
  }
}

// ... 

Estoy de acuerdo con @webberig. De hecho, me sorprendió un poco que esto no fuera ya parte de Raven, ya que es bastante impresionante en muchos otros aspectos interesantes. Dependiendo de la arquitectura de una aplicación, podría haber un porcentaje no trivial de errores que son el RESULTADO de estar fuera de línea. Ser capaz de informar sobre ellos es bastante crítico en muchas implementaciones.

Así que mi voto es que esto debería ser integrado y automático. Cuando hay un error al enviar el mensaje al centinela, el mensaje debe almacenarse e intentarse nuevamente más tarde (ya sea en un temporizador, en un evento o incluso solo en la siguiente transmisión del mensaje si desea que sea simple).

Además, ¿qué significa la etiqueta "DDN"?

De hecho, me sorprendió un poco que esto no fuera ya parte de Raven, ya que es bastante impresionante en muchos otros aspectos interesantes. Dependiendo de la arquitectura de una aplicación, podría haber un porcentaje no trivial de errores que son el RESULTADO de estar fuera de línea.

Totalmente justo. Pero no estoy seguro de que deba hacerse de forma predeterminada. Hay muchos escenarios en los que, si un script no se carga, la aplicación no funcionará pase lo que pase. Y yo diría que la mayoría de las aplicaciones simplemente no funcionan sin conexión, y no lo esperan. Si eso es una buena práctica o no, es otra cosa.

Es por eso que no registramos errores AJAX de forma predeterminada, a pesar de que una buena parte de los usuarios de Raven han escrito código para hacerlo. Pero intentaremos que sea más fácil hacerlo _ si lo desea_. Y me gustaría hacer lo mismo aquí.

Además, ¿qué significa la etiqueta "DDN"?

No estoy seguro. @mattrobenolt?

Se necesita una decisión de diseño. :)

No estoy seguro de que deba hacerse de forma predeterminada.

Eso tiene sentido.

Pero intentaremos que sea más fácil si lo desea. Y me gustaría hacer lo mismo aquí.

Entonces, con el interés de ayudar a tomar una decisión de diseño, aquí hay algunas ideas:

Si entiendo los documentos correctamente, la opción transport config permite básicamente tomar el control de la última parte de la canalización donde Sentry envía los datos al servidor y se hace responsable de hacer que esa transmisión suceda. En ese caso, ese parece ser el mejor lugar para agregar una cola fuera de línea. En lugar de enviar los datos al servidor, envíelos a una cola que se carga en el servidor en segundo plano. Eso sería si alguien estuviera escribiendo su propio código para que esto suceda.

En una línea similar, ¿sería lo suficientemente simple también exponer una opción de configuración ( includeOffline ?) Que reemplazaría el transporte HTTP predeterminado con una cola oficial lista para usar sin conexión?

  • Para la compatibilidad del navegador, tal vez almacene la cola en localStorage y haga que verifique la conexión en un tiempo de espera.
  • Para un mejor rendimiento y estabilidad, quizás aproveche a los trabajadores del servicio para que administren la cola, de modo que los errores se puedan cargar incluso después de cerrar la página. Pero, ¿es un poco presuntuoso que una biblioteca de servicios públicos esté instalando a sus propios trabajadores de servicios en este momento?

¿Esta funcionalidad ahora se ha incorporado de alguna manera a Raven?

@Freundschaft No, todavía no. Según tengo entendido, por ahora tendrá que anular la opción transport o usar shouldSendCallback para crear una cola para enviar más tarde.

@cudasteve gracias!
¿Alguien tiene una implementación de muestra funcional? si no, intentaré escribir uno y publicarlo aquí

@Freundschaft esto sería muy útil. estamos enfrentando el mismo problema

++ 1 por favor

+1

+1

Nuestra solución:

Pase shouldSendCallback a Raven init

Si no hay conexión, logStorageService guardará los datos del 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();

Cola intentando enviar registros

La cola dispara este código cada 25 segundos, y finalmente entrega todos los eventos a 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]);
                                    });
                            }
                            ...
                        });
                });

Algunos ejemplos anteriores mostraron una llamada a una función "privada". Sin embargo, no puedo llamar a Raven._sendProcessedPayload o Raven._send .

Mirando su código fuente, ni siquiera estoy seguro de cómo se está construyendo Raven () como un objeto. No veo "new Raven ()" en ningún lado.

¿Cómo puedo llamar a estas funciones?

No importa, el problema solo sucedió cuando raven.min.js y no raven.js por lo que responde esa pregunta.

Entonces, busqué el nombre minificado para la función _sendProcessedPayload y esto es lo que terminé con en mi código (por ahora):

  /**
   * 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);

Esto está lejos de ser ideal debido al horrendo HACK y también porque se podrían capturar más errores mientras estoy procesando esta cola, por lo que se enviarían fuera de servicio ...

Nota final sobre esto para hoy: creo que debería hacer público _sendProcessedPayload . Se retoma justo donde _send sale cuando shouldSendCallback devuelve falso, por lo que es la opción obvia para llamar si desea volver a intentar un envío ...

Sin embargo, no me gusta que modifique la carga útil. Entonces, no es el método ideal.

¿Se ha agregado esta característica a la biblioteca?

Me encontré con la necesidad de esto hoy, ya que tengo una función sin conexión. Almaceno todos mis propios datos usando indexdb, pero sería bueno tener una funcionalidad fuera de línea lista para usar para Sentry. Si pudiera usar su propia base de datos local para almacenar eventos y periódicamente / en los cambios de red, intenta enviar y borrar la base de datos que sería muy útil.

Si almaceno excepciones para enviarlas más tarde cuando me conecto, ¿hay alguna manera de establecer la marca de tiempo en las excepciones para indicar que no sucedieron ahora cuando las envío al centinela, pero en algún momento del ¿pasado? Supongo que podría agregarlo en el extra, pero sería bueno poder establecer la marca de tiempo real.

No veo ninguna de estas opciones en captureException

¿Fue útil esta página
0 / 5 - 0 calificaciones