Ghi nhật ký lỗi mạng (NEL)

Giới thiệu

Ghi nhật ký lỗi mạng (NEL) là một cơ chế thu thập lỗi mạng phía máy khách từ một nguồn gốc.

Phương thức này sử dụng tiêu đề phản hồi HTTP NEL để yêu cầu trình duyệt thu thập lỗi mạng, sau đó tích hợp với API Báo cáo để báo cáo lỗi cho máy chủ.

Tổng quan về API Báo cáo cũ

Để sử dụng API Báo cáo cũ, bạn cần đặt tiêu đề phản hồi HTTP Report-To. Giá trị của lớp này là một đối tượng mô tả nhóm điểm cuối để trình duyệt báo cáo lỗi để:

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

Nếu URL điểm cuối của bạn nằm trên một nguồn gốc khác với trang web, thì điểm cuối phải hỗ trợ các yêu cầu kiểm tra CORS. (ví dụ: 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).

Ở ví dụ này, việc gửi tiêu đề phản hồi này qua trang chính của bạn sẽ định cấu hình trình duyệt để báo cáo các cảnh báo do trình duyệt tạo đến điểm cuối https://analytics.provider.com/browser-errors trong max_age giây. Quan trọng là bạn cần lưu ý rằng tất cả các yêu cầu HTTP tiếp theo do trang đưa ra (đối với hình ảnh, tập lệnh, v.v.) sẽ bị bỏ qua. Cấu hình được thiết lập trong thời gian phản hồi của trang chính.

Giải thích về các trường tiêu đề

Mỗi cấu hình điểm cuối chứa một mảng tên group, max_ageendpoints. Bạn cũng có thể chọn xem có xem xét miền con khi báo cáo lỗi hay không bằng cách sử dụng trường include_subdomains.

Trường Loại Nội dung mô tả
group string Không bắt buộc. Nếu bạn không chỉ định tên group thì điểm cuối sẽ được đặt tên là "mặc định".
max_age number Bắt buộc. Số nguyên không âm xác định thời gian tồn tại của điểm cuối tính bằng giây. Giá trị "0" sẽ khiến nhóm điểm cuối bị xoá khỏi bộ nhớ đệm báo cáo của tác nhân người dùng.
endpoints Mảng<Object> Bắt buộc. Một mảng các đối tượng JSON chỉ định URL thực tế của trình thu thập báo cáo.
include_subdomains boolean Không bắt buộc. Một giá trị boolean bật nhóm điểm cuối cho tất cả miền con của máy chủ lưu trữ nguồn hiện tại. Nếu bị bỏ qua hoặc bất kỳ giá trị nào khác "true", miền con sẽ không được báo cáo cho điểm cuối.

Tên group là tên duy nhất dùng để liên kết một chuỗi với một điểm cuối. Sử dụng tên này ở những vị trí khác tích hợp với API Báo cáo để tham chiếu đến một nhóm điểm cuối cụ thể.

Trường max-age cũng là trường bắt buộc và chỉ định khoảng thời gian mà trình duyệt sẽ sử dụng điểm cuối và báo cáo lỗi với điểm cuối đó.

Trường endpoints là một mảng cung cấp các tính năng chuyển đổi dự phòng và cân bằng tải. Xem phần Chuyển đổi và cân bằng tải. Điều quan trọng bạn cần lưu ý là trình duyệt sẽ chỉ chọn một điểm cuối, ngay cả khi nhóm liệt kê một số trình thu thập trong endpoints. Nếu muốn gửi báo cáo đến nhiều máy chủ cùng một lúc, phần phụ trợ của bạn sẽ cần chuyển tiếp các báo cáo đó.

Trình duyệt gửi báo cáo như thế nào?

Trình duyệt định kỳ phân lô các báo cáo và gửi các báo cáo đó đến các điểm cuối báo cáo mà bạn định cấu hình.

Để gửi báo cáo, trình duyệt đưa ra yêu cầu POST với Content-Type: application/reports+json và nội dung chứa mảng cảnh báo/lỗi đã được thu thập.

Khi nào trình duyệt gửi báo cáo?

Báo cáo được phân phối ngoài băng tần từ ứng dụng của bạn, nghĩa là trình duyệt sẽ kiểm soát thời điểm báo cáo được gửi đến(các) máy chủ của bạn.

