Metrik kustom

Ada banyak manfaat dari memiliki metrik yang berfokus pada pengguna yang dapat Anda ukur, secara universal, di situs mana pun. Metrik ini memungkinkan Anda:

  • Memahami pengalaman pengguna nyata dengan web secara keseluruhan.
  • Bandingkan situs Anda dengan situs pesaing.
  • Lacak data yang berguna dan dapat ditindaklanjuti di alat analisis Anda tanpa perlu menulis kode kustom.

Metrik universal menawarkan dasar pengukuran yang baik, tetapi dalam banyak kasus, Anda perlu mengukur lebih dari metrik ini untuk menangkap pengalaman lengkap untuk situs Anda.

Metrik kustom memungkinkan Anda mengukur aspek pengalaman situs yang mungkin hanya berlaku untuk situs Anda, seperti:

  • Waktu yang dibutuhkan aplikasi web satu halaman (SPA) untuk bertransisi dari satu "halaman" ke "halaman" lainnya.
  • Waktu yang dibutuhkan halaman untuk menampilkan data yang diambil dari database untuk pengguna yang login.
  • Waktu yang diperlukan aplikasi server-side-render (SSR) untuk melakukan hidrasi.
  • Rasio cache ditemukan untuk resource yang dimuat oleh pengunjung yang kembali.
  • Latensi peristiwa klik atau peristiwa keyboard dalam game.

API untuk mengukur metrik kustom

Sebelumnya, developer web belum memiliki banyak API tingkat rendah untuk mengukur performa. Akibatnya, mereka harus melakukan peretasan untuk mengukur apakah suatu situs berperforma baik atau tidak.

Misalnya, Anda dapat menentukan apakah thread utama diblokir karena tugas JavaScript yang berjalan lama dengan menjalankan loop requestAnimationFrame dan menghitung delta di antara setiap frame. Jika delta secara signifikan lebih panjang dari kecepatan frame layar, Anda dapat melaporkannya sebagai tugas yang panjang. Namun, peretasan semacam itu tidak disarankan karena akan memengaruhi performanya sendiri (misalnya, dengan menghabiskan baterai).

Aturan pertama pengukuran kinerja yang efektif adalah memastikan bahwa teknik pengukuran kinerja Anda tidak menyebabkan masalah kinerja itu sendiri. Jadi untuk setiap metrik kustom yang Anda ukur di situs, sebaiknya gunakan salah satu API berikut jika memungkinkan.

API Pengamat Performa

Dukungan Browser

  • 52
  • 79
  • 57
  • 11

Sumber

Performance Observer API adalah mekanisme yang mengumpulkan dan menampilkan data dari semua API performa lain yang dibahas di halaman ini. Memahami hal tersebut sangat penting untuk mendapatkan data yang baik.

Anda dapat menggunakan PerformanceObserver untuk berlangganan peristiwa terkait performa secara pasif. Hal ini memungkinkan callback API diaktifkan selama periode tidak ada aktivitas, yang berarti callback ini biasanya tidak akan mengganggu performa halaman.

Untuk membuat PerformanceObserver, teruskan callback untuk dijalankan setiap kali entri performa baru dikirim. Kemudian, Anda memberi tahu observer jenis entri yang perlu diproses menggunakan metode observe():

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  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'});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Bagian berikut mencantumkan semua jenis entri yang tersedia untuk diamati, tetapi di browser yang lebih baru, Anda dapat memeriksa jenis entri yang tersedia melalui properti PerformanceObserver.supportedEntryTypes statis.

Mengamati entri yang sudah terjadi

Secara default, objek PerformanceObserver hanya dapat mengamati entri saat terjadi. Hal ini dapat menyebabkan masalah jika Anda ingin memuat kode analisis performa secara lambat agar tidak memblokir resource dengan prioritas lebih tinggi.

Untuk mendapatkan entri historis (setelah entri terjadi), setel tanda buffered ke true saat Anda memanggil observe(). Browser akan menyertakan entri historis dari buffer entri performa saat pertama kali callback PerformanceObserver dipanggil.

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

API performa lama yang harus dihindari

Sebelum Performance Observer API, developer dapat mengakses entri performa menggunakan tiga metode berikut yang ditentukan pada objek performance:

Meskipun API ini masih didukung, penggunaannya tidak direkomendasikan karena tidak memungkinkan Anda memproses saat entri baru dimunculkan. Selain itu, banyak API baru (seperti Long Tasks) yang tidak diekspos melalui objek performance, dan hanya diekspos melalui PerformanceObserver.

