Netzwerkfehler-Logging (NEL)

Die Netzwerkfehlerprotokollierung (NEL) ist ein Mechanismus zum Erfassen von clientseitigen Netzwerkfehlern von einem Ursprung.

Über den NEL-HTTP-Antwortheader wird der Browser angewiesen, Netzwerkfehler zu erfassen. Anschließend werden die Fehler über die Reporting API an einen Server gesendet.

Die bisherige Reporting API

Wenn Sie die bisherige Reporting API verwenden möchten, müssen Sie einen Report-To-HTTP-Antwortheader festlegen. Der Wert ist ein Objekt, das eine Endpunktgruppe für den Browser beschreibt, an die Fehler gemeldet werden sollen:

Report-To:
{
    "max_age": 10886400,
    "endpoints": [{
    "url": "https://analytics.provider.com/browser-errors"
    }]
}

Wenn sich die Endpunkt-URL an einem anderen Ursprung als Ihre Website befindet, sollte der Endpunkt CORS-Preflight-Anfragen unterstützen. (z.B. Access-Control-Allow-Origin: *; Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS; Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With).

In diesem Beispiel wird der Browser so konfiguriert, dass er browsergenerierte Warnungen für max_age Sekunden an den Endpunkt https://analytics.provider.com/browser-errors meldet, wenn dieser Antwortheader mit der Startseite gesendet wird. Alle nachfolgenden HTTP-Anfragen der Seite (z. B. für Bilder und Scripts) werden ignoriert. Die Konfiguration wird während der Antwort der Hauptseite eingerichtet.

Kopfzeilenfelder

Jede Endpunktkonfiguration enthält einen group-Namen, ein max_age- und ein endpoints-Array. Im Feld include_subdomains können Sie auch festlegen, ob Subdomains bei der Meldung von Fehlern berücksichtigt werden sollen.

Feld Typ Beschreibung
group String Optional. Wenn kein group-Name angegeben ist, wird dem Endpunkt der Name „default“ zugewiesen.
max_age Zahl Erforderlich. Eine positive Ganzzahl, die die Lebensdauer des Endpunkts in Sekunden definiert. Wenn der Wert „0“ ist, wird die Endpunktgruppe aus dem Berichtscache des User-Agents entfernt.
endpoints Array<Object> Erforderlich. Ein Array von JSON-Objekten, das die tatsächliche URL Ihres Berichts-Collectors angibt.
include_subdomains boolean Optional. Ein boolescher Wert, mit dem die Endpunktgruppe für alle Subdomains des Hosts des aktuellen Ursprungs aktiviert wird. Wenn der Parameter weggelassen wird oder einen anderen Wert als „true“ hat, werden die Subdomains nicht an den Endpunkt gesendet.

Der group-Name ist ein eindeutiger Name, mit dem ein String einem Endpunkt zugeordnet wird. Verwenden Sie diesen Namen an anderen Stellen, die in die Reporting API eingebunden sind, um auf eine bestimmte Endpunktgruppe zu verweisen.

Das Feld max-age ist ebenfalls erforderlich und gibt an, wie lange der Browser den Endpunkt verwenden und Fehler an ihn melden soll.

Das Feld endpoints ist ein Array, das Failover- und Load Balancing-Funktionen bereitstellt. Weitere Informationen finden Sie im Abschnitt Failover und Load Balancing. Beachten Sie, dass der Browser nur einen Endpunkt auswählt, auch wenn die Gruppe mehrere Collector in endpoints auflistet. Wenn Sie einen Bericht an mehrere Server gleichzeitig senden möchten, muss Ihr Backend die Berichte weiterleiten.

Wie sendet der Browser Berichte?

Der Browser fasst Berichte in regelmäßigen Abständen in einem Batch zusammen und sendet sie an die von Ihnen konfigurierten Berichtsendpunkte.

Zum Senden von Berichten sendet der Browser eine POST-Anfrage mit Content-Type: application/reports+json und einem Textkörper, der das Array der erfassten Warnungen/Fehler enthält.

Wann sendet der Browser Berichte?

Berichte werden von Ihrer App außerhalb des Bandes gesendet. Das bedeutet, dass der Browser steuert, wann Berichte an Ihre Server gesendet werden.

Der Browser versucht, Berichte in der Warteschlange zum optimalen Zeitpunkt zu senden. Das kann sofort nach der Fertigstellung geschehen, um dem Entwickler zeitnah Feedback zu geben. Der Browser kann die Übermittlung aber auch verzögern, wenn er gerade mit der Verarbeitung von Aufgaben mit höherer Priorität beschäftigt ist oder sich der Nutzer gerade in einem langsamen und/oder überlasteten Netzwerk befindet. Der Browser kann auch priorisieren, dass Berichte zu einer bestimmten Quelle zuerst gesendet werden, wenn der Nutzer ein häufiger Besucher ist.

Bei der Verwendung der Reporting API treten kaum bis gar keine Leistungsprobleme auf (z.B. Netzwerkkonflikte mit Ihrer App). Außerdem können Sie nicht festlegen, wann der Browser Berichte aus der Warteschlange sendet.

Mehrere Endpunkte konfigurieren

Mit einer einzelnen Antwort können mehrere Endpunkte gleichzeitig konfiguriert werden, indem mehrere Report-To-Header gesendet werden:

Report-To: {
             "group": "default",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/browser-reports"
             }]
           }
Report-To: {
             "group": "network-errors-endpoint",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/network-errors"
             }]
           }

