Anfragedaten erfassen und bereinigen

Erfassen Sie die Anfragedaten, um zu verstehen, welche Fehler Ihnen im Frontend unterlaufen

Anfragedaten erfassen und bereinigen

Manchmal sind Fehler in Ihrem Client-Code nicht so offensichtlich wie ein leerer Bildschirm, weil keiner Ihrer JavaScript-Codes funktioniert. Manchmal liegt das Problem Ihrer App darin, dass Sie bei bestimmten Aktionen Ihrer Benutzer eine Anfrage an den Server falsch zusammenstellen. Der Client-Code funktioniert, in der Konsole erscheinen keine JS-Fehler, aber Ihrem Backend gefällt nicht wirklich, was Sie ihm senden.

Mit OpenReplay können Sie die Client-Server-Kommunikation als Teil Ihres normalen Session Replays erfassen und später überprüfen. Schauen wir uns also an, wie das geht und welchen Nutzen es bringt.

Für dieses How-to habe ich eine einfache React-Anwendung erstellt, die die Bored API verwendet. Das ist eine sehr einfache API, die anhand einiger Parameter einen zufälligen Aktivitätsvorschlag zurückgibt. Daraus habe ich die „I’m bored App“ gemacht, die so aussieht:

Sie finden sie live auf Netlify hier, und wenn Sie sich den Code im Detail ansehen möchten, steht er vollständig auf GitHub zur Verfügung.

Diese Anwendung besteht aus 2 Komponenten: Die Komponente SearchForm kümmert sich um die Darstellung dieser beiden Felder und der Schaltfläche sowie um das Senden der eigentlichen Anfrage an die API. Die Komponente Suggestion stellt den Vorschlag einfach in einem ansprechenden Kasten dar.

Ich konzentriere mich auf die erste, da nur sie Anfragen mit der Funktion fetch sendet.

Beachten Sie, dass diese Technik auch für jede mit Axios ausgeführte Anfrage funktioniert.

Werfen wir einen kurzen Blick auf die Komponente, um zu verstehen, was sie tut.

Der Code der Komponente SearchForm

Section titled Der Code der Komponente SearchForm

Das ist keine komplexe Komponente, aber es gibt einen Abschnitt, der für diesen speziellen Anwendungsfall besonders relevant ist. Schauen wir ihn uns daher kurz an.

import { Container, Col, Form, Row, Button } from 'react-bootstrap';

const SearchForm = ({setResult, fetcher}) => {
const getSomething = async (evt) => {
    evt.preventDefault()
    let form = evt.target

    const API_URL = "/api/activity?"
    let getParams = {}
    if(form.participants.value !== '') {
      getParams.participants = form.participants.value
    }

    if(form.priceRange.value !== '') {
      let prices = form.priceRange.value.split("_")
      getParams.minprice = prices[0]
      getParams.maxprice = prices[1]
    }

    let results = await fetcher(API_URL + new URLSearchParams(getParams), {
        mode: 'no-cors'
    })
    setResult(await results.json())

    return false
  }

    return (
        <Container>
        <Form onSubmit={getSomething}>
          <Row>
            <Col>
          <Form.Group controlId='participants' >
            <Form.Label>Participants</Form.Label>
            <Form.Control type='text' name="totalParticipants" placeholder='Leave empty if you dont care...'></Form.Control>
          </Form.Group>
          </Col>
            <Col>
          <Form.Group controlId='priceRangeId'>
            <Form.Label>Price range</Form.Label>
            <Form.Select name="priceRange" >
              <option value="" >Select one or leave empty if you dont care</option>
              <option value="0.0">Free</option>
              <option value="0.1_0.5">Cheap</option>
              <option value="0.6_1.0">Expensive</option>
            </Form.Select>
          </Form.Group>
          </Col>
          </Row>
          <Row className='m-3'>
            <Col>
            <Form.Group>
              <Button variant="primary" type="submit">Get me something!</Button>
            </Form.Group>
            </Col>
          </Row>
        </Form>
      </Container>
    )
}

export default SearchForm

