مقدمة
تسجيل أخطاء الشبكة (NEL) هو آلية لجمع أخطاء الشبكة من جهة العميل من مصدر معيّن.
تستخدم هذه السياسة عنوان استجابة HTTP NEL لإخبار المتصفّح بجمع أخطاء الشبكة، ثم يتم دمجها مع Reporting API لإرسال الأخطاء إلى خادم.
نظرة عامة على Reporting API القديمة
عنوان Report-To القديم
لاستخدام 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 |
Array<Object> | مَعلمة مطلوبة. مصفوفة من عناصر JSON تحدّد عنوان URL الفعلي لجامع التقارير. |
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، ويرسل كل تحذيرات/أخطاء وحدة التحكّم المزعجة هذه إلى عناوين 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.
مثال على الخادم
في ما يلي مثال على خادم 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}`);
});