कस्टम मेट्रिक

उपयोगकर्ता को ध्यान में रखकर बनाई गई मेट्रिक बनाने से काफ़ी मदद मिलती है. इन्हें किसी भी वेबसाइट पर, दुनिया भर में मेज़र किया जा सकता है. इन मेट्रिक की मदद से:

  • वेब पर वास्तविक उपयोगकर्ताओं के अनुभव को समझें.
  • अपनी साइट की तुलना किसी प्रतिस्पर्धी की साइट से करें.
  • कस्टम कोड लिखे बिना, अपने आंकड़ों के टूल में काम का और कार्रवाई लायक डेटा ट्रैक करें.

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

कस्टम मेट्रिक की मदद से, आपकी साइट पर मिलने वाले अनुभव के उन पहलुओं का आकलन किया जा सकता है जो शायद सिर्फ़ आपकी साइट पर लागू हों, जैसे:

  • किसी एक पेज के ऐप्लिकेशन (एसपीए) को एक "पेज" से दूसरे पर ट्रांज़िशन होने में कितना समय लगता है.
  • लॉग इन किए हुए उपयोगकर्ताओं के लिए, किसी डेटाबेस से फ़ेच किए गए डेटा को पेज पर दिखाने में कितना समय लगता है.
  • सर्वर साइड रेंडरिंग (एसएसआर) वाले ऐप्लिकेशन को हाइड्रेट होने में कितना समय लगता है.
  • वेबसाइट पर वापस आने वाले लोगों से लोड किए गए रिसॉर्स के लिए, कैश मेमोरी हिट रेट.
  • किसी गेम में क्लिक या कीबोर्ड इवेंट के रिस्पॉन्स में लगने वाला समय.

कस्टम मेट्रिक मापने के लिए एपीआई

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

उदाहरण के लिए, requestAnimationFrame लूप चलाकर और हर फ़्रेम के बीच के डेल्टा का हिसाब लगाकर, यह पता लगाया जा सकता है कि लंबे समय तक चलने वाले JavaScript टास्क की वजह से मुख्य थ्रेड ब्लॉक है या नहीं. अगर डेल्टा का आकार डिसप्ले की फ़्रेम दर से काफ़ी ज़्यादा है, तो उसे लंबे टास्क के तौर पर रिपोर्ट किया जा सकता है. हालांकि, हम ऐसे हैक इस्तेमाल करने का सुझाव नहीं देते, क्योंकि इनसे परफ़ॉर्मेंस पर असर पड़ता है. उदाहरण के लिए, बैटरी खर्च होना.

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

परफ़ॉर्मेंस ऑब्ज़र्वर एपीआई

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 52.
  • Edge: 79.
  • Firefox: 57.
  • Safari: 11.

सोर्स

परफ़ॉर्मेंस ऑब्ज़र्वर एपीआई एक ऐसा तरीका है जो इस पेज पर बताए गए अन्य सभी परफ़ॉर्मेंस एपीआई से डेटा इकट्ठा और दिखाता है. अच्छा डेटा पाने के लिए, इसे समझना ज़रूरी है.

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

PerformanceObserver बनाने के लिए, उसे एक कॉलबैक पास करें, ताकि जब भी नई परफ़ॉर्मेंस एंट्री डिस्पैच की जाएं, तब वह कॉलबैक चलाया जा सके. इसके बाद, आपको observe() तरीके का इस्तेमाल करके, ऑब्ज़र्वर को यह बताना होगा कि किस तरह की एंट्री को सुनना है:

const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

po.observe({type: 'some-entry-type'});

नीचे दिए गए सेक्शन में, निगरानी के लिए उपलब्ध अलग-अलग एंट्री टाइप की सूची दी गई है. हालांकि, नए ब्राउज़र में, स्टैटिक PerformanceObserver.supportedEntryTypes प्रॉपर्टी की मदद से यह जांचा जा सकता है कि कौनसे एंट्री टाइप उपलब्ध हैं.

पहले से मौजूद एंट्री देखना

डिफ़ॉल्ट रूप से, PerformanceObserver ऑब्जेक्ट, एंट्री होने पर ही उनकी जानकारी देख सकते हैं. अगर आपको परफ़ॉर्मेंस के आंकड़े देने वाले कोड को धीरे-धीरे लोड करना है, तो इससे समस्याएं आ सकती हैं. ऐसा इसलिए, क्योंकि इससे ज़्यादा प्राथमिकता वाले संसाधन ब्लॉक हो सकते हैं.

