Özel metrikler

Herhangi bir web sitesinde evrensel olarak ölçebileceğiniz kullanıcı odaklı metriklere sahip olmak çok değerlidir. Bu metrikler sayesinde şunları yapabilirsiniz:

  • Gerçek kullanıcıların web'i bir bütün olarak nasıl deneyimlediğini anlayın.
  • Sitenizi bir rakip siteyle karşılaştırın.
  • Özel kod yazmanıza gerek kalmadan analiz araçlarınızda faydalı ve işlem yapılabilir verileri izleyin.

Evrensel metrikler iyi bir referans noktası sunar ancak çoğu durumda, belirli bir sitenizin deneyimini tam olarak yakalamak için bu metriklerden daha fazlasını ölçmeniz gerekir.

Özel metrikler, sitenizdeki deneyimin yalnızca siteniz için geçerli olabilecek yönlerini ölçmenize olanak tanır. Örneğin:

  • Tek sayfalık bir uygulamanın (SPA) bir "sayfada"n diğerine geçişi için geçen süre.
  • Bir sayfanın, oturum açmış kullanıcılar için veritabanından alınan verileri göstermesi ne kadar sürer?
  • Sunucu tarafında oluşturulan (SSR) bir uygulamanın etkinleştirilmesi için gereken süre.
  • Geri gelen ziyaretçiler tarafından yüklenen kaynakların önbelleğe isabet oranı.
  • Bir oyundaki tıklama veya klavye etkinliklerinin etkinlik gecikmesi.

Özel metrikleri ölçmek için API'ler

Geçmişte web geliştiricilerinin performansı ölçmek için çok fazla düşük düzey API'si yoktu. Bu nedenle, bir sitenin iyi performans gösterip göstermediğini ölçmek için hilelere başvurmak zorunda kalıyorlardı.

Örneğin, bir requestAnimationFrame döngüsü çalıştırıp her kare arasındaki farkı hesaplayarak ana iş parçacığının uzun süre çalışan JavaScript görevleri nedeniyle engellenip engellenmediğini belirlemek mümkündür. Delta, ekranın kare hızından çok daha uzunsa bunu uzun görev olarak bildirebilirsiniz. Ancak bu tür hilelerin performansı etkilediği (ör. pili tüketerek) için önerilmez.

Etkili performans ölçümünün ilk kuralı, performans ölçüm tekniklerinizin performans sorunlarına neden olmadığından emin olmaktır. Bu nedenle, mümkünse sitenizde ölçtüğünüz tüm özel metrikler için aşağıdaki API'lerden birini kullanmak en iyisidir.

Performance Observer API

Tarayıcı desteği

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

Kaynak

Performans Gözlemleyici API'si, bu sayfada açıklanan diğer tüm performans API'lerinden gelen verileri toplayıp görüntüleyen mekanizmadır. İyi veriler elde etmek için bu konuyu anlamak çok önemlidir.

Performansla ilgili etkinliklere pasif olarak abone olmak için PerformanceObserver değerini kullanabilirsiniz. Bu, API geri çağırmalarının boş zamanlarda etkinleşmesini sağlar. Yani genellikle sayfa performansını etkilemezler.

PerformanceObserver oluşturmak için yeni performans girişleri gönderildiğinde çalıştırılacak bir geri çağırma işlevi iletin. Ardından, observe() yöntemini kullanarak gözlemciye ne tür girişleri dinlemesi gerektiğini bildirirsiniz:

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

Aşağıdaki bölümlerde, gözlemlenebilir tüm giriş türleri listelenmektedir. Ancak yeni tarayıcılarda, statik PerformanceObserver.supportedEntryTypes mülkü aracılığıyla hangi giriş türlerinin kullanılabileceğini inceleyebilirsiniz.

Geçmişte gerçekleşen girişleri gözlemleme

Varsayılan olarak, PerformanceObserver nesneleri yalnızca girişleri gerçekleştikçe gözlemleyebilir. Bu durum, performans analizleri kodunuzu daha yüksek öncelikli kaynakları engellememesi için yavaş yüklemek isterseniz sorunlara neden olabilir.

Geçmiş girişleri almak için (gerçekleştikten sonra) observe() işlevini çağırırken buffered işaretini true olarak ayarlayın. Tarayıcı, PerformanceObserver geri çağırma işleviniz ilk kez çağrıldığında performans giriş arabelleğindeki geçmiş girişleri bu tür için maksimum arabellek boyutuna kadar dahil eder.

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

Kullanılmaması gereken eski performans API'leri

Performance Observer API'den önce geliştiriciler, performance nesnesinde tanımlanan aşağıdaki üç yöntemi kullanarak performans girişlerine erişebiliyordu:

