---
title: 'Gerçek Kullanıcı İzleme'
source: 'https://academia.sh/tr/kurslar/frontend-kalitesi/gercek-kullanici-izleme'
course: 'Frontend Kalitesi'
language: tr
updated: '2026-08-17T18:09:22+00:00'
license: 'CC BY-SA 4.0'
---

# Gerçek Kullanıcı İzleme

Laboratuvar ölçümüyle alan verisinin yanıtladığı farklı sorular, alanda ölçüt toplama ve gönderme biçimi, yüzdelik dilim hesabıyla dağılımın okunması, bölütleme ve örneklem büyüklüğünün etkisi.

Kararlı bir test paketi, denetim altındaki bir ortamda beklenen davranışın korunduğunu
söyler. Söylemediği şey, uygulamanın gerçek kullanıcıların elinde nasıl davrandığıdır. Test
makinesi hızlıdır, ağı düzgündür, önbelleği bilinen bir durumdadır. Kuzey Yamaç arayüzünü
alanda kullanan gözlemci ise zayıf bir bağlantıda, yaşlı bir aygıtla ve arka planda başka
sekmelerle çalışır.

Bu ders iki veri kaynağını yan yana koyar ve aradaki farkı ölçülebilir hâle getirir.

## İki Kaynak, İki Soru

**Laboratuvar verisi**, denetimli bir koşumdan gelir: sabit aygıt profili, sabit ağ
koşulları, temiz önbellek. Başarım konusundaki ölçümler bu türdendir. Değerli yanı
belirlenimci olmasıdır — iki koşum arasındaki fark, koda yapılan değişikliğe bağlanabilir.
Yanıtladığı soru şudur: bu değişiklik neyi bozdu?

**Alan verisi**, gerçek oturumlardan toplanan ölçümlerdir; toplama yöntemine **gerçek
kullanıcı izleme (real user monitoring)** denir. Tek bir sayı değil, bir dağılım verir.
Yanıtladığı soru farklıdır: kullanıcılar gerçekte ne yaşıyor?

İkisi birbirinin yerine geçmez. Laboratuvar ölçümü gerileme tespiti için, alan verisi hedef
belirlemek için kullanılır.

## Alanda Ne Toplanır

Tarayıcı, ölçütleri kendi başına biriktirir ve bir gözlemciyle sunar. Aşağıdaki kod boyama
kayıtlarını ve eşiği aşan etkileşim kayıtlarını toplar, sayfa gizlendiğinde tek bir demet
hâlinde gönderir.

```js
// olcut-toplayici.js — alan olcutlerini toplar ve tek demet halinde gonderir
const demet = { yol: location.pathname, surum: '2.4.1', olcutler: {} };

const gozlemci = new PerformanceObserver((liste) => {
  for (const kayit of liste.getEntries()) {
    demet.olcutler[kayit.name] = Math.round(kayit.startTime ?? kayit.duration);
  }
});
gozlemci.observe({ type: 'paint', buffered: true });
gozlemci.observe({ type: 'event', buffered: true, durationThreshold: 40 });

addEventListener('visibilitychange', () => {
  if (document.visibilityState !== 'hidden') return;
  gozlemci.takeRecords();
  navigator.sendBeacon('/olcut', JSON.stringify(demet));
}, { once: true });
```

Üç karar bu kodun içindedir. `buffered` seçeneği, gözlemci kurulmadan önce oluşmuş kayıtları
da getirir; ölçüm betiği geç yüklendiğinde ilk boyama kaybolmasın diye. Gönderim sayfa
kapanışında değil, sayfa **gizlendiğinde** yapılır: bir sekme kapanmadan arka plana atılıp
bir daha öne gelmeyebilir ve o durumda kapanış olayı hiç çalışmaz. Gönderim, sayfa
kaldırılırken de tamamlanan bir işaret isteğiyle yapılır.

Demete bağlam alanları eklenir: yol, uygulama sürümü, aygıt sınıfı, bağlantı türü, gezinme
türü. Bölütleme bu alanlarla yapılır ve bir sonraki bölümde görüleceği gibi, tek bir sayının
gizlediği şey burada ortaya çıkar.

Toplama her oturumda yapılmak zorunda değildir. **Örnekleme**, oturumların bir bölümünden
veri almaktır; oranı düşürmek iletim ve saklama maliyetini düşürür. Seçim oturum başına bir
kez yapılmalıdır — sayfa başına yapılırsa aynı oturumun bazı sayfaları örnekleme girer,
bazıları girmez ve oturum düzeyindeki sorular yanıtsız kalır.

## Dağılımı Okumak

Alan verisi bir dağılımdır ve dağılımı tek sayıya indirmenin birden çok yolu vardır.
Aşağıdaki modül belirlenimci bir alan örneklemi üretir — üç aygıt sınıfı, farklı paylarla ve
farklı süre aralıklarıyla — ve yüzdelik dilim hesabını verir.

