ثبت خطای شبکه (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"
    }]
}

اگر نشانی وب نقطه پایانی شما در مبدأ متفاوتی نسبت به سایت شما قرار دارد، نقطه پایانی باید از درخواست‌های پیش‌پرواز 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 شماره الزامی. عدد صحیح غیرمنفی که طول عمر نقطه پایانی را برحسب ثانیه تعریف می‌کند. مقدار «۰» باعث می‌شود گروه نقطه پایانی از حافظه نهان گزارش‌دهی نماینده کاربر برداشته شود.
endpoints Array<Object> الزامی. آرایه‌ای از اشیاء JSON که نشانی وب واقعی جمع‌آوری‌کننده گزارش شما را مشخص می‌کند.
include_subdomains بولی اختیاری. یک مقدار بولی که گروه نقطه پایانی را برای همه زیردامنه‌های میزبان مبدأ فعلی فعال می‌کند. اگر حذف شود یا هر چیزی غیراز «true» باشد، زیردامنه‌ها به نقطه پایانی گزارش نمی‌شوند.

نام group نامی یکتا است که برای مرتبط کردن رشته با نقطه پایانی استفاده می‌شود. از این نام در جاهای دیگری که با Reporting API ادغام می‌شوند استفاده کنید تا به گروه نقطه پایانی خاصی ارجاع دهید.

فیلد max-age نیز الزامی است و مشخص می‌کند که مرورگر چه مدت باید از نقطه پایانی استفاده کند و خطاها را به آن گزارش دهد.

فیلد endpoints آرایه‌ای برای ارائه ویژگی‌های توازن بار و انتقال خودکار به سیستم جایگزین است. بخش مربوط به توازن بار و انتقال خودکار به سیستم جایگزین را ببینید. باید توجه داشته باشید که مرورگر فقط یک نقطه پایانی را انتخاب می‌کند، حتی اگر گروه چندین جمع‌آورنده را در endpoints فهرست کند. اگر می‌خواهید گزارشی را به‌طور هم‌زمان به چند سرور ارسال کنید، باطن شما باید گزارش‌ها را بازارسال کند.

مرورگر چگونه گزارش‌ها را ارسال می‌کند؟

مرورگر به‌طور دوره‌ای گزارش‌ها را دسته‌بندی می‌کند و آن‌ها را به نقاط پایانی گزارش‌دهی که پیکربندی کرده‌اید ارسال می‌کند.

برای ارسال گزارش‌ها، مرورگر درخواست POST با Content-Type: application/reports+json و بدنه‌ای حاوی آرایه هشدارها/خطاهای ضبط‌شده صادر می‌کند.

مرورگر چه زمانی گزارش‌ها را ارسال می‌کند؟

گزارش‌ها خارج از باند از برنامه شما ارسال می‌شوند، یعنی مرورگر کنترل می‌کند که گزارش‌ها چه زمانی به سرور(های) شما ارسال شوند.

مرورگر تلاش می‌کند گزارش‌های صف‌بندی‌شده را در مناسب‌ترین زمان ارسال کند. این کار ممکن است به‌محض آماده شدن گزارش‌ها انجام شود (تا بازخورد به‌موقع به توسعه‌دهنده ارائه شود)، اما اگر مرورگر مشغول پردازش کارهای با اولویت بالاتر باشد یا اگر کاربر در آن زمان در شبکه‌ای کند و/یا شلوغ باشد، مرورگر می‌تواند ارسال را به تأخیر بیندازد. اگر کاربر بازدیدکننده مکرر باشد، ممکن است مرورگر ارسال گزارش‌های مربوط به مبدأ خاصی را نیز در اولویت قرار دهد.

هنگام استفاده از 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 آن‌ها ذخیره می‌کند و همه آن هشدارها/خطاهای کنسول را به نشانی‌های وب شما ارسال می‌کند.

انتقال خودکار به سیستم پشتیبان و توازن بار

در بیشتر مواقع، برای هر گروه یک جمع‌آورنده نشانی وب پیکربندی خواهید کرد. اما ازآنجایی‌که گزارش‌دهی می‌تواند ترافیک زیادی ایجاد کند، این مشخصات شامل ویژگی‌های انتقال خودکار به سیستم جایگزین و توازن بار است که از سابقه SRV ساناد الهام گرفته شده است.

مرورگر تمام تلاش خود را می‌کند تا گزارش را به حداکثر یک نقطه پایانی در گروه ارسال کند. می‌توان به نقاط پایانی 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 سازوکار گزارش‌دهی مرتبط اما متفاوتی است. این روش براساس فراخوانی‌های جاوا اسکریپت است. برای ثبت خطای شبکه مناسب نیست، زیرا خطاهای شبکه نمی‌توانند ازطریق جاوا اسکریپت رهگیری شوند.

سرور نمونه

در زیر نمونه‌ای از سرور 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}`);
});

مطالعه بیشتر