Özel metrikler

Herhangi bir web sitesinde ölçebileceğiniz evrensel, kullanıcı odaklı metriklerin olması, kullanıcılarınızın web deneyimini anlamanıza ve sitenizi rakiplerinizinkiyle karşılaştırmanıza çok yardımcı olabilir. Ancak çoğu durumda, sitenizin tam deneyimini yakalamak için evrensel metriklerden daha fazlasını ölçmeniz gerekir.

Özel metrikler, site deneyiminizin 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 "sayfadan" diğerine geçişinin ne kadar sürdüğü.
  • Bir sayfanın, giriş yapmış kullanıcılar için bir veritabanından getirilen verileri görüntülemesinin ne kadar sürdüğü.
  • Sunucu tarafında oluşturulan (SSR) bir uygulamanın hidratlanması ne kadar sürer.
  • Geri gelen ziyaretçiler tarafından yüklenen kaynakların önbellek isabet oranı.
  • Bir oyundaki tıklama veya klavye etkinliklerinin etkinlik gecikmesi.

Özel metrikleri ölçmeye yönelik API'ler

Web geliştiricileri geçmişte performansı ölçmek için çok sayıda alt düzey API'ye sahip olmamıştı ve bunun sonucunda, bir sitenin iyi performans gösterip göstermediğini ölçmek için saldırılara başvurmak zorunda kaldılar. Örneğin, bir requestAnimationFrame döngüsü çalıştırarak ve her kare arasındaki deltayı hesaplayarak ana iş parçacığının uzun süreli JavaScript görevleri tarafından engellenip engellenmediğini belirleyebilirsiniz. Delta, ekranın kare hızından önemli ölçüde daha uzunsa bunu uzun bir görev olarak bildirebilirsiniz.

Ancak bu tür saldırılar, örneğin cihazın pilini tüketerek sitenizin performansını etkileyebilir. Performans ölçüm teknikleriniz performans sorunlarına neden oluyorsa bu tekniklerden aldığınız veriler doğru olmaz. Bu nedenle, özel metrik oluşturmak için aşağıdaki API'lerden birini kullanmanızı öneririz.

Performance Observer API'si

Tarayıcı Desteği

  • 52
  • 79
  • 57
  • 11

Kaynak

Performance Observer API, bu sayfada açıklanan diğer tüm performans API'lerinden veri toplayıp görüntüleyen mekanizmadır. Bunu anlamak, iyi veriler elde etmek açısından çok önemlidir.

Performansla ilgili etkinliklere pasif olarak abone olmak için PerformanceObserver kullanabilirsiniz. Bu, API geri çağırmalarının boşta kalma dönemlerde tetiklenmesine olanak tanır. Bu da genellikle sayfa performansını etkilemeyecekleri anlamına gelir.

Bir PerformanceObserver oluştururken, buna yeni performans girişleri gönderildiğinde çalışan bir geri çağırma iletin. Ardından, gözlemciye ne tür girişlerin dinleneceğini aşağıdaki şekilde belirtmek için observe() yöntemini kullanın:

// Catch errors that 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.
}

Aşağıdaki bölümlerde gözlemleyebileceğiniz tüm giriş türleri listelenmiştir. Yeni tarayıcılarda, statik PerformanceObserver.supportedEntryTypes özelliğini kullanarak hangi giriş türlerinin kullanılabileceğini de inceleyebilirsiniz.

Gerçekleşen girişleri gözlemle

Varsayılan olarak, PerformanceObserver nesneleri yalnızca gerçekleştikleri sırada girişleri gözlemleyebilir. Performans analizi kodunuzun daha yüksek öncelikli kaynakları engellememesi için geç yüklemek istiyorsanız bu durum sorunlara yol açabilir.

Geçmiş girişleri almak için buffered işareti true olarak ayarlanmış şekilde observe yöntemini çağırın. Ardından tarayıcı, PerformanceObserver geri çağırma işleminiz ilk kez çağrıldığında performans giriş arabelleğindeki geçmiş girişleri dahil eder.

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

Kaçınılması gereken eski performans API'leri

Performance Observer API'den önce geliştiriciler, performance nesnesinde tanımlanan aşağıdaki yöntemleri kullanarak performans girişlerine erişebiliyordu. Yeni girişleri dinlemenize izin vermediklerinden bunları kullanmanızı önermeyiz.