Beachten Sie die Funktion getSomething – dort passiert der Großteil der Magie. Die Funktion wird aufgerufen, wenn das Submit-Ereignis des Formulars ausgelöst wird. Dabei erhält die Funktion das synthetische Ereignis, in dessen Eigenschaft target das Formular verknüpft ist. Wir erfassen einfach die Werte aus den einzelnen Filtern (dem Eingabefeld und dem Dropdown) und führen dann die Anfrage mit der Funktion fetch aus. Beachten Sie, dass die URL nicht direkt auf den Endpunkt der BoredAPI zeigt. Damit die Anfrage funktioniert und nicht wegen CORS-Einschränkungen blockiert wird, habe ich im Backend einen Proxy konfiguriert, der alle Anfragen von /api an die eigentliche API weiterleitet.

Nachdem Sie den Code gesehen haben, schauen wir uns an, was Sie erhalten, wenn Sie den Tracker von OpenReplay ohne das Fetch-Plugin installieren.

Reguläre Datenerfassung mit OpenReplay

Section titled Reguläre Datenerfassung mit OpenReplay

Für dieses Beispiel verwende ich die NPM-Version des Pakets. Wenn Sie nicht wissen, wie das geht, lesen Sie die Dokumentation und kehren Sie dann hierher zurück.

Das ist die standardmäßige Oberfläche des Session Replays. Beachten Sie, dass ich in der unteren Hälfte bereits den Tab „Network“ ausgewählt habe. Er zeigt zwar die gesendeten Anfragen an, enthält aber keine Details dazu. Selbst wenn Sie auf eine davon klicken, erhalten Sie nur die minimal verfügbaren Details:

Was können wir also tun? Sie können die Erfassung der Anfrageinformationen mit dem Objekt mit Netzwerkoptionen aktivieren. Schauen wir uns das an.

Anfragedaten in Ihren Session Replays erfassen

Section titled Anfragedaten in Ihren Session Replays erfassen

Dazu müssen wir lediglich beim Instanziieren des Trackers eine Konfigurationsoption hinzufügen. Wenn Sie jetzt die Zeile new tracker(...) schreiben, fügen Sie eine neue Eigenschaft hinzu:

import Tracker from '@openreplay/tracker';

const tracker = new Tracker({
  projectKey: "<your project key>",
  network: {
    capturePayload: true //start capturing the payload of every request
  }
});

Mehr ist nicht nötig: Ab jetzt werden bei jeder Anfrage, die Sie ausführen, die Daten vom Tracker aufgezeichnet. Stellen Sie die Änderung nun bereit, testen Sie die App, schließen Sie den Tab und warten Sie ein paar Minuten. Die Sitzung sollte bald erscheinen, und Sie können auf die Schaltfläche „play“ klicken.

Die Client-Server-Kommunikation untersuchen

Section titled Die Client-Server-Kommunikation untersuchen

Für dieses Beispiel schauen wir uns auch ein Problem an, das mir nach der Veröffentlichung der Anwendung aufgefallen ist.

Beachten Sie das Warnfeld, das ich in diesem Fall erhalte:

Als Entwickler, der dies programmiert hat, weiß ich, wie ich testen und herausfinden kann, wo der Fehler liegt. Als Benutzer sagt mir der Fehler aber nicht wirklich viel, und ich kann ihn möglicherweise nicht so kommunizieren, dass das Entwicklungsteam ihn versteht. Als Benutzer kann ich mich also einfach beim Unternehmen darüber beschweren, dass die App nicht funktioniert, und Sie als der für die Anwendung verantwortliche Entwickler können sich meine Sitzung ansehen und die vom Client gesendete Anfrage sowie die Antwort des Servers prüfen.

Sehen Sie sich nun die Oberfläche des Session Replays an. Im Tab „Network“ sehen Sie die Anfragen, die wir an die externe API gesendet haben.

Jetzt müssen wir nur noch den Moment finden, in dem wir die Fehlerantwort erhalten, und uns die gesendeten Anfragen ansehen. Wahrscheinlich sehen Sie das Problem in den Anfragedetails. In unserem Fall lautet der Fehler „Failed to query due to error in arguments“. Das bedeutet, dass wir keine gültige Anfrage senden, wenn wir im Dropdown die Option „Free“ auswählen. Schauen wir uns also die Details an.

Sehen Sie das Problem? Ich helfe Ihnen:

