רישום שגיאות ברשת (NEL)

מבוא

רישום שגיאות בחיבור לרשת (NEL) הוא מנגנון לאיסוף שגיאות בחיבור לרשת בצד הלקוח ממקור מסוים.

הוא משתמש בכותרת תגובת ה-HTTP NEL כדי להורות לדפדפן לאסוף שגיאות בחיבור לרשת, ואז משתלב עם Reporting API כדי לדווח על השגיאות לשרת.

סקירה כללית על Reporting API הקודם

כדי להשתמש ב-Reporting API הקודם, צריך להגדיר כותרת תגובת HTTP ‏Report-To. הערך שלו הוא אובייקט שמתאר קבוצה של נקודות קצה (endpoint) שהדפדפן יכול לדווח להן על שגיאות:

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, נקודת הקצה מקבלת את השם default.
max_age number נדרש. מספר שלם חיובי שמגדיר את משך החיים של נקודת הקצה בשניות. הערך "0" יגרום להסרת קבוצת נקודות הקצה מהמטמון של דיווח סוכן המשתמש.
endpoints מערך<Object> נדרש. מערך של אובייקטים מסוג JSON שמציינים את כתובת ה-URL בפועל של אוסף הדוחות.
include_subdomains בוליאני אופציונלי. ערך בוליאני שמפעיל את קבוצת נקודות הקצה לכל תת-הדומיינים של המארח של המקור הנוכחי. אם משמיטים את המאפיין או מזינים ערך אחר, תת-הדומיינים לא מדווחים לנקודת הקצה.

השם group הוא שם ייחודי שמשמש לשיוך מחרוזת לנקודת קצה. אפשר להשתמש בשם הזה במקומות אחרים שמשולבים עם Reporting API כדי להתייחס לקבוצת נקודות קצה ספציפית.

השדה max-age הוא גם שדה חובה, והוא מציין כמה זמן הדפדפן צריך להשתמש בנקודת הקצה ולדווח לה על שגיאות.

השדה endpoints הוא מערך שמספק תכונות של יתירות כשל ואיזון עומסים. אפשר לעיין בקטע בנושא יתירות כשל ואיזון עומסים. חשוב לציין שהדפדפן יבחר רק נקודת קצה אחת, גם אם הרשימה המשותפת כוללת כמה אוספים ב-endpoints. אם אתם רוצים לשלוח דוח לכמה שרתים בו-זמנית, ה-backend שלכם יצטרך להעביר את הדוחות.

איך הדפדפן שולח דוחות?

הדפדפן אוסף דוחות מדי פעם ושולח אותם לנקודות הקצה לדיווח שהגדרתם.

כדי לשלוח דוחות, הדפדפן שולח בקשת POST עם Content-Type: application/reports+json וגוף שמכיל את מערך האזהרות או השגיאות שתועדו.

מתי הדפדפן שולח דוחות?

הדוחות נשלחים מחוץ לאפליקציה, כלומר הדפדפן קובע מתי הדוחות נשלחים לשרתים.

הדפדפן מנסה לשלוח את הדוחות שבתור בזמן המתאים ביותר. הדפדפן יכול לשלוח את הדוחות ברגע שהם מוכנים (כדי לספק משוב למפתח בזמן אמת), אבל הוא יכול גם לעכב את השליחה אם הוא עסוק בעיבוד של משימות בעדיפות גבוהה יותר, או אם המשתמש מחובר לרשת איטית או עמוסה באותו זמן. יכול להיות שהדפדפן גם יתעדף שליחת דוחות על מקור מסוים קודם, אם המשתמש מבקר בו לעיתים קרובות.

כשמשתמשים ב-Reporting API, כמעט שאין חשש לפגיעה בביצועים (למשל, תחרות על רוחב הפס של הרשת עם האפליקציה). בנוסף, אין דרך לקבוע מתי הדפדפן ישלח דוחות שנמצאים בתור.

הגדרת כמה נקודות קצה (endpoint)

תגובה אחת יכולה להגדיר כמה נקודות קצה בבת אחת על ידי שליחת כמה כותרות 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 אחד לכל קבוצה. עם זאת, מכיוון שהדיווח יכול ליצור תנועה רבה, המפרט כולל תכונות של יתירות כשל ואיזון עומסים בהשראת רשומת SRV של DNS.

הדפדפן ינסה לשלוח דוח לנקודת קצה אחת לכל היותר בקבוצה. אפשר להקצות לנקודות קצה 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
  • מערכת איסוף הנתונים של example.com לדיווח על שגיאות ברשת (NEL) לא מקבלת התראות

כלל האצבע הוא ש-NEL משחזר יומנים בצד השרת, שנוצרו אצל הלקוח.

מכיוון של-example.com אין גישה ליומני השרת של foobar.com, אין לו גם גישה לדוחות ה-NEL שלו.

הגדרות של דוחות ניפוי באגים

אם לא מופיעים דוחות בשרת, צריך לעבור אל chrome://net-export/. הדף הזה שימושי כדי לוודא שהדברים מוגדרים כמו שצריך ושהדוחות נשלחים בצורה תקינה.

מה לגבי ReportingObserver?

‫ReportingObserver הוא מנגנון דיווח קשור, אבל שונה. הוא מבוסס על קריאות ל-JavaScript. הוא לא מתאים לרישום שגיאות בחיבור לרשת, כי אי אפשר ליירט שגיאות בחיבור לרשת באמצעות JavaScript.

שרת לדוגמה

בהמשך מוצגת דוגמה לשרת Node שמשתמש ב-Express. הוא מראה איך להגדיר דיווח על שגיאות בחיבור לרשת, ויוצר handler ייעודי כדי לתעד את התוצאה.

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

קריאה נוספת