Logowanie błędów sieciowych (NEL)

Wprowadzenie

Logowanie błędów sieci (NEL) to mechanizm służący do zbieranie błędów sieci po stronie klienta z punktu początkowego.

Korzysta ono z nagłówka odpowiedzi HTTP NEL, aby poinformować przeglądarkę, że ma zbierać błędy sieci, a potem integruje się z interfejsem API do raportowania, by zgłaszać te błędy do serwera.

Omówienie starszej wersji interfejsu API do raportowania

Aby korzystać ze starszej wersji interfejsu API do raportowania, musisz ustawić nagłówek odpowiedzi HTTP Report-To. To Wartość to obiekt opisujący grupę punktów końcowych przeglądarki aby zgłosić błędy:

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

Jeśli URL punktu końcowego znajduje się w innym źródle niż Twoja witryna, parametr 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 ze stroną główną konfiguruje przeglądarkę, aby zgłaszała ostrzeżenia generowane przez przeglądarkę do punktu końcowego https://analytics.provider.com/browser-errors na max_age s. Warto zauważyć, że wszystkie kolejne żądania HTTP wysyłane przez stronę (w przypadku obrazów, skryptów itp.) są ignorowane. Konfiguracja jest konfigurowana w odpowiedź na stronie głównej.

Objaśnienie pól nagłówka

Każda konfiguracja punktu końcowego zawiera nazwę group, max_age i endpoints . Możesz też wybrać, czy przy raportowaniu chcesz uwzględnić subdomeny za pomocą 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, która określa czas trwania 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 Tablica<Object> Wymagany. Tablica obiektów JSON, które określają rzeczywisty adres URL kolektora raportów.
include_subdomains wartość logiczna Opcjonalnie: Wartość logiczna, która włącza grupę punktów końcowych we wszystkich subdomenach hosta bieżącego punktu początkowego. Jeśli zostanie pominięty lub ma wartość inną niż „true”, subdomeny nie są raportowane do punktu końcowego.

Nazwa group to unikalna nazwa używana do powiązania ciągu z i punktu końcowego. Użyj tej nazwy w innych miejscach zintegrowanych za pomocą interfejsu API do raportowania, aby odwołać się do konkretnej grupy punktów końcowych.

Pole max-age jest również wymagane i określa, przeglądarka powinna używać punktu końcowego i zgłaszać mu błędy.

Pole endpoints to tablica do przełączania awaryjnego i równoważenia obciążenia funkcje zabezpieczeń. Więcej informacji znajdziesz w sekcji Przełączanie awaryjne i równoważenie obciążenia. Jest pamiętaj, że przeglądarka wybiera tylko jeden punkt końcowy, nawet jeśli grupa zawiera kilka kolektorów w endpoints. Jeśli chcesz wysłać do kilku serwerów jednocześnie, backend będzie musiał przekazać raportów.

W jaki sposób przeglądarka wysyła raporty?

Przeglądarka okresowo grupuje raporty i wysyła je do raportu skonfigurowanych przez Ciebie punktach końcowych.

Aby wysyłać raporty, przeglądarka wysyła POST poproś o Content-Type: application/reports+json i treści zawierająca tablicę przechwyconych ostrzeżeń/błędów.

Kiedy przeglądarka wysyła raporty?

Raporty są dostarczane poza zakresem z aplikacji, czyli przeglądarka pozwala kontrolować wysyłanie raportów na Twoje serwery.

Przeglądarka próbuje dostarczać raporty w kolejce w najdogodniejszym czasie. Można to zrobić od razu, gdy będą gotowe (aby zapewnić deweloperowi), ale przeglądarka może opóźnić dostarczenie zajęty jest przetwarzanie zadań o wyższym priorytecie lub jeśli użytkownik działa wolno lub przeciążona sieć. Przeglądarka może też priorytetowo traktować wysyłanie jeśli użytkownik jest często odwiedzającym witrynę, najpierw przekazuje informacje o danym miejscu pochodzenia.

Nie ma żadnych problemów z wydajnością lub nie ma ich wcale (np. rywalizacji sieci z aplikacją) podczas korzystania z interfejsu API do raportowania. Jest a także nie ma możliwości kontrolowania, kiedy przeglądarka wysyła raporty w kolejce.

Konfigurowanie wielu punktów końcowych

Pojedyncza 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 łącząc 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 punkty końcowe w pamięci podręcznej zgodnie z wartościami max_age i wysyła wszystkie te paskudne konsole ostrzeżenia lub błędy w URL-ach.

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

Najczęściej będziesz konfigurować po jednym kolektorze adresów URL dla każdej grupy. Pamiętaj jednak: Ponieważ raportowanie może generować duży ruch, specyfikacja obejmuje przełączanie awaryjne i równoważenia obciążenia inspirowanego systemem DNS Rekord SRV.

Przeglądarka dołoży wszelkich starań, aby przesłać raport do co najmniej jednego punktu końcowego w danej grupie. Punktom końcowym można przypisać weight, aby rozłożyć obciążenie, z każdym z nich punktu końcowego odbierającego określoną część ruchu objętego raportowaniem. Punkty końcowe mają też przypisaną zasadę priority do skonfigurowania zastępczych kolektorów.

Kolektory zastępcze są używane tylko w przypadku niepowodzenia przesyłania do kolektorów głównych.

Przykład: utwórz zastępczy kolektor w środowisku 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}
             ]
           }

Konfiguruję logowanie błędów sieci

Konfiguracja

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

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

Następnie wyślij nagłówek odpowiedzi NEL, aby zacząć zbierać błędy. Od NEL jest uwzględniany dla źródła, wystarczy wysłać nagłówek tylko raz. Zarówno NEL, jak i Pole Report-To będzie stosowane w przyszłych żądaniach dotyczących tego samego punktu początkowego i będzie kontynuowane do zbierania błędów zgodnie z wartością max_age użytej do skonfigurowania na kolektorze.

Wartość nagłówka powinna być obiektem JSON zawierającym max_age oraz report_to. Użyj tego drugiego, aby odwołać się do nazwy grupy swojego kolektor 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 wczyta plik foobar.com/cat.gif i ten zasób ulegnie awarii w celu załadowania:

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

zgodnie z ogólną zasadą NEL odtwarza logi po stronie serwera, wygenerowane do klienta.

example.com nie ma wglądu w serwer serwera foobar.com nie ma też wglądu w raporty NEL.

Konfiguracje raportu debugowania

Jeśli nie widzisz raportów na swoim serwerze, wejdź na chrome://net-export/ Ta strona jest przydatna dla: sprawdzanie, czy wszystko jest skonfigurowane prawidłowo, i wysyłanie raportów. jak ją wyświetlić.

A co z funkcją ReportingObserver?

ReportingObserver to powiązany, ale inny mechanizm raportowania. który opiera się na wywołaniach JavaScriptu. Nie nadaje się do rejestrowania błędów sieci, ponieważ nie mogą zostać przechwycone za pomocą JavaScriptu.

Przykładowy serwer

Poniżej znajdziesz przykładowy serwer węzłów, który używa Express. Pokazuje on, jak skonfigurować raportowanie błędów sieci, oraz tworzy specjalny moduł obsługi do rejestrowania wyników.

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