การบันทึกข้อผิดพลาดเกี่ยวกับเครือข่าย (NEL)

บทนำ

การบันทึกข้อผิดพลาดเกี่ยวกับเครือข่าย (NEL) เป็นกลไกสำหรับ รวบรวมข้อผิดพลาดเกี่ยวกับเครือข่ายฝั่งไคลเอ็นต์จากต้นทาง

โดยจะใช้ส่วนหัวการตอบกลับ HTTP NEL เพื่อบอกเบราว์เซอร์ให้รวบรวมข้อผิดพลาดของเครือข่าย แล้วผสานรวมกับ Reporting API เพื่อรายงานข้อผิดพลาดไปยังเซิร์ฟเวอร์

ภาพรวมของ Reporting API เดิม

หากต้องการใช้ Reporting 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" จะทำให้กลุ่มปลายทางถูกนำออกจากแคชการรายงานของ User Agent
endpoints อาร์เรย์<ออบเจ็กต์> ต้องระบุ อาร์เรย์ของออบเจ็กต์ JSON ที่ระบุ URL จริงของเครื่องมือรวบรวมรายงาน
include_subdomains boolean ไม่บังคับ บูลีนที่เปิดใช้กลุ่มปลายทางสำหรับโดเมนย่อยทั้งหมดของโฮสต์ของต้นทางปัจจุบัน หากละเว้นหรือไม่ใช่ "จริง" ระบบจะไม่รายงานโดเมนย่อยไปยังปลายทาง

ชื่อ group คือชื่อที่ไม่ซ้ำกันซึ่งใช้ในการเชื่อมโยงสตริง ปลายทาง ใช้ชื่อนี้ในที่อื่นๆ ที่ผสานรวม ด้วย Reporting API เพื่ออ้างอิงถึงกลุ่มปลายทางที่เฉพาะเจาะจง

นอกจากนี้ ต้องกรอกข้อมูลในช่อง max-age และระบุวิธีการ เบราว์เซอร์ควรใช้ปลายทางและรายงานข้อผิดพลาดไปยังปลายทางนั้น

ฟิลด์ endpoints เป็นอาร์เรย์สำหรับเฟลโอเวอร์และการจัดสรรภาระงาน ใหม่ๆ โปรดดูส่วนเกี่ยวกับเฟลโอเวอร์และการจัดสรรภาระงาน ตอนนี้ โปรดทราบว่าเบราว์เซอร์จะเลือกเพียงปลายทางเดียว หากกลุ่มแสดงผู้รวบรวมหลายคนใน endpoints หากคุณต้องการส่ง ไปยังเซิร์ฟเวอร์หลายเครื่องพร้อมกัน แบ็กเอนด์ของคุณจะต้องส่งต่อ รายงาน

เบราว์เซอร์ส่งรายงานอย่างไร

เบราว์เซอร์จะจัดกลุ่มรายงานเป็นระยะๆ แล้วส่งให้การรายงาน ปลายทางที่คุณกำหนดค่า

โดยเบราว์เซอร์จะออก POST เพื่อส่งรายงาน ส่งคำขอด้วย Content-Type: application/reports+json และเนื้อความที่มีอาร์เรย์ของ คำเตือน/ข้อผิดพลาดที่บันทึก

เบราว์เซอร์จะส่งรายงานเมื่อใด

รายงานจะแสดงนอกขอบเขตจากแอปของคุณ ซึ่งหมายถึงเบราว์เซอร์ ควบคุมเวลาในการส่งรายงานไปยังเซิร์ฟเวอร์ของคุณ

เบราว์เซอร์จะพยายาม ส่งรายงานในคิวในช่วงเวลาที่เหมาะสม ซึ่งอาจพร้อมใช้งานทันทีที่พร้อม (เพื่อให้ นักพัฒนาซอฟต์แวร์อย่างทันท่วงที) แต่เบราว์เซอร์ยังอาจชะลอการส่งหาก ไม่ว่างเนื่องจากกำลังประมวลผลข้อมูลที่มีลำดับความสำคัญสูงกว่า หรือหากผู้ใช้อยู่ใน Chromebook และ/หรือ ในช่วงนั้นที่มีการจราจรคับคั่ง เบราว์เซอร์ยังอาจให้ความสำคัญกับการส่ง รายงานเกี่ยวกับต้นทางที่เจาะจงก่อน หากผู้ใช้เข้าชมบ่อย

มีข้อกังวลด้านประสิทธิภาพเพียงเล็กน้อยหรือไม่มีเลย (เช่น การช่วงชิงเครือข่ายกับแอปของคุณ) เมื่อใช้ Reporting 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 1 รายการต่อกลุ่ม อย่างไรก็ตาม เนื่องจากการรายงานสามารถสร้างการเข้าชมที่ดี ข้อกำหนดจึงมีกรณีเฟลโอเวอร์ รวมถึงฟีเจอร์การจัดสรรภาระงานที่ได้รับแรงบันดาลใจมาจาก DNS ระเบียน SRV

เบราว์เซอร์จะพยายามอย่างเต็มที่เพื่อส่งรายงานไปยังปลายทางมากที่สุด 1 รายการ ในกลุ่ม สามารถกำหนด weight ปลายทางเพื่อกระจายภาระงาน โดยที่แต่ละปลายทาง ปลายทางที่ได้รับสัดส่วนของการรับส่งข้อมูลการรายงานที่ระบุ ปลายทางสามารถ จะได้รับ 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 ของบันทึกได้

การแก้ไขข้อบกพร่องของการกำหนดค่ารายงาน

หากคุณไม่เห็นรายงานแสดงในเซิร์ฟเวอร์ของคุณ ให้ไปยัง chrome://net-export/ หน้าเว็บนี้มีประโยชน์สำหรับ ยืนยันว่ามีการกำหนดค่าสิ่งต่างๆ อย่างถูกต้องและกำลังส่งรายงาน อย่างเหมาะสม

แล้ว ReportingObserver ล่ะ

ReportingObserver เป็นกลไกการรายงานที่เกี่ยวข้องแต่แตกต่างกัน โดยอิงตามการเรียก JavaScript ไม่เหมาะกับการบันทึกข้อผิดพลาดเกี่ยวกับเครือข่าย เพราะเป็นข้อผิดพลาดเกี่ยวกับเครือข่าย ไม่สามารถดักจับผ่าน JavaScript ได้

เซิร์ฟเวอร์ตัวอย่าง

ด้านล่างคือตัวอย่างเซิร์ฟเวอร์โหนดที่ใช้ 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}`);
});

อ่านเพิ่มเติม