تسجيل خطأ في الشبكة (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، سيُسمّى "default" لنقطة النهاية.
max_age الرقم مَعلمة مطلوبة. عدد صحيح غير سالب يحدد عمر نقطة النهاية بالثواني. ستؤدي القيمة "0" إلى إزالة مجموعة نقاط النهاية من ذاكرة التخزين المؤقت لإعداد تقارير وكيل المستخدم.
endpoints مصفوفة<Object> مَعلمة مطلوبة. مصفوفة من كائنات JSON التي تحدِّد عنوان URL الفعلي لأداة جمع التقارير.
include_subdomains boolean اختياريّ. قيمة منطقية تفعِّل مجموعة نقاط النهاية لجميع النطاقات الفرعية لمضيف المصدر الحالي. إذا تم حذفها أو استخدام أي شيء آخر غير "صحيح"، لا يتم إبلاغ نقطة النهاية بالنطاقات الفرعية.

الاسم 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 الخاصة بها، ويرسل جميع هذه التحذيرات/الأخطاء المزعجة إلى عناوين URL.

تجاوز الفشل وموازنة التحميل

ستضبط معظم الوقت على أداة تجميع عناوين URL واحدة لكل مجموعة. ومع ذلك، وبما أنّ إعداد التقارير قد ينتج عنه مقدار كبير من الزيارات، تتضمّن المواصفات ميزات تجاوز الأعطال وموازنة التحميل المستوحاة من سجلّ 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 هي آلية ذات صلة، ولكنّها مختلفة للإبلاغ عن المحتوى. وهو يعتمد على استدعاءات 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}`);
});

محتوى إضافي للقراءة