Sentry-javascript: Anweisungen für die Offline-Berichterstellung?

Erstellt am 31. Okt. 2014  ·  27Kommentare  ·  Quelle: getsentry/sentry-javascript

Hallo, wir haben eine Web-App mit Offline-Funktionen bereitgestellt, und es wäre großartig, Sentry für die Anwendungsüberwachung zu verwenden. Wir verwenden es bereits für unser Backend und es funktioniert großartig!

Leider sehe ich dafür keine Unterstützung in raven js, daher denke ich, dass wir gezwungen wären, unsere eigene Lösung einzuführen. Können Sie dies bestätigen? Was wären Ihre Vorschläge für das weitere Vorgehen? Würden Sie empfehlen, zu versuchen, etwas Logik von Raven js wiederzuverwenden?

Hilfreichster Kommentar

Unsere Lösung:

Übergeben Sie shouldSendCallback an Raven-Init

Wenn keine Verbindung besteht, speichert unser logStorageService die Daten des Ereignisses

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();

Warteschlange beim Versuch, Protokolle zu senden

Queue löst diesen Code alle 25 Sekunden aus und liefert schließlich alle Ereignisse an 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]);
                                    });
                            }
                            ...
                        });
                });

Alle 27 Kommentare

Können Sie erkennen, ob der Benutzer offline ist?

Wenn ja, wäre es nicht unmöglich, Ereignisse zu sammeln und in eine Warteschlange einzureihen. Wenn der Benutzer wieder online ist, senden Sie ihn erneut über Raven.captureException .

Ich kann wahrscheinlich helfen, wie das funktionieren würde, oder einen Haken hinzufügen, um dies zu unterstützen.

Super, danke für die Zusammenarbeit. Ich konnte feststellen, dass der Benutzer gerade online war, um die Erreichbarkeit von Sentry zu testen. Dafür könnte ich die Übertragungsfehlerereignisse abhören, aber wie kann ich es dann erneut versuchen?

Über die Verwendung von captureException , das wäre in Ordnung, aber ich möchte den ausgezeichneten Handler, den raven für unbehandelte Ausnahmen bietet, beibehalten. Ich müsste eine mittlere Logik zwischen der Rabenfehlererkennung und der Fehlerübertragung hinzufügen

Ja, lass mich darüber nachdenken. Ich denke, es gibt eine gute Möglichkeit, dies entweder automatisch in raven-js zu unterstützen oder einen Hook dafür bereitzustellen. Ich denke, das ist gerecht.

Die gleiche Funktionalität suche ich auch. Nach Durchsicht der Dokumente scheint es, dass ein Workaround darin bestehen könnte, shouldSendCallback , etwa so:

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

Und dann auf Netzwerkkonnektivität warten und die Warteschlange mit Raven.captureException :

window.addEventListener('online', checkAndProcessQueue);

Das ist ein bisschen huckepack, aber ich habe ein ähnliches Problem. Wir können keine Fehler melden, wenn der Client die Verbindung zum Host verliert (obwohl sie nicht unbedingt offline sind). Beim Herumtrollen sehe ich, dass ein ravenFailure Ereignis im Fenster ausgelöst wird, aber ich kann nicht genügend Daten von diesem Ereignis abrufen, um das zu erreichen, was ich versuche: Wiederholen Sie das Senden des Fehlers bei einem Fehler.

