Введение
Регистрация сетевых ошибок (NEL) — это механизм сбора сетевых ошибок на стороне клиента от источника.
Он использует заголовок ответа HTTP NEL
чтобы сообщить браузеру о необходимости сбора сетевых ошибок, а затем интегрируется с API отчетов, чтобы сообщать об ошибках на сервер.
Обзор устаревшего API отчетов
Устаревший заголовок Report-To
Чтобы использовать устаревший API отчетов, вам необходимо установить HTTP-заголовок ответа Report-To
. Его значением является объект, который описывает группу конечных точек, в которую браузер сообщает об ошибках:
Report-To:
{
"max_age": 10886400,
"endpoints": [{
"url": "https://analytics.provider.com/browser-errors"
}]
}
Если URL-адрес вашей конечной точки находится в другом источнике, чем ваш сайт, конечная точка должна поддерживать предварительные запросы CORS. (например 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
).
В этом примере отправка этого заголовка ответа вместе с вашей главной страницей настраивает браузер на отправку сгенерированных браузером предупреждений в конечную точку https://analytics.provider.com/browser-errors
в течение max_age
секунд. Важно отметить, что все последующие HTTP-запросы страницы (изображений, скриптов и т. д.) игнорируются. Конфигурация настраивается во время ответа главной страницы.
Объяснение полей заголовка
Каждая конфигурация конечной точки содержит имя group
, max_age
и массив endpoints
. Вы также можете выбрать, следует ли учитывать субдомены при сообщении об ошибках, используя поле include_subdomains
.
Поле | Тип | Описание |
---|---|---|
group | нить | Необязательный. Если имя group не указано, конечной точке присваивается имя «по умолчанию». |
max_age | число | Необходимый . Неотрицательное целое число, определяющее время жизни конечной точки в секундах. Значение «0» приведет к удалению группы конечных точек из кэша отчетов пользовательского агента. |
endpoints | Массив<Объект> | Необходимый . Массив объектов JSON, определяющий фактический URL-адрес вашего сборщика отчетов. |
include_subdomains | логическое значение | Необязательный. Логическое значение, которое включает группу конечных точек для всех поддоменов хоста текущего источника. Если этот параметр опущен или имеет значение, отличное от «true», о поддоменах не сообщается конечной точке. |
Имя group
— это уникальное имя, используемое для связи строки с конечной точкой. Используйте это имя в других местах, которые интегрируются с API отчетов, для ссылки на определенную группу конечных точек.
Поле max-age
также является обязательным и указывает, как долго браузер должен использовать конечную точку и сообщать ей об ошибках.
Поле endpoints
представляет собой массив, обеспечивающий функции аварийного переключения и балансировки нагрузки. См. раздел «Отработка отказа и балансировка нагрузки» . Важно отметить, что браузер выберет только одну конечную точку , даже если в группе endpoints
указано несколько сборщиков. Если вы хотите отправить отчет на несколько серверов одновременно, вашему серверу необходимо будет пересылать отчеты.
Как браузер отправляет отчеты?
Браузер периодически группирует отчеты и отправляет их на настроенные вами конечные точки отчетов.
Для отправки отчетов браузер отправляет запрос POST
с Content-Type: application/reports+json
и телом, содержащим массив зафиксированных предупреждений/ошибок.
Когда браузер отправляет отчеты?
Отчеты доставляются из вашего приложения вне канала , то есть браузер контролирует отправку отчетов на ваши серверы.
Браузер пытается доставить отчеты в очереди в наиболее подходящее время. Это может произойти, как только они будут готовы (чтобы обеспечить своевременную обратную связь с разработчиком), но браузер также может задержать доставку, если он занят обработкой более приоритетной работы или если пользователь находится в медленной и/или перегруженной сети. время. Браузер также может установить приоритет отправки отчетов об определенном источнике в первую очередь, если пользователь является частым посетителем.
При использовании API отчетов практически не возникает проблем с производительностью (например, сетевых конфликтов с вашим приложением). Также невозможно контролировать, когда браузер отправляет отчеты в очереди.
Настройка нескольких конечных точек
Один ответ может настроить несколько конечных точек одновременно, отправив несколько заголовков 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"
}]
}
или объединив их в один 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"
}]
}
После того, как вы отправили заголовок Report-To
, браузер кэширует конечные точки в соответствии с их значениями max_age
и отправляет все эти неприятные предупреждения/ошибки консоли на ваши URL-адреса.
Аварийное переключение и балансировка нагрузки
Большую часть времени вам придется настраивать один сборщик URL-адресов для каждой группы. Однако, поскольку отчеты могут генерировать большой объем трафика, спецификация включает функции аварийного переключения и балансировки нагрузки, основанные на записи DNS SRV .
Браузер сделает все возможное, чтобы доставить отчет не более чем в одну конечную точку в группе. Endpoints can be assigned a weight
to distribute load, with each endpoint receiving a specified fraction of reporting traffic. Конечным точкам также можно назначить priority
для настройки резервных сборщиков.
Резервные сборщики пробуются только в случае сбоя загрузки на основные сборщики.
Пример . Создайте резервный сборщик по адресу 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}
]
}
Настройка журнала сетевых ошибок
Настраивать
Чтобы использовать NEL, настройте заголовок Report-To
с помощью сборщика, который использует именованную группу:
Report-To: {
...
}, {
"group": "network-errors",
"max_age": 2592000,
"endpoints": [{
"url": "https://analytics.provider.com/networkerrors"
}]
}
Затем отправьте заголовок ответа NEL
, чтобы начать сбор ошибок. Поскольку NEL поддерживает источник, вам нужно отправить заголовок только один раз. И NEL
, и Report-To
будут применяться к будущим запросам к тому же источнику и продолжат собирать ошибки в соответствии со значением max_age
, которое использовалось для настройки сборщика.
Значение заголовка должно быть объектом JSON, содержащим поля max_age
и report_to
. Используйте последнее для ссылки на имя группы вашего сборщика сетевых ошибок:
GET /index.html HTTP/1.1
NEL: {"report_to": "network-errors", "max_age": 2592000}
Подресурсы
Пример : если example.com
загружает foobar.com/cat.gif
и этот ресурс не загружается:
- Коллекционер NEL
foobar.com
уведомлен - Сборщик NEL на
example.com
не уведомлен
Эмпирическое правило заключается в том, что NEL воспроизводит журналы на стороне сервера, только что созданные на клиенте.
Поскольку example.com
не имеет доступа к журналам сервера foobar.com
, он также не имеет доступа к своим отчетам NEL.
Отладка конфигураций отчетов
If you don't see reports showing up on your server, head over to chrome://net-export/
. Эта страница полезна для проверки правильности настройки и правильной отправки отчетов.
А как насчет ReportingObserver?
ReportingObserver
— это родственный, но другой механизм отчетности. Он основан на вызовах JavaScript. Он не подходит для регистрации сетевых ошибок , поскольку сетевые ошибки невозможно перехватить с помощью JavaScript.
Пример сервера
Ниже приведен пример Node-сервера, использующего Express. Он показывает, как настроить отчеты о сетевых ошибках, и создает специальный обработчик для сбора результатов.
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}`);
});