Trình duyệt sẽ cố gắng phân phối các báo cáo trong hàng đợi vào thời điểm thích hợp nhất. Việc này có thể diễn ra ngay sau khi ứng dụng sẵn sàng (để cung cấp phản hồi kịp thời cho nhà phát triển), nhưng trình duyệt cũng có thể trì hoãn việc phân phối nếu bận phải xử lý công việc có mức độ ưu tiên cao hơn hoặc nếu người dùng đang sử dụng mạng chậm và/hoặc bị nghẽn tại thời điểm đó. Trình duyệt cũng có thể ưu tiên gửi báo cáo về một nguồn gốc cụ thể trước nếu người dùng là khách truy cập thường xuyên.

Khi sử dụng API Báo cáo, bạn hầu như không gặp phải vấn đề gì về hiệu suất (ví dụ: tranh chấp mạng với ứng dụng). Ngoài ra, không có cách nào để kiểm soát thời điểm trình duyệt gửi báo cáo trong hàng đợi.

Định cấu hình nhiều điểm cuối

Một phản hồi có thể định cấu hình nhiều điểm cuối cùng lúc bằng cách gửi nhiều tiêu đề 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"
             }]
           }

hoặc bằng cách kết hợp chúng vào một tiêu đề HTTP duy nhất:

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

Sau khi bạn gửi tiêu đề Report-To, trình duyệt sẽ lưu các điểm cuối vào bộ nhớ đệm theo giá trị max_age của chúng, đồng thời gửi tất cả các cảnh báo/lỗi xấu trên bảng điều khiển đến URL của bạn.

Chuyển đổi dự phòng và cân bằng tải

Thường thì bạn sẽ định cấu hình một trình thu thập URL cho mỗi nhóm. Tuy nhiên, vì hoạt động báo cáo có thể tạo ra nhiều lưu lượng truy cập, nên thông số kỹ thuật sẽ bao gồm các tính năng chuyển đổi dự phòng và cân bằng tải lấy cảm hứng từ bản ghi SRV của DNS.

Trình duyệt sẽ cố gắng hết sức để gửi báo cáo đến tối đa một điểm cuối trong nhóm. Các điểm cuối có thể được chỉ định một weight để phân phối tải, trong đó mỗi điểm cuối nhận được một tỷ lệ lưu lượng truy cập báo cáo được chỉ định. Điểm cuối cũng có thể được gán priority để thiết lập trình thu thập dự phòng.

Trình thu thập dự phòng chỉ được thử khi không tải lên được trình thu thập chính.

Ví dụ: Tạo trình thu thập dự phòng tại 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}
             ]
           }

Thiết lập ghi nhật ký lỗi mạng

Thiết lập

Để sử dụng NEL, hãy thiết lập tiêu đề Report-To bằng bộ thu thập sử dụng nhóm được đặt tên:

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

Tiếp theo, hãy gửi tiêu đề phản hồi NEL để bắt đầu thu thập lỗi. Vì NEL chọn sử dụng một nguồn gốc, nên bạn chỉ cần gửi tiêu đề một lần. Cả NELReport-To sẽ áp dụng cho các yêu cầu trong tương lai tới cùng một nguồn gốc và sẽ tiếp tục thu thập lỗi theo giá trị max_age đã được dùng để thiết lập trình thu thập.

Giá trị tiêu đề phải là đối tượng JSON có chứa trường max_agereport_to. Hãy sử dụng URL thứ hai để tham chiếu tên nhóm của trình thu thập lỗi mạng:

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

Tài nguyên phụ

Ví dụ: Nếu example.com tải foobar.com/cat.gif nhưng tài nguyên đó không tải được:

  • Trình thu thập NEL của foobar.com đã được thông báo
  • Trình thu thập NEL của example.com không được thông báo

Quy tắc chung là NEL tái tạo nhật ký phía máy chủ, vừa được tạo trên máy khách.

example.com không xem được nhật ký máy chủ của foobar.com, nên ứng dụng này cũng không xem được các báo cáo NEL.

Gỡ lỗi cấu hình báo cáo

Nếu bạn không thấy các báo cáo xuất hiện trên máy chủ của mình, hãy truy cập vào chrome://net-export/. Trang đó rất hữu ích trong việc xác minh mọi thứ được định cấu hình chính xác và báo cáo đang được gửi đúng cách.

Còn ReportingObserver thì sao?

ReportingObserver là một cơ chế báo cáo có liên quan, nhưng khác. Mã này dựa trên các lệnh gọi JavaScript. Không phù hợp để ghi nhật ký lỗi mạng vì không thể chặn lỗi mạng qua JavaScript.

Máy chủ mẫu

Dưới đây là ví dụ về máy chủ Nút sử dụng Express. Hướng dẫn này trình bày cách định cấu hình báo cáo cho lỗi mạng và tạo một trình xử lý chuyên dụng để ghi nhận kết quả.

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

Tài liệu đọc thêm