oder indem Sie sie in einem einzigen HTTP-Header kombinieren:

Report-To: {
             "group": "network-errors-endpoint",
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/network-errors"
             }]
           },
           {
             "max_age": 10886400,
             "endpoints": [{
               "url": "https://example.com/browser-errors"
             }]
           }

Nachdem Sie die Report-To-Header gesendet haben, speichert der Browser die Endpunkte gemäß ihren max_age-Werten im Cache und sendet alle diese üblen Konsolenwarnungen/-fehler an Ihre URLs.

Failover und Load Balancing

In den meisten Fällen konfigurieren Sie einen URL-Collector pro Gruppe. Da Berichte jedoch viel Traffic generieren können, enthält die Spezifikation Failover- und Load Balancing-Funktionen, die vom DNS-SRV-Eintrag inspiriert sind.

Der Browser versucht, einen Bericht an höchstens einen Endpunkt in einer Gruppe zu senden. Endpunkten kann eine weight zugewiesen werden, um die Last zu verteilen. Dabei erhält jeder Endpunkt einen bestimmten Anteil des Berichtstraffics. Endpoints können auch eine priority zugewiesen werden, um Fallback-Aufnehmer einzurichten.

Fallback-Collectors werden nur dann verwendet, wenn Uploads an primäre Collectors fehlschlagen.

Beispiel: Fallback-Collector unter https://backup.com/reports erstellen:

Report-To: {
             "group": "endpoint-1",
             "max_age": 10886400,
             "endpoints": [
               {"url": "https://example.com/reports", "priority": 1},
               {"url": "https://backup.com/reports", "priority": 2}
             ]
           }

Netzwerkfehlerprotokollierung einrichten

Einrichtung

Wenn Sie NEL verwenden möchten, richten Sie die Report-To-Überschrift mit einem Dispatcher ein, der eine benannte Gruppe verwendet:

Report-To: {
    ...
  }, {
    "group": "network-errors",
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://analytics.provider.com/networkerrors"
    }]
  }

Senden Sie als Nächstes den Antwortheader NEL, um mit dem Erfassen von Fehlern zu beginnen. Da NEL für einen Ursprung aktiviert werden muss, müssen Sie den Header nur einmal senden. Sowohl NEL als auch Report-To werden auf zukünftige Anfragen an denselben Ursprung angewendet und es werden weiterhin Fehler gemäß dem max_age-Wert erfasst, der zum Einrichten des Collectors verwendet wurde.

Der Headerwert muss ein JSON-Objekt sein, das ein max_age- und ein report_to-Feld enthält. Verwenden Sie letzteren, um auf den Gruppennamen Ihres Netzwerkfehler-Collectors zu verweisen:

GET /index.html HTTP/1.1
NEL: {"report_to": "network-errors", "max_age": 2592000}

Unterressourcen

Beispiel: Wenn example.com foobar.com/cat.gif lädt und diese Ressource nicht geladen werden kann:

  • Der NEL-Abholer von foobar.com wird benachrichtigt
  • Der NEL-Abholer von example.com wird nicht benachrichtigt

Als Faustregel gilt, dass NEL serverseitige Protokolle reproduziert, die gerade auf dem Client generiert wurden.

Da example.com keinen Zugriff auf die Serverprotokolle von foobar.com hat, kann es auch nicht auf die NEL-Berichte zugreifen.

Berichtskonfigurationen debuggen

Wenn auf Ihrem Server keine Berichte angezeigt werden, rufen Sie chrome://net-export/ auf. Auf dieser Seite können Sie prüfen, ob alles richtig konfiguriert ist und Berichte ordnungsgemäß gesendet werden.

Was ist mit ReportingObserver?

ReportingObserver ist ein ähnlicher, aber anderer Berichtsmechanismus. Er basiert auf JavaScript-Aufrufen. Sie eignet sich nicht für die Protokollierung von Netzwerkfehlern, da Netzwerkfehler nicht über JavaScript abgefangen werden können.

Beispielserver

Unten sehen Sie ein Beispiel für einen Node-Server, der Express verwendet. Es zeigt, wie Sie die Berichterstellung für Netzwerkfehler konfigurieren, und erstellt einen speziellen Handler, um das Ergebnis zu erfassen.

const express = require('express');

const app = express();
app.use(
  express.json({
    type: ['application/json', 'application/reports+json'],
  }),
);
app.use(express.urlencoded());

app.get('/', (request, response) => {
  // Note: report_to and not report-to for NEL.
  response.set('NEL', `{"report_to": "network-errors", "max_age": 2592000}`);

  // The Report-To header tells the browser where to send network errors.
  // The default group (first example below) captures interventions and
  // deprecation reports. Other groups, like the network-error group, are referenced by their "group" name.
  response.set(
    'Report-To',
    `{
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://reporting-observer-api-demo.glitch.me/reports"
    }],
  }, {
    "group": "network-errors",
    "max_age": 2592000,
    "endpoints": [{
      "url": "https://reporting-observer-api-demo.glitch.me/network-reports"
    }]
  }`,
  );

  response.sendFile('./index.html');
});

function echoReports(request, response) {
  // Record report in server logs or otherwise process results.
  for (const report of request.body) {
    console.log(report.body);
  }
  response.send(request.body);
}

app.post('/network-reports', (request, response) => {
  console.log(`${request.body.length} Network error reports:`);
  echoReports(request, response);
});

const listener = app.listen(process.env.PORT, () => {
  console.log(`Your app is listening on port ${listener.address().port}`);
});

Weitere Informationen