Ja, ich sende undefined als Wert des Attributs maxprice. Das habe ich in meiner Logik komplett übersehen und erst beim Untersuchen der Anfrage bemerkt. Zugegeben, jetzt, da ich weiß, wo das Problem liegt, ist es leicht zu beheben. Dank dieses Vorgehens hätte ich aber entweder einen sehr detaillierten Fehlerbericht erstellen oder dem Entwickler direkt helfen können, das Problem zu identifizieren und zu lösen, ohne selbst testen und das Problem reproduzieren zu müssen.

Den Datenschutz auf die Probe stellen

Section titled Den Datenschutz auf die Probe stellen

Gut, gehen wir mit diesem Beispiel noch einen Schritt weiter und tun so, als bräuchte ich für diese Anfrage auch die Telefonnummer meines Benutzers. Natürlich brauche ich sie nicht, aber spielen Sie bitte kurz mit.

Ich füge das Feld zum Formular hinzu und passe den Code an, sodass er diesen Wert erfasst und als Teil der Anfrage sendet.

Im HTML des Formulars müssen wir dafür lediglich ein neues Element Col hinzufügen, etwa so:

<!-- previous code -->
<Col>
    <Form.Group controlId='phoneNumber'>
        <Form.Label>Phone Number</Form.Label>
        <Form.Control type='number' name="phoneNumber" placeholder='Enter your phone number here please'></Form.Control>
    </Form.Group>
</Col>
<!-- rest of the code -->

Und den Inhalt dieses Feldes in die eigentliche Anfrage aufzunehmen, erfordert nur eine einzige Codezeile:

getParams.phonenumber = form.phoneNumber.value

Was passiert nun, wenn wir diesen neuen Code verwenden und eine Sitzung mit OpenReplay erfassen? Nun, zwei Dinge:

  1. Das Replay, das Sie ansehen, bereinigt den Inhalt des Telefonnummernfelds automatisch, sodass er niemandem angezeigt wird, der es sich ansieht.
  2. Die vom Plugin erfassten Anfrageinformationen zeigen den Wert dagegen an.

Der folgende Screenshot zeigt, was ich gerade beschrieben habe:

Im rechten Bereich des Bildschirms sehen Sie die vollständige Telefonnummer. Das liegt daran, dass der normale Tracker das Telefonnummernfeld zwar als numerisches Feld erkennt, seine Eingabe aber vorsichtshalber nicht erfasst, falls die Zahl personenbezogene Informationen darstellt. Auf der Anfrageseite können wir diese Annahme jedoch nicht treffen, da der Entwickler mit den Daten oder sogar mit dem Namen des Parameters alles Mögliche gemacht haben könnte. Die Frage lautet also: Können wir mit diesem Plugin die Privatsphäre unserer Benutzer schützen?

Und die Antwort lautet, wie ich gern berichte: JA, das können wir.

Wenn Sie zum Anfang dieses Tutorials zurückgehen, wo ich die Netzwerkoptionen konfiguriert habe, werden Sie sehen, dass ich nichts zur Bereinigung gesagt habe. Als Teil dieser Optionen können Sie jedoch einen Callback angeben, der Daten bereinigen soll. Dieser Callback erhält ein einzelnes Attribut, das sowohl das Anfrage- als auch das Antwortobjekt enthält. Sie können beide beliebig bearbeiten; sie wirken sich nicht auf die eigentliche Anfrage aus, ändern aber die Darstellung der Daten in der OpenReplay-Oberfläche.

Angenommen, ich möchte das Attribut „phonenumber“ ändern und die Ziffern entfernen, damit diese Information nicht preisgegeben wird. Das geht so:

const tracker = new Tracker({
  projectKey: "<your project id>",
  network: {
    capturePayload: true,
    sanitizer: (data) => { //we change the content of the "phonenumber" parameter from the url
      data.url = data.url.replace(/phonenumber=([0-9]+)/, "phonenumber=XXXXXX")
      return data
    }
    }
});

Wie Sie sehen, ist die Änderung einfach: Wir ersetzen nur die Ziffern in diesem Attribut, sodass die Anfrage in unserer Oberfläche jetzt so aussieht:

Jetzt sind die Daten Ihrer Benutzer wieder geschützt.

Wenn Sie sich den Code dieses Beispiels im Detail ansehen möchten, finden Sie ihn hier auf GitHub. Wenn Sie Probleme beim Einrichten des Fetch-Plugins oder des Trackers selbst haben, wenden Sie sich bitte an unsere Slack-Community und fragen Sie unsere Entwickler direkt!