Bu API'ler hâlâ destekleniyor olsa da yeni girişler yayınlandığında dinlemenize izin vermedikleri için kullanılmaları önerilmez. Ayrıca, birçok yeni API (largest-contentful-paint gibi) performance nesnesi üzerinden değil, yalnızca PerformanceObserver üzerinden gösterilir.

Özellikle Internet Explorer ile uyumluluğu desteklemeniz gerekmiyorsa kodunuzda bu yöntemlerden kaçınmanız ve bundan sonra PerformanceObserver kullanmaya başlamanız en iyisidir.

User Timing API

Tarayıcı desteği

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

Kaynak

User Timing API, zamana dayalı metrikler için genel amaçlı bir ölçüm API'sidir. Zaman içinde istediğiniz noktaları işaretlemenize ve daha sonra bu işaretler arasındaki süreyi ölçmenize olanak tanır.

// 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() veya performance.now() gibi API'ler size benzer özellikler sunsa da User Timing API'yi kullanmanın avantajı, performans araçlarıyla iyi entegre olmasıdır. Örneğin, Chrome DevTools Performans panelinde kullanıcı zamanlama ölçümlerini görselleştirir. Ayrıca birçok analiz sağlayıcı, yaptığınız tüm ölçümleri otomatik olarak izler ve süre verilerini kendi analiz arka uçlarına gönderir.

Kullanıcı zamanlaması ölçümlerini bildirmek için PerformanceObserver'ı kullanabilir ve measure türündeki girişleri gözlemlemek için kaydolabilirsiniz:

// 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

Tarayıcı desteği

  • Chrome: 58.
  • Edge: 79.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Kaynak

Long Tasks API, tarayıcının ana iş parçacığının kare hızını veya giriş gecikmesini etkileyecek kadar uzun süre engellendiğini öğrenmek için kullanışlıdır. API, 50 milisaniyeden uzun süren tüm görevleri bildirir.

Pahalı kod çalıştırmanız veya büyük komut dosyaları yükleyip yürütmeniz gerektiğinde bu kodun ana iş parçacığını engelleyip engellemediğini izlemek faydalıdır. Aslında, birçok üst düzey metrik (ör. Etkileşime Hazır Olma Süresi (TTI) ve Toplam Engelleme Süresi (TBT)) Long Tasks API'nin üzerine inşa edilmiştir.

Uzun görevlerin ne zaman gerçekleştiğini belirlemek için PerformanceObserver'ı kullanabilir ve longtask türündeki girişleri gözlemlemek için kaydolun:

// 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

Tarayıcı desteği

  • Chrome: 123.
  • Edge: 123.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Kaynak

Long Animation Frames API, 50 milisaniyeden uzun uzun görevler yerine uzun kareleri inceleyen Long Tasks API'nin yeni bir iterasyonudur. Bu sayede, daha iyi ilişkilendirme ve soruna yol açabilecek gecikmeler için daha geniş bir kapsam da dahil olmak üzere Long Tasks API'nin bazı eksiklikleri giderilir.

Uzun karelerin ne zaman gerçekleştiğini belirlemek için PerformanceObserver'ı kullanabilir ve long-animation-frame türündeki girişleri gözlemlemek için kaydolabilirsiniz:

// 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

Tarayıcı desteği

  • Chrome: 77.
  • Edge: 79.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Kaynak

Largest Contentful Paint (LCP) metriği, en büyük resmin veya metin bloğunun ekrana ne zaman çizildiğini öğrenmek için kullanışlıdır ancak bazı durumlarda farklı bir öğenin oluşturma süresini ölçmek istersiniz.

Bu durumlarda Element Timing API'yi kullanın. LCP API aslında Element Timing API'nin üzerine inşa edilmiştir ve en büyük içerikli öğenin otomatik raporlamasını ekler. Ancak elementtiming özelliğini açıkça ekleyerek ve element giriş türünü gözlemlemek için bir PerformanceObserver kaydederek diğer öğeler hakkında da rapor oluşturabilirsiniz.

<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>

Event Timing API

Tarayıcı desteği

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 89.
  • Safari: Desteklenmez.

Kaynak

Interaction to Next Paint (INP) metriği, sayfanın kullanım süresi boyunca tüm tıklama, dokunma ve klavye etkileşimlerini gözlemleyerek sayfanın genel duyarlılığını değerlendirir. Bir sayfanın INP'si genellikle kullanıcının etkileşimi başlattığı andan, tarayıcı kullanıcının girişinin görsel sonucunu gösteren bir sonraki kareyi boyadığı ana kadar geçen süredir.