पुरानी एंट्री देखने के लिए, observe() को कॉल करते समय buffered फ़्लैग को true पर सेट करें. जब पहली बार आपके PerformanceObserver कॉलबैक को कॉल किया जाएगा, तब ब्राउज़र अपने परफ़ॉर्मेंस एंट्री बफ़र से पुरानी एंट्री शामिल करेगा. हालांकि, यह उस टाइप के लिए बफ़र के ज़्यादा से ज़्यादा साइज़ तक ही शामिल करेगा.

po.observe({
  type: 'some-entry-type',
  buffered: true,
});

परफ़ॉर्मेंस से जुड़े ऐसे लेगसी एपीआई जिनका इस्तेमाल नहीं करना चाहिए

परफ़ॉर्मेंस ऑब्ज़र्वर एपीआई से पहले, डेवलपर performance ऑब्जेक्ट पर बताए गए इन तीन तरीकों का इस्तेमाल करके, परफ़ॉर्मेंस एंट्री ऐक्सेस कर सकते थे:

इन एपीआई का इस्तेमाल अब भी किया जा सकता है. हालांकि, हमारा सुझाव है कि इनका इस्तेमाल न करें, क्योंकि इनकी मदद से यह पता नहीं लगाया जा सकता कि नई एंट्री कब जनरेट हुई हैं. इसके अलावा, कई नए एपीआई (जैसे, largest-contentful-paint) performance ऑब्जेक्ट के ज़रिए एक्सपोज़ नहीं किए जाते. ये सिर्फ़ PerformanceObserver के ज़रिए एक्सपोज़ किए जाते हैं.

अगर आपको खास तौर पर Internet Explorer के साथ काम करने की ज़रूरत नहीं है, तो अपने कोड में इन तरीकों का इस्तेमाल न करें. इसके बजाय, आगे PerformanceObserver का इस्तेमाल करें.

User Timing API

ब्राउज़र सहायता

  • Chrome: 28.
  • Edge: 12.
  • Firefox: 38.
  • Safari: 11.

सोर्स

User Timing API, समय पर आधारित मेट्रिक के लिए, सामान्य मकसद वाला मेज़रमेंट एपीआई है. इसकी मदद से, अपनी मर्ज़ी से समय पर पॉइंट मार्क किए जा सकते हैं और बाद में, उन मार्क के बीच की अवधि को मापा जा सकता है.

// Record the time immediately before running a task.
performance.mark('myTask:start');
await doMyTask();

// Record the time immediately after running a task.
performance.mark('myTask:end');

// Measure the delta between the start and end of the task
performance.measure('myTask', 'myTask:start', 'myTask:end');

Date.now() या performance.now() जैसे एपीआई, आपको मिलती-जुलती सुविधाएं देते हैं. हालांकि, User Timing API का इस्तेमाल करने का फ़ायदा यह है कि यह परफ़ॉर्मेंस टूल के साथ अच्छी तरह से इंटिग्रेट होता है. उदाहरण के लिए, Chrome DevTools, परफ़ॉर्मेंस पैनल में उपयोगकर्ता के समय से जुड़े मेज़रमेंट को विज़ुअलाइज़ करता है. साथ ही, कई आंकड़े देने वाली कंपनियां, आपके किए गए किसी भी मेज़रमेंट को अपने-आप ट्रैक करेंगी और कुल समय का डेटा अपने आंकड़े देने वाले बैकएंड को भेजेंगी.

उपयोगकर्ता के समय से जुड़े मेज़रमेंट की रिपोर्ट करने के लिए, PerformanceObserver का इस्तेमाल करें. साथ ही, measure टाइप की एंट्री को देखने के लिए रजिस्टर करें:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `measure` entries to be dispatched.
po.observe({type: 'measure', buffered: true});

Long Tasks API

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 58.
  • एज: 79.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: यह सुविधा काम नहीं करती.

सोर्स

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

जब भी आपको ज़्यादा समय लेने वाला कोड चलाना हो या बड़ी स्क्रिप्ट लोड और एक्ज़ीक्यूट करनी हो, तो यह ट्रैक करना ज़रूरी है कि वह कोड मुख्य थ्रेड को ब्लॉक करता है या नहीं. असल में, कई बेहतर लेवल की मेट्रिक, Long Tasks API के ऊपर बनाई गई हैं. जैसे, इंटरैक्टिव में लगने वाला समय (TTI) और ब्लॉक करने में लगने वाला कुल समय (TBT).

यह पता लगाने के लिए कि लंबे टास्क कब होते हैं, PerformanceObserver का इस्तेमाल करें. साथ ही, longtask टाइप की एंट्री को देखने के लिए रजिस्टर करें:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `longtask` entries to be dispatched.
po.observe({type: 'longtask', buffered: true});

