नेटवर्क की गड़बड़ी का डेटा लॉग करने की सुविधा (NEL)

एरिक बिडेलमैन
मॉड नाल्पस
मॉड नाल्पस

शुरुआती जानकारी

नेटवर्क गड़बड़ी लॉग करने (NEL) एक ऐसा तरीका है जिसकी मदद से, किसी ऑरिजिन से क्लाइंट-साइड नेटवर्क की गड़बड़ियां इकट्ठा की जाती हैं.

यह, ब्राउज़र को नेटवर्क की गड़बड़ियां इकट्ठा करने के बारे में बताने के लिए, NEL एचटीटीपी रिस्पॉन्स हेडर का इस्तेमाल करता है. इसके बाद, यह सर्वर को गड़बड़ियों की रिपोर्ट करने के लिए, Reporting API के साथ इंटिग्रेट करता है.

लेगसी Reporting API की खास जानकारी

लेगसी Reporting API का इस्तेमाल करने के लिए, आपको Report-To एचटीटीपी रिस्पॉन्स हेडर सेट करना होगा. इसकी वैल्यू एक ऑब्जेक्ट है, जो ब्राउज़र के एंडपॉइंट ग्रुप के बारे में जानकारी देता है. इससे ब्राउज़र को गड़बड़ियों की रिपोर्ट करने में मदद मिलती है:

Report-To:
{
    "max_age": 10886400,
    "endpoints": [{
    "url": "https://analytics.provider.com/browser-errors"
    }]
}

अगर आपका एंडपॉइंट यूआरएल आपकी साइट से अलग ऑरिजिन पर है, तो एंडपॉइंट पर सीओआरएस प्रीफ़्लाइट के अनुरोध काम करने चाहिए. (उदाहरण के लिए, 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 सेकंड के लिए कॉन्फ़िगर कर देता है. इस बात पर ध्यान देना ज़रूरी है कि पेज (इमेज, स्क्रिप्ट वगैरह के लिए) से बाद के सभी एचटीटीपी अनुरोधों को अनदेखा किया जाता है. कॉन्फ़िगरेशन, मुख्य पेज के रिस्पॉन्स के दौरान सेट अप किया जाता है.

हेडर फ़ील्ड का ब्यौरा

हर एंडपॉइंट कॉन्फ़िगरेशन में, group नाम, max_age, और endpoints कलेक्शन शामिल होता है. आपके पास यह चुनने का विकल्प भी होता है कि include_subdomains फ़ील्ड का इस्तेमाल करके, गड़बड़ियों की शिकायत करते समय सबडोमेन पर विचार किया जाए या नहीं.

फ़ील्ड टाइप जानकारी
group स्ट्रिंग ज़रूरी नहीं. अगर group नाम नहीं बताया गया है, तो एंडपॉइंट को "डिफ़ॉल्ट" नाम दिया जाता है.
max_age नंबर ज़रूरी है. यह एक नॉन-नेगेटिव पूर्णांक होता है, जो एंडपॉइंट के लाइफ़टाइम की जानकारी सेकंड में देता है. अगर वैल्यू "0" है, तो एंडपॉइंट ग्रुप को उपयोगकर्ता एजेंट की रिपोर्टिंग कैश मेमोरी से हटा दिया जाएगा.
endpoints कलेक्शन<ऑब्जेक्ट> ज़रूरी है. JSON ऑब्जेक्ट का कलेक्शन, जो आपके रिपोर्ट कलेक्टर का असली यूआरएल बताता है.
include_subdomains boolean ज़रूरी नहीं. एक बूलियन जो मौजूदा ऑरिजिन के होस्ट के सभी सबडोमेन के लिए एंडपॉइंट ग्रुप को चालू करता है. अगर इसे हटाया जाता है या "सही" के अलावा कुछ और कहा जाता है, तो एंडपॉइंट को सबडोमेन की जानकारी नहीं दी जाएगी.

group नाम एक यूनीक नाम है, जिसका इस्तेमाल स्ट्रिंग को एंडपॉइंट से जोड़ने के लिए किया जाता है. इस नाम का इस्तेमाल उन अन्य जगहों पर करें जो किसी खास एंडपॉइंट ग्रुप को रेफ़र करने के लिए, Reporting API के साथ इंटिग्रेट की जाती हैं.

max-age फ़ील्ड भी ज़रूरी है और इससे यह तय होता है कि ब्राउज़र को कितने समय तक एंडपॉइंट का इस्तेमाल करना चाहिए. साथ ही, इससे गड़बड़ियों की रिपोर्ट भी करनी चाहिए.

endpoints फ़ील्ड में फ़ेलओवर और लोड बैलेंसिंग की सुविधाएं मिलती हैं. फ़ेलओवर और लोड बैलेंसिंग के बारे में जानकारी देने वाला सेक्शन देखें. इस बात का ध्यान रखना ज़रूरी है कि ब्राउज़र सिर्फ़ एक एंडपॉइंट चुनेगा, भले ही ग्रुप में endpoints में कई कलेक्टर शामिल हों. अगर आपको एक साथ कई सर्वर को रिपोर्ट भेजनी है, तो आपके बैकएंड को रिपोर्ट फ़ॉरवर्ड करनी होगी.

ब्राउज़र रिपोर्ट कैसे भेजता है?

ब्राउज़र समय-समय पर रिपोर्ट को बैच करता है और उन्हें आपके कॉन्फ़िगर किए गए रिपोर्टिंग एंडपॉइंट पर भेजता है.

रिपोर्ट भेजने के लिए ब्राउज़र, Content-Type: application/reports+json के साथ POST अनुरोध करता है. साथ ही, कैप्चर की गई चेतावनियों/गड़बड़ियों की जानकारी वाला एक मुख्य हिस्सा जारी करता है.

ब्राउज़र रिपोर्ट कब भेजता है?

रिपोर्ट, आपके ऐप्लिकेशन से आउट-ऑफ़-बैंड डिलीवर की जाती हैं. इसका मतलब है कि आपके सर्वर पर रिपोर्ट भेजे जाने पर, ब्राउज़र कंट्रोल करता है.

ब्राउज़र, सूची में शामिल रिपोर्ट को सही समय पर डिलीवर करने की कोशिश करता है. यह उन्हें तुरंत तैयार (डेवलपर को समय पर सुझाव देने के लिए) किया जा सकता है. हालांकि, अगर ब्राउज़र ज़्यादा प्राथमिकता वाले काम को प्रोसेस करने में व्यस्त हो या उस समय उपयोगकर्ता धीमे और/या भीड़-भाड़ वाले नेटवर्क पर हो, तो ब्राउज़र डिलीवरी में भी देरी कर सकता है. अगर उपयोगकर्ता बार-बार वेबसाइट पर आता है, तो ब्राउज़र किसी खास ऑरिजिन के बारे में रिपोर्ट भेजने को प्राथमिकता दे सकता है.

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"
             }]
           }