INP metriği, Event Timing API tarafından sağlanır. Bu API, etkinlik yaşam döngüsü sırasında gerçekleşen bir dizi zaman damgasını gösterir. Örneğin:

  • startTime: Tarayıcının etkinliği aldığı zaman.
  • processingStart: Tarayıcının etkinlik için etkinlik işleyicilerini işlemeye başlayabileceği zaman.
  • processingEnd: Tarayıcının, bu etkinlik için etkinlik işleyicilerden başlatılan tüm eşzamanlı kodu yürütmeyi tamamladığı zaman.
  • duration: Tarayıcının etkinliği aldığı andan, etkinlik işleyicilerden başlatılan tüm senkronize kodun yürütülmesini tamamladıktan sonra bir sonraki kareyi boyayabildiği ana kadar geçen süre (güvenlik nedeniyle 8 milisaniyeye yuvarlanır).

Aşağıdaki örnekte, özel ölçümler oluşturmak için bu değerlerin nasıl kullanılacağı gösterilmektedir:

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

Tarayıcı desteği

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

Kaynak

Resource Timing API, geliştiricilere belirli bir sayfanın kaynakları nasıl yüklendiğini ayrıntılı olarak gösterir. API'nin adına rağmen sağladığı bilgiler yalnızca zamanlama verileriyle sınırlı değildir (bununla birlikte çok sayıda zamanlama verisi vardır). Erişebileceğiniz diğer veriler şunlardır:

  • initiatorType: Kaynağın getirilme şekli: <script> veya <link> etiketi ya da fetch() çağrısı gibi.
  • nextHopProtocol: Kaynağı getirmek için kullanılan protokol (ör. h2 veya quic).
  • encodedBodySize/decodedBodySize]: Kaynak, kodlanmış veya kod çözülmüş biçimde (sırasıyla)
  • transferSize: Ağ üzerinden gerçekte aktarılan kaynağın boyutu. Kaynaklar önbellek tarafından karşılandığında bu değer encodedBodySize değerinden çok daha küçük olabilir ve bazı durumlarda sıfır olabilir (önbellek yeniden doğrulaması gerekmiyorsa).

Önbellek isabet oranı metriğini veya önbelleğe alınan toplam kaynak boyutu metriğini ölçmek için kaynak zamanlama girişlerinin transferSize mülkünü kullanabilirsiniz. Bu metrik, kaynak önbelleğe alma stratejinizin tekrar ziyaret eden kullanıcıların performansını nasıl etkilediğini anlamanıza yardımcı olabilir.

Aşağıdaki örnekte, sayfa tarafından istenen tüm kaynaklar günlüğe kaydedilir ve her bir kaynağın önbelleğe alınıp alınmadığı belirtilir.

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

Tarayıcı desteği

  • Chrome: 57.
  • Edge: 12.
  • Firefox: 58.
  • Safari: 15.

Kaynak

Navigation Timing API, Resource Timing API'ye benzer ancak yalnızca gezinme isteklerini raporlar. navigation giriş türü de resource giriş türüne benzer ancak yalnızca gezinme isteklerine özgü bazı ek bilgiler içerir (ör. DOMContentLoaded ve load etkinliklerinin tetiklendiği durumlar).

Birçok geliştiricinin sunucu yanıt süresini (ilk bayt zamanı (TTFB)) anlamak için izlediği bir metrik, Gezinme Zamanlaması API'si (özellikle de girişinin responseStart zaman damgası) kullanılarak kullanılabilir.

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

Hizmet çalışanı kullanan geliştiricilerin dikkate alabileceği bir diğer metrik de gezinme isteklerine yönelik hizmet çalışanı başlatma süresidir. Bu, tarayıcı tarafından getirme etkinliklerini durdurmaya başlamadan önce hizmet çalışanı iş parçacığının başlatılması için gereken süredir.

Belirli bir gezinme isteği için hizmet çalışanının başlangıç zamanı, entry.responseStart ile entry.workerStart arasındaki farktan belirlenebilir.

// 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

Tarayıcı desteği

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

Kaynak

Sunucu Zamanlama API'si, isteklere özgü zamanlama verilerini sunucunuzdan yanıt üstbilgileri aracılığıyla tarayıcıya iletmenize olanak tanır. Örneğin, belirli bir istek için veritabanında verilerin aranmasının ne kadar sürdüğünü belirtebilirsiniz. Bu, sunucudaki yavaşlıktan kaynaklanan performans sorunlarını gidermede yararlı olabilir.

Üçüncü taraf analiz sağlayıcıları kullanan geliştiriciler için sunucu performansı verilerini bu analiz araçlarının ölçebileceği diğer işletme metrikleriyle ilişkilendirmenin tek yolu Sunucu Zamanlaması API'sidir.

Yanıtlarınızda sunucu zamanlama verilerini belirtmek için Server-Timing yanıt üst bilgisini kullanabilirsiniz. Örneğin,

HTTP/1.1 200 OK

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

Ardından, sayfalarınızdan bu verileri Resource Timing ve Navigation Timing API'lerindeki hem resource hem de navigation girişlerinde okuyabilirsiniz.

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