Long Animation Frames API

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 123.
  • Edge: 123.
  • Firefox: समर्थित नहीं.
  • Safari: समर्थित नहीं.

सोर्स

Long Animation Frames API, Long Tasks API का नया वर्शन है. यह 50 मिलीसेकंड से ज़्यादा के लंबे टास्क के बजाय, लंबे फ़्रेम पर नज़र रखता है. इससे लॉन्ग टास्क एपीआई की कुछ कमियों को ठीक किया जा सकता है. इसमें बेहतर एट्रिब्यूशन और देरी होने की संभावना को भी ज़्यादा दूर करना शामिल है.

यह तय करने के लिए कि फ़्रेम कब ट्रिगर हों, PerformanceObserver का इस्तेमाल करके, long-animation-frame टाइप की एंट्री पर नज़र रखने के लिए रजिस्टर करें:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `long-animation-frame` entries to be dispatched.
po.observe({type: 'long-animation-frame', buffered: true});

Element Timing API

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 77.
  • Edge: 79.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: यह सुविधा काम नहीं करती.

सोर्स

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

इन मामलों के लिए, Element Timing API का इस्तेमाल करें. एलसीपी एपीआई, असल में एलिमेंट टाइमिंग एपीआई के ऊपर बनाया गया है. यह सबसे बड़े कॉन्टेंट वाले एलिमेंट की रिपोर्टिंग अपने-आप जोड़ता है. हालांकि, अन्य एलिमेंट की रिपोर्टिंग भी की जा सकती है. इसके लिए, उनमें elementtiming एट्रिब्यूट को साफ़ तौर पर जोड़ें और element एंट्री टाइप को देखने के लिए, PerformanceObserver को रजिस्टर करें.

<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
<!-- ... -->

<script>
  const po = new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
      // Log the entry and all associated details.
      console.log(entry.toJSON());
    }
  });

  // Start listening for `element` entries to be dispatched.
  po.observe({type: 'element', buffered: true});
</script>

इवेंट टाइमिंग एपीआई

ब्राउज़र सहायता

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 89.
  • Safari: यह सुविधा काम नहीं करती.

सोर्स

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

INP मेट्रिक, इवेंट टाइमिंग एपीआई की मदद से जनरेट होती है. यह एपीआई, इवेंट के लाइफ़साइकल के दौरान होने वाले कई टाइमस्टैंप दिखाता है. इनमें ये शामिल हैं:

  • startTime: वह समय जब ब्राउज़र को इवेंट मिलता है.
  • processingStart: वह समय जब ब्राउज़र, इवेंट के लिए इवेंट हैंडलर को प्रोसेस करना शुरू कर सकता है.
  • processingEnd: वह समय जब ब्राउज़र इस इवेंट के लिए इवेंट हैंडलर से शुरू किए गए सभी सिंक्रोनस कोड को एक्ज़ीक्यूट करता है.
  • duration: इवेंट हैंडलर से शुरू किए गए सभी सिंक्रोनस कोड को लागू करने के बाद, ब्राउज़र को इवेंट मिलने और अगले फ़्रेम को पेंट करने के बीच लगने वाला समय. यह सुरक्षा की वजहों से आठ मिलीसेकंड तक हो सकता है.

नीचे दिए गए उदाहरण में, कस्टम मेज़रमेंट बनाने के लिए इन वैल्यू का इस्तेमाल करने का तरीका बताया गया है:

const po = new PerformanceObserver((entryList) => {
  // Get the last interaction observed:
  const entries = Array.from(entryList.getEntries()).forEach((entry) => {
    // Get various bits of interaction data:
    const inputDelay = entry.processingStart - entry.startTime;
    const processingTime = entry.processingEnd - entry.processingStart;
    const presentationDelay = entry.startTime + entry.duration - entry.processingEnd;
    const duration = entry.duration;
    const eventType = entry.name;
    const target = entry.target || "(not set)"

    console.log("----- INTERACTION -----");
    console.log(`Input delay (ms): ${inputDelay}`);
    console.log(`Event handler processing time (ms): ${processingTime}`);
    console.log(`Presentation delay (ms): ${presentationDelay}`);
    console.log(`Total event duration (ms): ${duration}`);
    console.log(`Event type: ${eventType}`);
    console.log(target);
  });
});

// A durationThreshold of 16ms is necessary to include more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po.observe({type: 'event', buffered: true, durationThreshold: 16});

Resource Timing API

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 29.
  • Edge: 12.
  • Firefox: 35.
  • Safari: 11.

सोर्स

