Özel metrikler

Herhangi bir web sitesiyle ilgili olarak evrensel olarak ölçebileceğiniz kullanıcı odaklı metriklere sahip olmak büyük önem taşır. Bu metrikler sayesinde:

  • Gerçek kullanıcıların web'i bir bütün olarak nasıl deneyimlediğini anlayın.
  • Sitenizi bir rakibinizin sitesiyle karşılaştırın.
  • Özel kod yazmaya gerek kalmadan analiz araçlarınızdaki yararlı ve işlem yapılabilir verileri izleyin.

Evrensel metrikler iyi bir temel çizgisi sunar, ancak birçok durumda belirli bir sitenizde tüm deneyimi sunmak için bu metriklerden daha fazlasını ölçmeniz gerekir.

Özel metrikler, site deneyiminizin yalnızca siteniz için geçerli olabilecek yönlerini ölçmenizi sağlar. Örneğin:

  • Tek sayfalık bir uygulamanın (SPA) bir "sayfadan" diğerine geçişi için geçen süre.
  • Bir sayfanın, giriş yapmış kullanıcılar için veritabanından getirilen verileri görüntülemesinin ne kadar sürdüğü.
  • Sunucu tarafı olarak oluşturulan (SSR) bir uygulamanın hidrasyona uğraması için gereken süre.
  • 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çmek için API'ler

Geçmişte web geliştiricileri, performansı ölçecek çok sayıda alt düzey API'ye sahip değildi. Bunun sonucunda, bir sitenin iyi performans gösterip göstermediğini ölçmek için saldırılara başvurmak zorundaydı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 nedeniyle 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, gerçekte performansı etkilediği için (örneğin, pili tüketerek) önerilmez.

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

Performance Observer API'si

Tarayıcı Desteği

  • 52
  • 79
  • 57
  • 11

Kaynak

Performance Observer API, bu sayfada ele alınan diğer tüm performans API'lerinden veri toplayan ve görüntüleyen mekanizmadır. İyi veriler elde etmek için bu metriğin anlaşılması kritik önem taşır.

Performansla ilgili etkinliklere pasif olarak abone olmak için PerformanceObserver öğesini kullanabilirsiniz. Bu sayede API geri çağırmaları boşta kalma sürelerinde etkinleşir, yani genellikle sayfa performansını etkilemezler.

Bir PerformanceObserver oluşturmak için bu öğeye yeni performans girişleri gönderildiğinde çalıştırılacak bir geri çağırma iletin. Daha sonra, observe() yöntemini kullanarak gözlemciye ne tür girişler dinlemesi gerektiğini söylersiniz:

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

Aşağıdaki bölümlerde, gözlemlemek için kullanılabilecek çeşitli giriş türleri listelenmiştir. Ancak yeni tarayıcılarda, statik PerformanceObserver.supportedEntryTypes özelliğini kullanarak hangi giriş türlerinin kullanılabilir olduğunu inceleyebilirsiniz.

Daha önce gerçekleşen girişleri gözlemleyin

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

Geçmiş girişleri (gerçekleştikten sonra) almak için observe() öğesini çağırırken buffered işaretini true olarak ayarlayın. Tarayıcı, PerformanceObserver geri çağırmanız ilk kez çağrıldığında performans girişi arabelleğinden 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öntemi kullanarak performans girişlerine erişebiliyordu:

Bu API'ler hâlâ desteklense de yeni girişler yayınlandığında dinleme yapmanıza izin vermediğinden kullanımı önerilmez. Ayrıca, birçok yeni API (uzun Görevler gibi) performance nesnesi üzerinden kullanıma sunulmamıştır, yalnızca PerformanceObserver üzerinden kullanıma sunulur.

Özellikle Internet Explorer ile uyumluluğa ihtiyacınız olmadığı sürece, kodunuzda bu yöntemlerden kaçınmanız ve gelecekte PerformanceObserver kullanmanız en iyisidir.

Kullanıcı Zamanlaması API'sı

User Timing API, zamana dayalı metrikler için genel amaçlı bir ölçüm API'sidir. Bu, noktaları rastgele işaretlemenizi ve daha sonra bu işaretler arasındaki süreyi ölçmenizi sağlar.

// 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'yi kullanmanın performans araçlarıyla iyi entegre edilmesidir. Örneğin, Chrome Geliştirici Araçları, Performans panelinde kullanıcı zamanlaması ölçümlerini görselleştirir. Ayrıca birçok analiz sağlayıcısı, yaptığınız ölçümleri otomatik olarak izler ve süre verilerini analiz arka uçlarına gönderir.

Kullanıcı Zamanlaması ölçümlerini raporlamak için PerformanceObserver'ı kullanabilir ve measure türündeki girişleri gözlemlemek üzere kaydedebilirsiniz:

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

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 ne zaman kare hızını veya giriş gecikmesini etkileyecek kadar uzun bir süre boyunca engellendiğini bilmek için kullanışlıdır. Bu API, 50 milisaniyeden uzun süren görevleri raporlar.

Pahalı kodlar ç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, Long Tasks API'nin temelini oluşturur (ör. Etkileşime Kalan Süre (TTI) ve Toplam Engelleme Süresi (TBT)).

Uzun görevlerin ne zaman gerçekleşeceğini belirlemek için PerformanceObserver'ı kullanıp longtask türündeki girişleri gözlemlemek için kayıt yapabilirsiniz:

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

