ثبت خطای شبکه (NEL)

مقدمه

ثبت خطای شبکه (NEL) مکانیزمی برای جمع آوری خطاهای شبکه سمت سرویس گیرنده از مبدا است.

از هدر پاسخ NEL HTTP استفاده می‌کند تا به مرورگر بگوید خطاهای شبکه را جمع‌آوری کند، سپس با Reporting API ادغام می‌شود تا خطاها را به سرور گزارش کند.

مروری بر API گزارش قدیمی

برای استفاده از گزارش API قدیمی، باید سرصفحه پاسخ Report-To HTTP را تنظیم کنید. مقدار آن یک شی است که یک گروه نقطه پایانی را برای مرورگر توصیف می کند تا خطاها را به آن گزارش کند:

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

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

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

فیلد endpoints آرایه ای برای ارائه ویژگی های Failover و متعادل کننده بار است. به بخش Failover و تعادل بار مراجعه کنید. توجه به این نکته مهم است که مرورگر فقط یک نقطه پایانی را انتخاب می کند ، حتی اگر گروه چندین جمع کننده را در 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 در حافظه پنهان ذخیره می‌کند و همه آن هشدارها/خطاهای ناخوشایند کنسول را به آدرس‌های اینترنتی شما ارسال می‌کند.

Failover و Load Balanceing

بیشتر اوقات شما در هر گروه یک جمع‌آورنده URL را پیکربندی می‌کنید. با این حال، از آنجایی که گزارش می‌تواند حجم خوبی از ترافیک ایجاد کند، این مشخصات شامل ویژگی‌های Failover و Load-balancing است که از رکورد DNS 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}`);
});

در ادامه مطلب