Kecuali jika Anda secara khusus memerlukan kompatibilitas dengan Internet Explorer, sebaiknya hindari metode ini di kode Anda dan gunakan PerformanceObserver untuk ke depannya.

API Waktu Pengguna

User Timing API adalah API pengukuran tujuan umum untuk metrik berbasis waktu. Alat ini memungkinkan Anda menandai titik secara bebas pada waktu, lalu mengukur durasi antara tanda tersebut nanti.

// 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');

Meskipun API seperti Date.now() atau performance.now() memberi Anda kemampuan yang serupa, manfaat penggunaan User Timing API adalah integrasi yang baik dengan alat performa. Misalnya, Chrome DevTools memvisualisasikan pengukuran Waktu Pengguna di panel Performa, dan banyak penyedia analisis juga akan otomatis melacak pengukuran apa pun yang Anda lakukan dan mengirim data durasi ke backend analisisnya.

Untuk melaporkan pengukuran Waktu Pengguna, Anda dapat menggunakan PerformanceObserver dan mendaftar untuk mengamati entri jenis measure:

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

API Tugas Panjang

Dukungan Browser

  • 58
  • 79
  • x
  • x

Sumber

Long Tasks API berguna untuk mengetahui kapan thread utama browser diblokir cukup lama untuk memengaruhi kecepatan frame atau latensi input. API akan melaporkan tugas apa pun yang dijalankan selama lebih dari 50 milidetik.

Setiap kali Anda perlu menjalankan kode yang mahal, atau memuat dan mengeksekusi skrip besar, akan berguna untuk melacak apakah kode tersebut memblokir thread utama. Faktanya, banyak metrik dengan tingkat lebih tinggi yang dibuat menggunakan Long Tasks API itu sendiri (seperti Time to Interactive (TTI) dan Total Blocking Time (TBT)).

Untuk menentukan kapan tugas yang berjalan lama terjadi, Anda dapat menggunakan PerformanceObserver dan mendaftar untuk mengamati entri jenis longtask:

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

API Waktu Elemen

Dukungan Browser

  • 77
  • 79
  • x
  • x

Sumber

Metrik Largest Contentful Paint (LCP) berguna untuk mengetahui kapan gambar atau blok teks terbesar digambar ke layar, tetapi dalam beberapa kasus Anda ingin mengukur waktu render elemen yang berbeda.

Untuk kasus ini, gunakan Element Timing API. LCP API sebenarnya dibuat di atas Element Timing API dan menambahkan pelaporan otomatis dari elemen konten terbesar, tetapi Anda juga dapat melaporkan elemen lain dengan secara eksplisit menambahkan atribut elementtiming ke elemen tersebut, dan mendaftarkan PerformanceObserver untuk mengamati jenis entri element.

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

<script>
  // Catch errors since some browsers throw when using the new `type` option.
  // https://bugs.webkit.org/show_bug.cgi?id=209216
  try {
    // Create the performance observer.
    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});
  } catch (e) {
    // Do nothing if the browser doesn't support this API.
  }
</script>

API Waktu Peristiwa

Metrik Interaction to Next Paint (INP) menilai responsivitas halaman secara keseluruhan dengan mengamati semua interaksi klik, ketukan, dan keyboard selama masa aktif halaman. INP halaman paling sering merupakan interaksi yang memerlukan waktu paling lama untuk diselesaikan, mulai dari saat pengguna memulai interaksi, hingga saat browser menggambar frame berikutnya yang menunjukkan hasil visual dari input pengguna.

Metrik INP dimungkinkan oleh Event Timing API. API ini mengekspos sejumlah stempel waktu yang terjadi selama siklus proses peristiwa, termasuk:

  • startTime: waktu saat browser menerima peristiwa.
  • processingStart: waktu saat browser dapat mulai memproses pengendali peristiwa untuk peristiwa tersebut.
  • processingEnd: waktu saat browser selesai mengeksekusi semua kode sinkron yang dimulai dari pengendali peristiwa untuk peristiwa ini.
  • duration: waktu (dibulatkan menjadi 8 milidetik untuk alasan keamanan) antara saat browser menerima peristiwa hingga dapat menggambar frame berikutnya setelah selesai mengeksekusi semua kode sinkron yang dimulai dari pengendali peristiwa.

