مقدمة
تسجيل أخطاء الشبكة (NEL) هو آلية لجمع أخطاء الشبكة من جهة العميل من مصدر.
ويستخدم عنوان استجابة HTTP NEL
لإعلام المتصفّح بجمع أخطاء الشبكة، ثم يتم دمجه مع Reporting API للإبلاغ عن الأخطاء إلى الخادم.
نظرة عامة على Reporting API القديمة
عنوان Report-To
القديم
لاستخدام Reporting API القديمة، عليك ضبط عنوان استجابة Report-To
HTTP. وقيمتها هي عنصر يصف مجموعة نقاط نهاية للمتصفّح
لإبلاغ عن الأخطاء إلى:
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 |
صفيف<عنصر> | مَعلمة مطلوبة. مصفوفة من عناصر JSON تحدّد عنوان URL الفعلي لمجموعة جمع التقارير |
include_subdomains |
قيمة منطقية | اختيارية: قيمة منطقية تفعّل مجموعة نقاط النهاية لجميع النطاقات الفرعية لمضيف المصدر الحالي. في حال حذف هذه السمة أو ضبطها على أي قيمة غير "صحيح"، لن يتم الإبلاغ عن النطاقات الفرعية في نقطة النهاية. |
اسم group
هو اسم فريد يُستخدَم لربط سلسلة بنقطة نهاية. استخدِم هذا الاسم في مواضع أخرى تندمج
مع Reporting API للإشارة إلى مجموعة نقاط نهاية معيّنة.
الحقل max-age
مطلوب أيضًا ويحدّد المدّة التي يجب أن يستخدِم فيها المتصفّح نقطة النهاية ويبلِغها بالأخطاء.
الحقل endpoints
هو صفيف لتوفير ميزتَي التبديل في حال انقطاع الخدمة وموازنة الحمولة. اطّلِع على القسم المعنيّ بالتبديل عند حدوث خطأ وموازنة التحميل. يُرجى
العِلم أنّ المتصفّح سيختار نقطة نهاية واحدة فقط، حتى
إذا كانت المجموعة تسرد عدة أدوات جمع في endpoints
. إذا كنت تريد إرسال ملف ملف
إحصاءات إلى عدة خوادم في آنٍ واحد، يجب أن تعيد توجيه ملف
الإحصاءات من خلال الخلفية.
كيف يُرسِل المتصفّح التقارير؟
يُجمِّع المتصفّح التقارير بشكل دوري ويرسلها إلى نقاط نهاية reporting التي تحدّدها.
لإرسال التقارير، يُرسِل المتصفّح 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
وتعذّر loadingتحميل هذا المورد:
- يتم إشعار جامع 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}`);
});