Ayrıca, birçok yeni API (Uzun Görevler gibi) performance nesnesi tarafından sunulmaz, yalnızca PerformanceObserver tarafından kullanıma sunulur. Bu nedenle, Internet Explorer uyumluluğuna özellikle ihtiyaç duymadığınız sürece, kodunuzda bu yöntemleri kullanmamanız ve bundan sonra PerformanceObserver kullanmanız önerilir.

Kullanıcı Zamanlaması API'sı

User Timing API, zamana dayalı metrikler için genel amaçlı bir ölçüm API'sidir. Zamandaki noktaları rastgele 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 yetenekler sunsa da User Timing API, performans araçlarıyla daha iyi entegre edilmiştir. Örneğin, Chrome Geliştirici Araçları Performans panelindeki Kullanıcı Zamanlaması ölçümlerini görselleştirir. Birçok analiz sağlayıcısı yaptığınız tüm ölçümleri otomatik olarak izleyip süre verilerini analiz arka uçlarına gönderir.

Kullanıcı Zamanlaması ölçümlerini raporlamak amacıyla measure türündeki girişleri gözlemlemek için bir PerformanceObserver kaydedin:

// Catch errors 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.
  po.observe({type: 'measure', buffered: true});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Uzun Görevler API'sı

Tarayıcı Desteği

  • 58
  • 79
  • x
  • x

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ğinde bunu belirlemek açısından yararlıdır. API, 50 milisaniyeden (ms) uzun süre yürütülen görevleri bildirir.

Pahalı kod çalıştırmanız veya büyük komut dosyaları yükleyip yürütmeniz gerektiğinde, kodun ana iş parçacığını engelleyip engellemediğini izlemek yararlıdır. Aslında, birçok üst düzey metrik, Uzun Görevler API'sinin (ör. Etkileşime Hazır Olma Süresi (TTI) ve Toplam Engelleme Süresi (TBT)) temel alınarak derlenir.

Uzun görevlerin ne zaman gerçekleştiğini belirlemek için longtask türündeki girişleri gözlemlemek üzere bir PerformanceObserver kaydedin:

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

Element Timing API'sı

Tarayıcı Desteği

  • 77
  • 79
  • x
  • x

Kaynak

Largest Contentful Paint (LCP) metriği, sayfanızdaki en büyük resmin veya metin bloğunun ne zaman ekrana boyandığını bilmek için yararlı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 kurulmuştur ve en büyük zengin içerikli öğenin otomatik olarak raporlanmasını sağlar. Bununla birlikte, 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 rapor oluşturabilirsiniz.

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

Etkinlik Zamanlaması API'sı

First Input Delay (FID) metriği, kullanıcının bir sayfayla ilk kez etkileşimde bulunmasından tarayıcının bu etkileşime yanıt olarak etkinlik işleyicileri işlemeye başlayabileceği ana kadar geçen süreyi ölçer. Ancak bazı durumlarda etkinlik işleme süresinin kendisini ölçmek de yararlı olabilir.

Bu durum, FID metriğinin yanı sıra etkinlik yaşam döngüsünde aşağıdakiler de dahil olmak üzere çeşitli zaman damgalarını da gösteren Event Timing API kullanılarak yapılabilir:

  • 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 bitirdiği zaman.
  • duration: Tarayıcının etkinliği alması ile etkinlik işleyicilerden başlatılan tüm eşzamanlı kodu yürütmeyi bitirdikten sonra bir sonraki kareyi boyayabilene kadar geçen süre (güvenlik nedenleriyle 8 ms'ye yuvarlanır).

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

// 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) => {
    const firstInput = entryList.getEntries()[0];

    // Measure First Input Delay (FID).
    const firstInputDelay = firstInput.processingStart - firstInput.startTime;

    // Measure the time it takes to run all event handlers
    // Doesn't include work scheduled asynchronously using methods like
    // `requestAnimationFrame()` or `setTimeout()`.
    const firstInputProcessingTime = firstInput.processingEnd - firstInput.processingStart;

    // Measure the entire duration of the event, from when input is received by
    // the browser until the next frame can be painted after processing all
    // event handlers.
    // Doesn't include work scheduled asynchronously using
    // `requestAnimationFrame()` or `setTimeout()`.
    // For security reasons, this value is rounded to the nearest 8 ms.
    const firstInputDuration = firstInput.duration;

    // Log these values to the console.
    console.log({
      firstInputDelay,
      firstInputProcessingTime,
      firstInputDuration,
    });
  });

  po.observe({type: 'first-input', buffered: true});
} catch (error) {
  // Do nothing if the browser doesn't support this API.
}