रिसॉर्स टाइमिंग एपीआई, डेवलपर को इस बारे में पूरी जानकारी देता है कि किसी पेज के लिए रिसॉर्स कैसे लोड किए गए. इस एपीआई का नाम 'टाइमिंग डेटा' होने के बावजूद, यह सिर्फ़ टाइमिंग डेटा ही नहीं दिखाता. हालांकि, इसमें टाइमिंग डेटा काफ़ी होता है. आपके पास इस तरह का अन्य डेटा ऐक्सेस करने का विकल्प होता है:

  • initiatorType: संसाधन को फ़ेच करने का तरीका: जैसे, <script> या <link> टैग से या fetch() कॉल से.
  • nextHopProtocol: संसाधन को फ़ेच करने के लिए इस्तेमाल किया जाने वाला प्रोटोकॉल, जैसे कि h2 या quic.
  • encodedBodySize/decodedBodySize]: एन्कोड किए गए या डिकोड किए गए फ़ॉर्म में, संसाधन का साइज़ (क्रमशः)
  • transferSize: नेटवर्क पर ट्रांसफ़र किए गए संसाधन का साइज़. जब कैश मेमोरी से संसाधनों की मांग पूरी की जाती है, तो यह वैल्यू encodedBodySize से काफ़ी कम हो सकती है. साथ ही, कुछ मामलों में यह शून्य भी हो सकती है (अगर कैश मेमोरी की फिर से पुष्टि करने की ज़रूरत नहीं है).

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

नीचे दिए गए उदाहरण में, पेज के अनुरोध किए गए सभी रिसॉर्स को लॉग किया गया है. साथ ही, यह भी बताया गया है कि कैश मेमोरी में सेव किए गए हर रिसॉर्स को लोड किया गया था या नहीं.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // If transferSize is 0, the resource was fulfilled using the cache.
    console.log(entry.name, entry.transferSize === 0);
  }
});

// Start listening for `resource` entries to be dispatched.
po.observe({type: 'resource', buffered: true});

ब्राउज़र सहायता

  • Chrome: 57.
  • एज: 12.
  • Firefox: 58.
  • Safari: 15.

सोर्स

नेविगेशन टाइमिंग एपीआई, Resource Timing API की तरह है. हालांकि, यह सिर्फ़ नेविगेशन अनुरोधों की रिपोर्ट करता है. navigation एंट्री टाइप, resource एंट्री टाइप से मिलता-जुलता है. हालांकि, इसमें सिर्फ़ नेविगेशन अनुरोधों के लिए अतिरिक्त जानकारी होती है. जैसे, DOMContentLoaded और load इवेंट कब ट्रिगर होते हैं.

सर्वर के जवाब में लगने वाले समय (टाइम टू फ़र्स्ट बाइट (टीटीएफ़बी)) को समझने के लिए, कई डेवलपर एक मेट्रिक ट्रैक करते हैं. यह मेट्रिक, नेविगेशन टाइमिंग एपीआई का इस्तेमाल करके उपलब्ध होती है. खास तौर पर, इसकी एंट्री का responseStart टाइमस्टैंप.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // If transferSize is 0, the resource was fulfilled using the cache.
    console.log('Time to first byte', entry.responseStart);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});

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

किसी नेविगेशन अनुरोध के लिए, सेवा वर्कर के शुरू होने का समय, entry.responseStart और entry.workerStart के बीच के डेल्टा से तय किया जा सकता है.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('Service Worker startup time:',
        entry.responseStart - entry.workerStart);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});

Server Timing API

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 65.
  • Edge: 79.
  • Firefox: 61.
  • Safari: 16.4.

सोर्स

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

तीसरे पक्ष के आंकड़े उपलब्ध कराने वाली कंपनियों का इस्तेमाल करने वाले डेवलपर के लिए, सर्वर की परफ़ॉर्मेंस के डेटा को कारोबार की उन अन्य मेट्रिक से जोड़ने का सिर्फ़ एक ही तरीका है जिन्हें ये आंकड़े उपलब्ध कराने वाले टूल मेज़र कर सकते हैं. इसके लिए, सर्वर टाइमिंग एपीआई का इस्तेमाल किया जाता है.

अपने जवाबों में सर्वर के टाइमिंग डेटा की जानकारी देने के लिए, Server-Timing रिस्पॉन्स हेडर का इस्तेमाल किया जा सकता है. यहां एक उदाहरण दिया गया है.

HTTP/1.1 200 OK

Server-Timing: miss, db;dur=53, app;dur=47.2

इसके बाद, अपने पेजों से इस डेटा को Resource Timing और Navigation Timing एपीआई की resource या navigation, दोनों एंट्री में पढ़ा जा सकता है.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Logs all server timing data for this response
    console.log('Server Timing', entry.serverTiming);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});