या फिर इन्हें एक ही एचटीटीपी हेडर में जोड़कर:

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 वैल्यू के हिसाब से कैश मेमोरी में सेव करता है. साथ ही, कंसोल से जुड़ी सभी खराब चेतावनियां/गड़बड़ियों को आपके यूआरएल पर भेजता है.

फ़ेलओवर और लोड बैलेंसिंग

ज़्यादातर मामलों में, आपको हर ग्रुप के लिए एक यूआरएल कलेक्टर को कॉन्फ़िगर करना होगा. हालांकि, रिपोर्टिंग से अच्छा ट्रैफ़िक जनरेट हो सकता है. इसलिए, इसमें फ़ेलओवर और लोड बैलेंस करने की सुविधाएं भी शामिल हैं. ये सुविधाएं, डीएनएस एसआरवी रिकॉर्ड से प्रेरित होती हैं.

ब्राउज़र, ग्रुप में ज़्यादा से ज़्यादा एक एंडपॉइंट पर रिपोर्ट डिलीवर करने की पूरी कोशिश करेगा. लोड को डिस्ट्रिब्यूट करने के लिए, एंडपॉइंट को एक 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 को लोड करता है और वह संसाधन लोड नहीं हो पाता:

  • foobar.com के NEL कलेक्टर को सूचना दी गई
  • example.com के NEL कलेक्टर को सूचना नहीं दी गई है

बुनियादी नियम यह है कि NEL, सिर्फ़ क्लाइंट पर जनरेट किए गए सर्वर-साइड लॉग को फिर से तैयार करता है.

example.com को foobar.com के सर्वर लॉग में नहीं दिखता, इसलिए इसकी NEL रिपोर्ट भी नहीं दिखती.

रिपोर्ट के कॉन्फ़िगरेशन डीबग करना

अगर आपको अपने सर्वर पर रिपोर्ट नहीं दिखती हैं, तो chrome://net-export/ पर जाएं. इस पेज से यह पुष्टि की जा सकती है कि चीज़ें सही तरीके से कॉन्फ़िगर की गई हैं और रिपोर्ट सही तरीके से भेजी जा रही हैं.

रिपोर्टिंग ऑब्ज़र्वर का क्या होगा?

ReportingObserver एक मिलता-जुलता, लेकिन रिपोर्टिंग का अलग तरीका है. यह JavaScript कॉल पर आधारित है. यह नेटवर्क की गड़बड़ी को लॉग करने के लिए सही नहीं है, क्योंकि नेटवर्क की गड़बड़ियों को JavaScript से नहीं रोका जा सकता.

उदाहरण सर्वर

नीचे एक नोड सर्वर का उदाहरण दिया गया है, जो एक्सप्रेस का इस्तेमाल करता है. इस गाइड में, नेटवर्क की गड़बड़ियों के लिए रिपोर्टिंग को कॉन्फ़िगर करने का तरीका बताया गया है. साथ ही, नतीजे को कैप्चर करने के लिए एक खास हैंडलर बनाया गया है.

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}`);
});

इसके बारे में और पढ़ें