Logowanie błędów sieciowych (NEL)

Logowanie błędów sieciowych (NEL) to mechanizm zbierania błędów sieciowych po stronie klienta z źródła.

Używa nagłówka odpowiedzi HTTP NEL, aby poinformować przeglądarkę o zbieraniu błędów sieciowych, a potem integruje się z interfejsem Reporting API, aby zgłaszać błędy na serwer.

Omówienie starszej wersji interfejsu Reporting API

Aby korzystać ze starszej wersji interfejsu API do raportowania, musisz ustawić nagłówek odpowiedzi HTTP Report-To. Jego wartość to obiekt opisujący 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ż Twoja 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ą powoduje, że przeglądarka przez max_age s zgłasza do punktu końcowego https://analytics.provider.com/browser-errors ostrzeżenia generowane przez przeglądarkę. Pamiętaj, że wszystkie kolejne żądania HTTP wysyłane przez stronę (w przypadku obrazów, skryptów itp.) są ignorowane. Konfiguracja jest konfigurowana podczas odpowiedzi na stronę główną.

Objaśnienie pól nagłówka

Każda konfiguracja punktu końcowego zawiera tablicę group, max_age i endpoints. Korzystając z pola include_subdomains, możesz też określić, czy przy zgłaszaniu błędów mają być uwzględniane subdomeny.

Pole Typ Opis
group ciąg znaków Opcjonalnie: Jeśli nazwa group nie jest określona, punkt końcowy otrzymuje nazwę „default”.
max_age liczba Wymagany. Nieujemna liczba całkowita określająca czas trwania punktu końcowego w sekundach. Wartość „0” spowoduje usunięcie grupy punktów końcowych z pamięci podręcznej raportowania przeglądarki użytkownika.
endpoints Tablica<Object> Wymagany. Tablica obiektów JSON, która określa rzeczywisty adres URL zbieracza raportów.
include_subdomains wartość logiczna Opcjonalnie: Wartość logiczna, która włącza grupę punktów końcowych dla wszystkich subdomen hosta bieżącego źródła. Jeśli ten parametr jest pominięty lub ma wartość inną niż „prawda”, podsubdomeny nie są raportowane do punktu końcowego.

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

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

Pole endpoints to tablica, która zapewnia funkcje przełączania awaryjnego i równoważenia obciążenia. Zobacz sekcję Przełączanie awaryjne i równoważenie obciążenia. Pamiętaj, że przeglądarka wybierze tylko 1 punkt końcowy, nawet jeśli grupa zawiera w sekcji endpoints kilka elementów kolekcjonera. Jeśli chcesz wysłać raport na kilka serwerów jednocześnie, Twój backend musi to zrobić.

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

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

Aby wysłać raporty, przeglądarka wysyła żądanie POST z parametrem Content-Type: application/reports+json i zbiorem zarejestrowanych ostrzeżeń/błędów.

Kiedy przeglądarka wysyła raporty?

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

Przeglądarka próbuje dostarczyć raporty oczekujące w kolejce w najdogodniejszym momencie. Przeglądarka może też opóźnić wyświetlenie, gdy tylko będzie gotowe (aby szybko przekazać informacje deweloperowi), ale może też opóźnić dostarczanie, jeśli jej przetwarzanie jest nadmiernie zajęte lub jeśli użytkownik korzysta w danym czasie z wolnej lub zatłoczonej sieci. Jeśli użytkownik często odwiedza daną witrynę, przeglądarka może też nadać priorytet wysyłaniu raportów dotyczących konkretnego źródła.

Podczas korzystania z interfejsu Reporting API nie ma prawie żadnych problemów ze skutecznością (np. konflikty sieciowe z Twoją aplikacją). Nie można też kontrolować, kiedy przeglądarka wysyła raporty z kolejki.

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

Po wysłaniu nagłówka Report-To przeglądarka umieszcza w pamięci podręcznej punkty końcowe zgodnie z ich wartościami max_age i wysyła wszystkie te nieprzyjemne ostrzeżenia/błędy konsoli do Twoich adresów URL.

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

W większości przypadków skonfigurujesz 1 kolektora adresów URL na grupę. Ponieważ jednak raportowanie może generować sporo ruchu, specyfikacja obejmuje funkcje failover i równoważenia obciążenia inspirowane przez rekord SRV w DNS.

Przeglądarka zrobi, co w jej mocy, aby przesłać raport do maksymalnie 1 usługodawcy w grupie. Do punktów końcowych można przypisać weight, aby rozłożyć obciążenie, przy czym każdy punkt końcowy otrzymuje określoną część ruchu objętego raportowaniem. Punktom końcowym można też przypisać priority, aby skonfigurować zbieracze zapasowe.

Kolektory zapasowe są używane tylko wtedy, gdy przesyłanie do kolektorów głównych zakończy się niepowodzeniem.

Przykład: utwórz kolekcjonera zastępczego na stronie 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 za pomocą kolektora, który korzysta z nazywanej 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. Ponieważ NEL jest opcjonalny dla źródła, nagłówek wystarczy wysłać tylko raz. Zarówno NEL, jak i Report-To będą miały zastosowanie do przyszłych żądań do tego samego pochodzenia i nadal będą zbierać błędy zgodnie z wartością max_age użytą do skonfigurowania kolektora.

Wartość nagłówka powinna być obiektem JSON zawierającym pole max_agereport_to. Używaj tego ostatniego, aby odwoływać 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, a ten zasób nie wczytuje się:

  • Powiadomienie NEL uczestnika foobar.com
  • Kolektor NEL użytkownika example.com nie otrzymuje powiadomienia

Zasada jest taka, że NEL odtwarza logi po stronie serwera, które są generowane na kliencie.

Ponieważ example.com nie ma dostępu do plików dziennika serwera foobar.com, nie ma też dostępu do raportów NEL.

Debugowanie konfiguracji raportów

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

A ReportingObserver?

ReportingObserver to powiązany, ale inny mechanizm raportowania. Jest ono obliczane na podstawie wywołań kodu JavaScript. Nie nadaje się do rejestrowania błędów sieciowych, ponieważ błędów sieci nie można przechwycić 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, i tworzy dedykowany 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