```js
// alan-verisi.mjs — alan olcumlerinin belirlenimci benzetimi ve yuzdelik hesabi
export function uretec(tohum) {
  let s = tohum >>> 0;
  return () => {
    s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
    return s / 4294967296;
  };
}

export const SINIFLAR = [
  { ad: 'hizli', pay: 0.60, taban: 300, yayilim: 200 },
  { ad: 'orta', pay: 0.30, taban: 700, yayilim: 600 },
  { ad: 'yavas', pay: 0.10, taban: 1800, yayilim: 2200 },
];

export function alanOrneklemi(sayi, tohum = 42) {
  const rastgele = uretec(tohum);
  const ornekler = [];
  for (let i = 0; i < sayi; i += 1) {
    const secim = rastgele();
    let birikim = 0;
    const sinif = SINIFLAR.find((s) => (birikim += s.pay) >= secim) ?? SINIFLAR.at(-1);
    ornekler.push({ sinif: sinif.ad, sure: Math.round(sinif.taban + sinif.yayilim * rastgele()) });
  }
  return ornekler;
}

// en yakin siralama yontemi: p yuzdeliginin altinda kalan orneklerin orani en az p'dir
export function yuzdelik(degerler, p) {
  if (degerler.length === 0) return NaN;
  const sirali = [...degerler].sort((a, b) => a - b);
  const sira = Math.ceil((p / 100) * sirali.length);
  return sirali[Math.min(sirali.length, Math.max(1, sira)) - 1];
}

export function ortalama(degerler) {
  return Math.round(degerler.reduce((t, d) => t + d, 0) / degerler.length);
}
```

```js
// rapor.mjs — laboratuvar olcumu ile alan dagiliminin karsilastirilmasi
import { alanOrneklemi, yuzdelik, ortalama, SINIFLAR } from './alan-verisi.mjs';

const alan = alanOrneklemi(5000);
const sureler = alan.map((o) => o.sure);

// laboratuvar kosumu: hizli aygit, kararli ag, dagilimin ortasi
const hizli = SINIFLAR[0];
const laboratuvar = Math.round(hizli.taban + hizli.yayilim * 0.5);

console.log(`laboratuvar olcumu   ${String(laboratuvar).padStart(5)} ms`);
console.log(`alan ortalamasi      ${String(ortalama(sureler)).padStart(5)} ms`);
for (const p of [50, 75, 90, 95]) {
  console.log(`alan p${String(p).padEnd(2)}             ${String(yuzdelik(sureler, p)).padStart(5)} ms`);
}

console.log('\naygit sinifina gore p75');
for (const s of SINIFLAR) {
  const alt = alan.filter((o) => o.sinif === s.ad).map((o) => o.sure);
  console.log(`  ${s.ad.padEnd(6)} ${String(alt.length).padStart(4)} oturum   p75 = ${yuzdelik(alt, 75)} ms`);
}

console.log('\norneklem buyuklugu ve p75 kararliligi');
for (const n of [20, 100, 1000, 5000]) {
  const p75ler = [0, 1, 2, 3, 4].map((t) => yuzdelik(alanOrneklemi(n, 100 + t).map((o) => o.sure), 75));
  console.log(`  n=${String(n).padStart(4)}  ${p75ler.join('  ')}`);
}
```

```sh
node rapor.mjs
```

```
laboratuvar olcumu     400 ms
alan ortalamasi        848 ms
alan p50               471 ms
alan p75              1014 ms
alan p90              1853 ms
alan p95              2971 ms

aygit sinifina gore p75
  hizli  2918 oturum   p75 = 452 ms
  orta   1561 oturum   p75 = 1143 ms
  yavas   521 oturum   p75 = 3473 ms

orneklem buyuklugu ve p75 kararliligi
  n=  20  775  930  837  1073  900
  n= 100  1054  1027  967  1082  1049
  n=1000  978  968  1006  1017  986
  n=5000  985  1001  996  1016  992
```

## Sayıların Söylediği

Laboratuvar ölçümü 400 milisaniye. Alandaki dağılımın ortancası 471, dörtte üçlük dilimi
1014. Yani denetimli koşum, kullanıcıların iyi yarısını temsil ediyor ve kalan yarının
gerçeğini hiç göstermiyor. Bu, laboratuvar ölçümünün yanlış olduğu anlamına gelmez;
kapsamının dar olduğu anlamına gelir.

Ortalama 848 milisaniye ve hiçbir kullanıcı grubunu tarif etmiyor. Dağılımın kuyruğu uzun
olduğunda ortalama, azınlıktaki çok yavaş oturumlar tarafından yukarı çekilir; sonuç ne
çoğunluğun deneyimidir ne de en kötü durumun ölçüsü. Süre dağılımlarında ortalama okunmaz.

Yüzdelik dilim seçimi bir denge sorunudur. Medyan kullanıcıların yarısını gizler. p95 ve
üstü, tek tük uç oturumlarla — arka planda kalmış bir sekme, aşırı yüklü bir aygıt —
oynamaya başlar ve gürültülüdür. **p75** ikisinin arasındadır: dörtte üç oranında kullanıcının
altında kaldığı değeri verir ve kuyruğa yeterince duyarlıdır. Alan ölçütleri bu yüzden
yaygın olarak dörtte üçlük dilimden okunur.