Kaynak Zamanlaması API'sı

Resource Timing API, belirli bir sayfaya ait kaynakların nasıl yüklendiğiyle ilgili geliştiricilere ayrıntılı bilgi sağlar. API'nin adına rağmen, sağladığı bilgi yalnızca zamanlama verileriyle sınırlı değildir (yine de bundan çok fazla veri vardır). Erişebileceğiniz diğer veriler şunlardır:

  • initiatorType: Kaynağın nasıl getirildiğini (örneğin, bir <script> veya <link> etiketinden ya da fetch()'dan).
  • nextHopProtocol: kaynağı getirmek için kullanılan h2 veya quic gibi protokol.
  • encodedBodySize ve decodedBodySize]: Kaynağın kodlanmış veya kodu çözülmüş biçimindeki (sırasıyla) boyutu.
  • transferSize: Ağ üzerinden gerçekten aktarılan kaynağın boyutu. Kaynaklar önbellek kullanılarak karşılandığında bu değer encodedBodySize değerinden çok daha küçük olabilir ve bazı durumlarda önbelleğin yeniden doğrulanması gerekmiyorsa sıfır olabilir.

Bir önbellek isabet oranı metriğini veya toplam önbelleğe alınmış kaynak boyutu metriğini ölçmek için kaynak zamanlama girişlerinin transferSize özelliğini kullanabilirsiniz. Bu, kaynak önbelleğe alma stratejinizin tekrar gelen ziyaretçiler için performansı nasıl etkilediğini anlamanıza yardımcı olabilir.

Aşağıdaki örnek, sayfa tarafından istenen tüm kaynakları günlüğe kaydeder ve her bir kaynağın önbellek kullanılarak karşılanıp karşılanmadığını gösterir:

// Catch errors 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.
}

Tarayıcı Desteği

  • 57
  • 12
  • 58
  • 15

Kaynak

Gezinme Zamanlaması API'si, 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 (DOMContentLoaded ve load etkinliklerinin etkinleşmesi gibi) özel bazı ek bilgiler içerir.

Birçok geliştiricinin sunucu yanıt süresini anlamak için izlediği bir metrik olan İlk Bayt Süresi (TTFB), Navigation Timing API'deki responseStart zaman damgası aracılığıyla kullanılabilir.

// Catch errors since  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 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Service Worker'ları kullanan bir diğer metrik geliştiricileri ise önemseyebileceği bir diğer metriktir. Bu süre, gezinme istekleri için Service Worker başlatma süresidir. Bu, tarayıcının getirme etkinliklerine müdahaleye başlamadan önce Service Worker iş parçacığını başlatması için gereken süredir.

Belirtilen gezinme isteği için hizmet çalışanı başlatma süresi, entry.responseStart ile entry.workerStart arasındaki deltadan aşağıdaki gibi belirlenebilir:

// Catch errors 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.
}

Sunucu Zamanlaması API'sı

Server Timing API, yanıt başlıklarını kullanarak isteğe özel zamanlama verilerini sunucunuzdan tarayıcıya iletmenizi sağlar. Örneğin, belirli bir istek için veritabanında veri aramasının ne kadar sürdüğünü belirtebilirsiniz. Bu, sunucudaki yavaşlıktan kaynaklanan performans sorunlarının ayıklanmasında yararlı olabilir.

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

Yanıtlarınızda sunucu zamanlama verilerini belirtmek için Server-Timing yanıt başlığını kullanın. Aşağıda bir örnek verilmiştir:

HTTP/1.1 200 OK

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

Ardından, sayfalarınızdan, Resource Timing ve Navigation Timing API'lerinden gelen resource veya navigation girişlerinde bu verileri okuyabilirsiniz.

// Catch errors 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.
}