Contoh berikut menunjukkan cara menggunakan nilai ini untuk membuat pengukuran kustom:

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  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 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 time (ms): ${processingTime}`);
      console.log(`Total event duration (ms): ${duration}`);
      console.log(`Event type: ${eventType}`);
      console.log(target);
    });
  });

  // A durationThreshold of 16ms is necessary to surface more
  // interactions, since the default is 104ms. The minimum
  // durationThreshold is 16ms.
  po.observe({type: 'event', buffered: true, durationThreshold: 16});
} catch (error) {
  // Do nothing if the browser doesn't support this API.
}

API Resource Timing

Resource Timing API memberikan insight mendetail kepada developer tentang cara resource untuk halaman tertentu dimuat. Terlepas dari nama API ini, informasi yang diberikannya tidak hanya terbatas pada data waktu (meskipun ada banyak sekali). Data lain yang dapat Anda akses meliputi:

  • initiatorType: cara resource diambil: seperti dari tag <script> atau <link>, atau dari panggilan fetch().
  • nextHopProtocol: protokol yang digunakan untuk mengambil resource, seperti h2 atau quic.
  • encodedBodySize/decodedBodySize]: ukuran resource dalam bentuk yang dienkode atau didekode (masing-masing)
  • transferSize: ukuran resource yang benar-benar ditransfer melalui jaringan. Jika resource dipenuhi oleh cache, nilai ini bisa jauh lebih kecil daripada encodedBodySize, dan dalam beberapa kasus bisa nol (jika validasi ulang cache tidak diperlukan).

Anda dapat menggunakan properti transferSize dari entri waktu resource untuk mengukur metrik rasio hit cache atau metrik total ukuran resource yang di-cache, yang dapat berguna dalam memahami pengaruh strategi penyimpanan dalam cache resource Anda terhadap performa untuk pengunjung berulang.

Contoh berikut mencatat semua resource yang diminta oleh halaman dan menunjukkan apakah setiap resource dipenuhi oleh cache atau tidak.

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // Create the performance observer.
  const po = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      // If transferSize is 0, the resource was fulfilled via the cache.
      console.log(entry.name, entry.transferSize === 0);
    }
  });

  // Start listening for `resource` entries to be dispatched.
  po.observe({type: 'resource', buffered: true});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Dukungan Browser

  • 57
  • 12
  • 58
  • 15

Sumber

Navigation Timing API mirip dengan Resource Timing API, tetapi hanya melaporkan permintaan navigasi. Jenis entri navigation juga mirip dengan jenis entri resource, tetapi berisi beberapa informasi tambahan khusus untuk permintaan navigasi saja (seperti saat peristiwa DOMContentLoaded dan load diaktifkan).

Satu metrik yang dilacak banyak developer untuk memahami waktu respons server (Time to First Byte (TTFB)) tersedia menggunakan Navigation Timing API—khususnya stempel waktu responseStart entri.

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // Create the performance observer.
  const po = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      // If transferSize is 0, the resource was fulfilled via the cache.
      console.log('Time to first byte', entry.responseStart);
    }
  });

  // Start listening for `navigation` entries to be dispatched.
  po.observe({type: 'navigation', buffered: true});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Metrik lain yang menjadi perhatian developer yang menggunakan pekerja layanan adalah waktu startup pekerja layanan untuk permintaan navigasi. Ini adalah jumlah waktu yang diperlukan browser untuk memulai thread pekerja layanan sebelum dapat mulai mencegat peristiwa pengambilan.

Waktu startup pekerja layanan untuk permintaan navigasi tertentu dapat ditentukan dari delta antara entry.responseStart dan entry.workerStart.

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

API Waktu Server

Server Timing API memungkinkan Anda meneruskan data waktu khusus permintaan dari server Anda ke browser melalui header respons. Misalnya, Anda dapat menunjukkan waktu yang diperlukan untuk mencari data dalam database untuk permintaan tertentu—yang dapat berguna dalam proses debug masalah performa yang disebabkan oleh kelambatan di server.

Untuk developer yang menggunakan penyedia analisis pihak ketiga, Server Timing API adalah satu-satunya cara untuk menghubungkan data performa server dengan metrik bisnis lain yang mungkin diukur oleh alat analisis ini.

Untuk menentukan data waktu server dalam respons, Anda dapat menggunakan header respons Server-Timing. Berikut contohnya.

HTTP/1.1 200 OK

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

Kemudian, dari halaman, Anda dapat membaca data ini pada entri resource atau navigation dari Resource Timing API dan Navigation Timing API.

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}