Bölütleme tablosu tek sayının neyi gizlediğini gösteriyor. Aynı uygulamanın p75 değeri hızlı
aygıtlarda 452, orta sınıfta 1143, yavaş sınıfta 3473 milisaniye. Genel değer olan 1014,
bu üç gerçekten hiçbirine karşılık gelmiyor. İyileştirme kararı ancak bölütlerle verilebilir:
yavaş sınıftaki 521 oturum, genel ortalamayı düzeltmeye çalışan her işten daha çok kazanç
taşır.

Son tablo örneklem büyüklüğünün etkisidir. Yirmi oturumluk beş ayrı örneklemin p75 değerleri
775 ile 1073 arasında dolaşıyor — aynı dağılımdan gelmelerine rağmen. Bin oturumda aralık
968 ile 1017 arasına daralıyor. Küçük örneklemle ölçülen bir "iyileşme", çoğu zaman yalnızca
örneklem gürültüsüdür. Bir ölçütü bölütlere ayırmak da örneklem büyüklüğünü böler; her
bölütün kendi başına yeterli oturumu olmalıdır.

## Bütçeye Bağlamak

Başarım konusunda tanımlanan bütçe, alan verisiyle doğrulandığında anlam kazanır. Bütçe
denetimi bir teste dönüştürülebilir.

```js
// butce.test.mjs
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { alanOrneklemi, yuzdelik } from './alan-verisi.mjs';

const BUTCE = { p75: 1200, yavasSinifP75: 4000 };

test('genel p75 butcenin altinda', () => {
  const sureler = alanOrneklemi(5000).map((o) => o.sure);
  assert.ok(yuzdelik(sureler, 75) <= BUTCE.p75, `p75 = ${yuzdelik(sureler, 75)} ms`);
});

test('yavas aygit sinifi kendi butcesinin altinda', () => {
  const yavas = alanOrneklemi(5000).filter((o) => o.sinif === 'yavas').map((o) => o.sure);
  assert.ok(yavas.length >= 300, 'yeterli ornek yok');
  assert.ok(yuzdelik(yavas, 75) <= BUTCE.yavasSinifP75, `yavas p75 = ${yuzdelik(yavas, 75)} ms`);
});
```

```sh
node --test butce.test.mjs
```

```
✔ genel p75 butcenin altinda (2.985458ms)
✔ yavas aygit sinifi kendi butcesinin altinda (0.718ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 37.70275
```

İki testin ayrı bütçeleri olması bilinçlidir. Tek bir genel eşik, yavaş sınıfın bozulmasını
hızlı sınıfın iyileşmesiyle örtebilir. Bölüt başına bütçe bu takası engeller.

Toplanan verinin kapsamı da bir karardır. Ölçüt demeti kullanıcıyı tanımlayan alan
taşımamalıdır; yol bilgisi kimlik içeren parçalardan arındırılır, serbest metin hiç
gönderilmez. Ölçüm kodunun kendisinin de bir maliyeti vardır — gözlemci geri çağrıları ana
iş parçacığında çalışır ve ölçtüğü şeyi bir miktar yavaşlatır.

## Özet

- Laboratuvar verisi belirlenimcidir ve gerileme tespitine yarar; alan verisi bir dağılımdır
  ve kullanıcıların gerçekte ne yaşadığını söyler.
- Ölçütler tarayıcının gözlemcisiyle toplanır ve sayfa gizlendiğinde tek demet hâlinde
  gönderilir; örnekleme kararı oturum başına bir kez verilir.
- Süre dağılımlarında ortalama okunmaz; ortanca yarıyı gizler, çok yüksek dilimler
  gürültülüdür, dörtte üçlük dilim ikisinin arasındadır.
- Laboratuvar ölçümü 400 milisaniyeyken alan p75 değeri 1014 çıktı; bölütlere ayrıldığında
  aynı ölçüt 452, 1143 ve 3473 milisaniye oldu.
- Küçük örneklemde p75 geniş bir aralıkta dolaşır; bölüt başına bütçe, bir sınıftaki
  bozulmanın bir başkasındaki iyileşmeyle örtülmesini engeller.

## Sonraki Adım

Ölçütler uygulamanın ne kadar hızlı olduğunu söyler; çalışıp çalışmadığını söylemez. Bir
gözlemci ölçümü kaydetmeye çalışırken bir istisna fırlarsa, o oturumun süre ölçütleri gayet
iyi görünmeyi sürdürür. Kullanıcı ise boş bir ekrana bakmaktadır ve çoğu zaman kimseye haber
vermez. Son ders bu sessiz başarısızlıkları görünür kılan düzeneği ele alır: istemci
hatalarının yakalanması, gönderilmesi ve binlerce olayın tek tek değil, aynı kökene inen
gruplar hâlinde okunması.