Dafür sehe ich einige mögliche Ansätze:

  1. Eine retry Option pro Instanz oder pro Nachricht, die angeben kann, wie oft das Senden von Ereignissen wiederholt, wie oft vor dem Aufgeben usw. versucht werden soll.
  2. Ein Callback/Callback(s) für die captureException(), sendMessage()`, etc. Methoden die bei Erfolg/Fehler ausgelöst werden
  3. Versprechen dieser Methoden (meh)
  4. Auslösen von Ereignissen (wo?) bei Fehlern und Bereitstellen von genügend Kontext in den Ereignisdaten, um zu versuchen, dieses Ereignis erneut zu senden

Sie sollten wahrscheinlich einen Offline-Speicher haben, damit die Fehlermeldungen später gesendet werden können. Möglicherweise sogar, nachdem der Benutzer die App geschlossen und später im Online-Modus erneut geöffnet hat. Ähnlich einem "Offline First"-Ansatz:
http://offlinefirst.org/

Ich habe das gleiche Problem gehabt. Zuerst wollte ich es ähnlich lösen, wie ich das Offline-Google-Analytics-Problem mit einem Servicemitarbeiter löse. Der Ansatz wird von Google hier gut erklärt.

Wenn Sie jedoch auf Cordova abzielen, ist Service Worker möglicherweise nicht verfügbar.
Und eine _hacky_ Lösung wird benötigt. Ich habe mir diesen einfallen lassen:

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]);
  }
}

// ... 

Ich stimme @webberg zu. Ich war eigentlich ein wenig überrascht, dass dies noch nicht Teil von Rabe war, da es auf viele andere coole Arten ziemlich beeindruckend ist. Abhängig von der Architektur einer App kann es möglicherweise einen nicht trivialen Prozentsatz der Fehler geben, die das ERGEBNIS des Offline-Zustands sind. In der Lage zu sein, darüber zu berichten, ist in vielen Implementierungen ziemlich wichtig.

Also meine Stimme ist, dass dies eingebacken und automatisch sein sollte. Wenn beim Senden der Nachricht an den Sentry ein Fehler auftritt, sollte die Nachricht gespeichert und später erneut versucht werden (entweder bei einem Timer, bei einem Ereignis oder sogar nur bei der nächsten Nachrichtenübertragung, wenn Sie es einfach halten möchten).

Und was bedeutet das "DDN"-Label?

Ich war eigentlich ein wenig überrascht, dass dies noch nicht Teil von Rabe war, da es auf viele andere coole Arten ziemlich beeindruckend ist. Abhängig von der Architektur einer App kann es möglicherweise einen nicht trivialen Prozentsatz der Fehler geben, die das ERGEBNIS des Offline-Zustands sind.

Total gerecht. Aber ich bin mir nicht sicher, ob dies standardmäßig erfolgen sollte. Es gibt viele Szenarien, in denen die App auf keinen Fall funktioniert, wenn ein Skript nicht geladen wird. Und ich würde sagen, dass die meisten Apps einfach nicht offline funktionieren und dies auch nicht erwarten. Ob das eine gute Praxis ist oder nicht, ist eine andere Sache.

Aus diesem Grund protokollieren wir standardmäßig keine AJAX-Fehler, obwohl viele Raven-Benutzer Code dafür geschrieben haben. Aber wir werden versuchen, es einfach zu machen, _wenn Sie wollen_. Und das gleiche würde ich hier gerne machen.

Und was bedeutet das "DDN"-Label?

Nicht sicher. @mattrobenolt?

Designentscheidung erforderlich. :)

Ich bin mir nicht sicher, ob dies standardmäßig erfolgen sollte.

Ja das macht Sinn.

Aber wir werden versuchen, es einfach zu machen, wenn Sie möchten. Und das gleiche würde ich hier gerne machen.

Im Interesse, eine Designentscheidung zu treffen, hier einige Gedanken:

Wenn ich die Dokumente richtig verstehe, kann man mit der Konfigurationsoption transport im Grunde die Kontrolle über den letzten Teil der Pipeline übernehmen, in dem Sentry die Daten an den Server sendet, und für die Durchführung dieser Übertragung verantwortlich sein. In diesem Fall scheint dies der beste Ort zu sein, um eine Offline-Warteschlange einzufügen. Anstatt die Daten an den Server zu senden, senden Sie sie an eine Warteschlange, die im Hintergrund auf den Server hochgeladen wird. Das wäre, wenn jemand seinen eigenen Code schreiben würde, um dies zu ermöglichen.

Wäre es in ähnlicher Weise einfach genug, auch eine Konfigurationsoption ( includeOffline ?) bereitzustellen, die den standardmäßigen HTTP-Transport durch eine offizielle Raven-rolled offline-fähige Warteschlange ersetzen würde?

  • Speichern Sie die Warteschlange aus Gründen der Browserkompatibilität möglicherweise in localStorage und lassen Sie sie bei einer Zeitüberschreitung auf Verbindung prüfen.
  • Nutzen Sie für eine bessere Leistung und Stabilität möglicherweise Servicemitarbeiter, um die Warteschlange zu verwalten, damit Fehler sogar nach dem Schließen der Seite hochgeladen werden können. Aber ist es für eine Versorgungsbibliothek an dieser Stelle ein wenig anmaßend, ihre eigenen Servicemitarbeiter auf die Beine zu stellen?

ist diese funktion nun irgendwie in raven eingebaut worden?

@Freundschaft Nein, noch nicht. Soweit ich es verstanden habe, müssen Sie vorerst die Option transport überschreiben oder die Option shouldSendCallback , um eine Warteschlange für das spätere Senden zu erstellen.

@cudasteve danke!
Hat jemand eine funktionierende Beispielimplementierung? wenn nicht versuche ich mal einen zu schreiben und poste ihn hier

@Freundschaft das wäre sehr hilfreich. wir stehen vor dem gleichen problem

++1 bitte

+1

+1

Unsere Lösung:

Übergeben Sie shouldSendCallback an Raven-Init

Wenn keine Verbindung besteht, speichert unser logStorageService die Daten des Ereignisses

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();

Warteschlange beim Versuch, Protokolle zu senden

Queue löst diesen Code alle 25 Sekunden aus und liefert schließlich alle Ereignisse an 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]);
                                    });
                            }
                            ...
                        });
                });

Einige Beispiele oben zeigten einen Aufruf einer "privaten" Funktion. Ich kann jedoch nicht Raven._sendProcessedPayload oder Raven._send anrufen.

Wenn ich mir Ihren Quellcode ansehe, bin ich mir nicht einmal sicher, wie Raven() als Objekt konstruiert wird. Ich sehe nirgendwo "new Raven()".

Wie kann ich diese Funktionen aufrufen?

Egal, das Problem trat nur auf, wenn raven.min.js und nicht raven.js passierten, also beantwortet dies diese Frage.

Also habe ich den minimierten Namen für die _sendProcessedPayload Funktion gesucht und Folgendes ist in meinem Code (vorerst) gelandet:

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

Dies ist alles andere als ideal aufgrund des schrecklichen

Abschließende Anmerkung dazu für heute: Ich denke, Sie sollten _sendProcessedPayload öffentlich machen. Es fängt genau dort an, wo _send endet, wenn shouldSendCallback false zurückgibt.

Allerdings gefällt mir nicht, dass es die Nutzlast verändert. Es ist also nicht die ideale Methode.

Wurde diese Funktion schon zur Bibliothek hinzugefügt.

Ich habe das heute gebraucht, da ich eine Offline-fähige Funktion habe. Ich speichere alle meine eigenen Daten mit indexdb, aber es wäre schön, eine sofort einsatzbereite Offline-Funktionalität für Sentry zu haben. Wenn es seine eigene lokale Datenbank verwenden könnte, um Ereignisse zu speichern und regelmäßig/bei Netzwerkänderungen zu versuchen, die Datenbank zu senden und zu löschen, wäre das sehr nützlich.

Wenn ich Ausnahmen speichere, um sie später zu senden, wenn ich online bin, kann ich dann den Zeitstempel für die Ausnahmen festlegen, um anzuzeigen, dass sie nicht jetzt aufgetreten sind, wenn ich sie an die Wache sende, sondern irgendwann in der Vergangenheit? Ich denke, ich könnte es einfach im Extra hinzufügen, aber es wäre schön, den tatsächlichen Zeitstempel setzen zu können.

Ich sehe keine solche Option in captureException

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen