Logowanie błędów sieciowych (NEL)

Wprowadzenie

Rejestrowanie błędów sieci (NEL) to mechanizm zbierania błędów sieci po stronie klienta z danej domeny.

Używa nagłówka odpowiedzi HTTP NEL, aby poinformować przeglądarkę o zbieraniu błędów sieci, a następnie integruje się z interfejsem API do raportowania, aby zgłaszać błędy na serwerze.

Przegląd starszej wersji interfejsu API do raportowania

Aby korzystać z starszej wersji interfejsu API do raportowania, musisz ustawić nagłówek odpowiedzi HTTP Report-To. Jego wartością jest obiekt, który opisuje grupę punktów końcowych, do której przeglądarka ma zgłaszać błędy:

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

Jeśli adres URL punktu końcowego znajduje się w innej domenie niż witryna, punkt końcowy powinien obsługiwać żądania wstępne CORS. (np. 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).

W tym przykładzie wysłanie tego nagłówka odpowiedzi z główną stroną konfiguruje przeglądarkę tak, aby przez max_age s zgłaszała ostrzeżenia generowane przez przeglądarkę do punktu końcowego https://analytics.provider.com/browser-errors. Pamiętaj, że wszystkie kolejne żądania HTTP wysyłane przez stronę (dotyczące obrazów, skryptów itp.) są ignorowane. Konfiguracja jest ustawiana podczas odpowiedzi strony głównej.

Wyjaśnienie pól nagłówka

Każda konfiguracja punktu końcowego zawiera group nazwę, max_age i endpoints tablicę. Możesz też określić, czy podczas zgłaszania błędów mają być uwzględniane subdomeny. W tym celu użyj pola include_subdomains.

Pole Typ Opis
group ciąg znaków Opcjonalnie. Jeśli nazwa group nie zostanie określona, punkt końcowy otrzyma nazwę „default”.
max_age liczba Wymagany. Nieujemna liczba całkowita określająca czas życia punktu końcowego w sekundach. Wartość „0” spowoduje usunięcie grupy punktów końcowych z pamięci podręcznej raportowania klienta użytkownika.
endpoints Array<Object> Wymagany. Tablica obiektów JSON, które określają rzeczywisty adres URL modułu zbierającego raporty.
include_subdomains Wartość logiczna Opcjonalnie. Wartość logiczna, która włącza grupę punktów końcowych dla wszystkich subdomen hosta bieżącego pochodzenia. Jeśli ten parametr zostanie pominięty lub będzie miał wartość inną niż „true”, subdomeny nie będą raportowane do punktu końcowego.

group to unikalna nazwa używana do powiązania ciągu znaków z punktem końcowym. Używaj tej nazwy w innych miejscach, które są zintegrowane z interfejsem API do raportowania, aby odwoływać się do konkretnej grupy punktów końcowych.

Pole max-age jest też wymagane i określa, jak długo przeglądarka ma używać punktu końcowego i zgłaszać do niego błędy.

Pole endpoints to tablica, która zapewnia funkcje przełączania awaryjnego i równoważenia obciążenia. Zapoznaj się z sekcją Przełączanie awaryjne i równoważenie obciążenia. Pamiętaj, że przeglądarka wybierze tylko jeden punkt końcowy, nawet jeśli grupa zawiera kilka kolektorów w endpoints. Jeśli chcesz wysłać raport do kilku serwerów jednocześnie, backend musi przekazać raporty dalej.

Jak przeglądarka wysyła raporty?

Przeglądarka okresowo łączy raporty w pakiety i wysyła je do skonfigurowanych przez Ciebie punktów końcowych raportowania.

Aby wysłać raporty, przeglądarka wysyła POSTżądanie z Content-Type: application/reports+jsoni treścią zawierającą tablicę przechwyconych ostrzeżeń lub błędów.

Kiedy przeglądarka wysyła raporty?

Raporty są dostarczane poza pasmem aplikacji, co oznacza, że przeglądarka kontroluje, kiedy raporty są wysyłane na Twoje serwery.