Tarayıcı Desteği

  • 77
  • 79
  • x
  • x

Kaynak

Largest Contentful Paint (LCP) metriği, en büyük resmin veya metin bloğunun ne zaman ekrana boyandığını bilmekte faydalıdır ancak bazı durumlarda farklı bir öğenin oluşturma süresini ölçmek isteyebilirsiniz.

Bu durumlarda Element Timing API'yi kullanın. LCP API, aslında Element Timing API'yi temel almakta ve en büyük zengin içerikli öğenin otomatik olarak raporlanmasını ekler. Bununla birlikte, diğer öğeler için açıkça elementtiming özelliğini 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>
  // 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>

Event Timing API'si

Sonraki Boyamayla Etkileşim (INP) metriği, bir sayfanın kullanım süresi boyunca gerçekleşen tüm tıklama, dokunma ve klavye etkileşimlerini gözlemleyerek genel sayfa duyarlılığını değerlendirir. Bir sayfanın INP'si genellikle kullanıcının etkileşimi başlattığı andan tarayıcının kullanıcı girişinin görsel sonucunu gösteren bir sonraki kareyi boyadığı zamana kadar tamamlanması en uzun süren etkileşimdir.

INP metriği, Event Timing API tarafından kullanılabilir. Bu API, etkinlik yaşam döngüsü boyunca meydana gelen çeşitli zaman damgalarını gösterir. Örneğin:

  • startTime: Tarayıcının etkinliği aldığı zaman.
  • processingStart: Tarayıcının, etkinlik için etkinlik işleyicileri işlemeye başlayabildiği zaman.
  • processingEnd: Tarayıcının bu etkinlik için etkinlik işleyicilerden başlatılan tüm eşzamanlı kodları yürütmeyi bitirdiği süre.
  • duration: Etkinlik işleyicilerden başlatılan tüm eşzamanlı kodun yürütme işlemini bitirdikten sonra tarayıcının etkinliği aldığı andan sonraki kareyi boyayabilene kadar geçen süre (güvenlik nedenleriyle 8 milisaniyeye 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) => {
    // 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.
}

Resource Timing API'si

Resource Timing API, geliştiricilere belirli bir sayfa için kaynakların nasıl yüklendiği hakkında ayrıntılı bilgi sağlar. API'nin adına rağmen sağladığı bilgiler yalnızca zamanlama verileriyle sınırlı değildir (ancak bu kadar çok şey vardır). Erişebileceğiniz diğer veriler şunlardır:

  • initiatorType: Kaynağın nasıl getirildiğidir (ör. <script> veya <link> etiketinden ya da fetch() çağrısından).
  • nextHopProtocol: kaynağı getirmek için kullanılan protokoldür (ör. h2 veya quic).
  • encodedBodySize/decodedBodySize]: kaynağın kodlanmış veya kodu çözülmüş biçiminde boyutu (sırasıyla)
  • transferSize: Ağ üzerinden gerçekten 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 (önbelleğin yeniden doğrulanması gerekmiyorsa).

Bir önbellek isabet oranı metriğini veya toplam önbelleğe alınmış kaynak boyutu metriğini ölçmek için kaynak zamanlaması girişlerinin transferSize özelliğini kullanabilirsiniz. Bu metrik, kaynak önbelleğe alma stratejinizin tekrar gelen ziyaretçilerin 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 önbellek tarafından karşılanıp karşılanmadığı belirtilir.

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

Tarayıcı Desteği

  • 57
  • 12
  • 58
  • 15

Kaynak

Gezinme Zamanlama API'si, Resource Timing API'ye benzer ancak yalnızca gezinme isteklerini bildirir. navigation giriş türü, resource giriş türüne de benzer ancak yalnızca gezinme isteklerine özel (DOMContentLoaded ve load etkinliklerinin etkinleşmesi gibi) bazı ek bilgiler içerir.

Pek çok geliştiricinin sunucu yanıt süresini anlamak için izlediği bir metrik (İlk Bayta Kadar Geçen Süre (TTFB)), Navigation Timing API'yi kullanarak mevcuttur. Özellikle de girişin responseStart zaman damgası kullanılır.

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

Service Worker'ı kullanan geliştiricilerin dikkate alabileceği bir diğer metrik, gezinme istekleri için Service Worker başlatma süresidir. Bu, tarayıcının Service Worker iş parçacığının getirme etkinliklerine müdahale etmeye başlamadan önce başlatılması için geçen süredir.

Belirli bir gezinme isteği için hizmet çalışanı başlatma süresi, entry.responseStart ile entry.workerStart arasındaki deltadan belirlenebilir.

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

Server Timing API'si

Server Timing API, isteğe özel zamanlama verilerini sunucunuzdan yanıt başlıkları aracılığıyla tarayıcınıza iletmenizi sağlar. Örneğin, belirli bir istek için veritabanında veri aramanın ne kadar sürdüğünü belirtebilirsiniz. Bu, sunucudaki yavaşlığın neden olduğu performans sorunlarını ayıklama konusunda yararlı olabilir.

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

Yanıtlarınızda sunucu zamanlaması verilerini belirtmek için Server-Timing yanıt başlığını kullanabilirsiniz. Bir örnekle açıklayalım.

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'lerinin resource veya navigation girişlerinde okuyabilirsiniz.

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