Przeglądarka próbuje dostarczyć raporty w najbardziej odpowiednim momencie. Może to nastąpić, gdy tylko będzie to możliwe (aby przekazać deweloperowi odpowiednie informacje zwrotne), ale przeglądarka może też opóźnić dostarczenie, jeśli jest zajęta przetwarzaniem zadań o wyższym priorytecie lub jeśli użytkownik korzysta w danym momencie z wolnej lub przeciążonej sieci. Przeglądarka może też w pierwszej kolejności wysyłać raporty dotyczące konkretnej domeny, jeśli użytkownik często ją odwiedza.

Korzystanie z interfejsu API do raportowania nie powoduje prawie żadnych problemów z wydajnością (np. konfliktów sieciowych z aplikacją). Nie można też kontrolować, kiedy przeglądarka wysyła raporty w kolejce.

Konfigurowanie wielu punktów końcowych

Jedna odpowiedź może skonfigurować kilka punktów końcowych jednocześnie, wysyłając wiele nagłówków Report-To:

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"
             }]
           }

lub połączyć je w jeden nagłówek HTTP:

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"
             }]
           }

Gdy wyślesz nagłówek Report-To, przeglądarka zapisze w pamięci podręcznej punkty końcowe zgodnie z ich wartościami max_age i wyśle wszystkie te nieprzyjemne ostrzeżenia/błędy konsoli do Twoich adresów URL.

Przełączanie awaryjne i równoważenie obciążenia

Zwykle konfiguruje się 1 kolektor adresów URL na grupę. Raportowanie może jednak generować duży ruch, dlatego specyfikacja zawiera funkcje przełączania awaryjnego i równoważenia obciążenia inspirowane rekordem SRV DNS.

Przeglądarka dołoży wszelkich starań, aby dostarczyć raport do co najwyżej jednego punktu końcowego w grupie. Punktom końcowym można przypisać weight, aby rozłożyć obciążenie. Każdy punkt końcowy będzie otrzymywać określoną część ruchu związanego z raportowaniem. Punktom końcowym można też przypisać priority, aby skonfigurować kolektory rezerwowe.

Kolektory rezerwowe są używane tylko wtedy, gdy przesyłanie do kolektorów podstawowych nie powiedzie się.

Przykład: utwórz kolektor zastępczy w lokalizacji https://backup.com/reports:

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

Konfigurowanie rejestrowania błędów sieci

Konfiguracja

Aby używać NEL, skonfiguruj nagłówek Report-To z kolektorem, który używa nazwanej grupy:

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

Następnie wyślij NEL nagłówek odpowiedzi, aby rozpocząć zbieranie błędów. Ponieważ NEL jest opcjonalny dla pochodzenia, wystarczy wysłać nagłówek tylko raz. Zarówno NEL, jak i Report-To będą stosowane do przyszłych żądań do tego samego pochodzenia i będą nadal zbierać błędy zgodnie z wartością max_age, która została użyta do skonfigurowania modułu zbierającego.

Wartość nagłówka powinna być obiektem JSON zawierającym pola max_agereport_to. Użyj tego drugiego, aby odwołać się do nazwy grupy kolektora błędów sieci:

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

Zasoby podrzędne

Przykład: jeśli example.com wczytuje foobar.com/cat.gif i nie uda się wczytać tego zasobu:

  • Kolektor NEL użytkownika foobar.com otrzyma powiadomienie
  • Kolektor NEL example.com nie otrzymuje powiadomienia.

Ogólna zasada jest taka, że NEL odtwarza logi po stronie serwera, tylko generowane po stronie klienta.

example.com nie ma wglądu w logi serwera foobar.com, więc nie ma też wglądu w jego raporty NEL.

Debugowanie konfiguracji raportów

Jeśli nie widzisz raportów na serwerze, przejdź na stronę chrome://net-export/. Ta strona jest przydatna do sprawdzania, czy wszystko jest prawidłowo skonfigurowane, a raporty są wysyłane prawidłowo.

A co z interfejsem ReportingObserver?

ReportingObserver to powiązany, ale inny mechanizm raportowania. Jest on obliczany na podstawie wywołań JavaScript. Nie nadaje się do rejestrowania błędów sieci, ponieważ nie można ich przechwytywać za pomocą JavaScriptu.

Przykładowy serwer

Poniżej znajdziesz przykład serwera Node, który korzysta z Express. Pokazuje, jak skonfigurować raportowanie błędów sieciowych, i tworzy dedykowany moduł obsługi do przechwytywania wyniku.

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

Więcej informacji