---
title: 'Dağıtık İzleme'
source: 'https://academia.sh/tr/kurslar/gozlemlenebilirlik/dagitik-izleme'
course: 'Gözlemlenebilirlik ve Güvenilirlik'
language: tr
updated: '2026-08-17T18:06:52+00:00'
license: 'CC BY-SA 4.0'
---

# Dağıtık İzleme

İz bağlamının elle yazılıp süreç sınırından geçirilmesi ve örnekleme oranının ölçülmesi: bağlamın taşınmadığı çağrı yerinde kopan iz sayısı, örnekleme oranının yakalanan sorunlu istek yüzdesine etkisi ve iz kaydının aralık başına hacmi.

Bağıntı kimliği bir isteğin hangi servislerden geçtiğini söylüyor, ölçütler sabit maliyetle özet
veriyor. İkisi de bir şeyi söylemiyor: sürelerin nasıl iç içe geçtiğini. Katalog çağrısı ödünç
isteğinin içinde nerede başladı, üyelik dalıyla aynı anda mı koştu, bekleme hangi çağrıda oluştu.
Bu ders o yapıyı kuran sinyali yazar.

**İz**, bir dış isteğin doğurduğu bütün işlerin ortak kaydıdır; **aralık** o kaydın tek bir
parçasıdır — bir işin başlangıcıyla bitişi arasında geçen süre ve o işin üst aralığa bağı. Buradaki
aralık, veri erişimi derslerinde geçen sorgu aralığından bütünüyle ayrı bir şeydir: orada aralık bir
anahtar kümesinin alt ve üst sınırıdır, burada bir işin zaman içindeki başlangıç ve bitiş noktasıdır.
**Yayılım**, bağlamın süreç sınırından geçirilmesidir; olmadığı yerde iz kopar.

## İz Bağlamı

Bağlam üç değerden oluşur: izin kimliği, üst aralığın kimliği ve örneklenip örneklenmediği. Üçü tek
bir başlıkta taşınır, çünkü sınırın karşısına geçebilen tek şey isteğin kendisidir.

```js
// iz.mjs — iz baglami ve aralik; baglam bir baslikta tasinir, aralik dosyaya yazilir
import { appendFileSync } from "node:fs";
export const BASLIK = "x-iz";
export const baglamCoz = (deger) => {            // "<iz>|<ust aralik>|<orneklendi>"
  if (!deger) return null;
  const [iz, ust, o] = deger.split("|");
  return { iz, ust, ornek: o === "1" };
};
export const baglamKur = (b) => `${b.iz}|${b.ust}|${b.ornek ? 1 : 0}`;
export const karma = (s) => {                    // kimligi esit dagitan karma; ornekleme karari buna dayanir
  let h = 2166136261;
  for (const c of s) { h ^= c.charCodeAt(0); h = Math.imul(h, 16777619) >>> 0; }
  return h;
};
export const orneklemeKarari = (iz, oran) => karma(iz) % 1000 < oran * 1000;

export class Iz {
  constructor(dosya, servis) { this.dosya = dosya; this.servis = servis; this.no = 0; }
  basla(ad, baglam) {
    return { iz: baglam.iz, aralik: `${this.servis}${(this.no += 1)}`, ust: baglam.ust,
      ad, t0: performance.now(), ornek: baglam.ornek };
  }
  bitir(a) {
    if (!a.ornek) return;                        // orneklenmemis aralik hic yazilmaz
    appendFileSync(this.dosya, JSON.stringify({ iz: a.iz, aralik: a.aralik, ust: a.ust,
      servis: this.servis, ad: a.ad, sure: Math.round(performance.now() - a.t0) }) + "\n");
  }
}
```

**TL4 — örnekleme kararı yalnız kökte verilir ve bağlamla taşınır.** Gerekçe: karar her serviste
ayrı verilseydi aynı izin bazı aralıkları kaydedilir, bazıları kaydedilmezdi ve yarım izler tam
izlerden ayırt edilemezdi. Kararın kökte verilmesi, kaydedilen her izin bütün olmasını sağlar; bedeli
de sonraki bölümde ölçülen şeydir.

## Bağlamı Sınırdan Geçirmek

Servisin yaptığı üç şey var: gelen başlıktan bağlamı çözmek, gelen bağlam yoksa kök olup iz kimliği
ile örnekleme kararını üretmek, ardıla giderken bağlamı kendi aralık kimliğiyle güncelleyip başlığa
koymak. Önceki derslerdeki bildirim çağrı yeri burada da bağlamı taşımıyor.

```js
// servis4.mjs — <ad> <port> [ardil...]; iz baglami surec sinirini gecer; uzun omurlu surec
import { createServer } from "node:http";
import { writeFileSync } from "node:fs";
import { Iz, BASLIK, baglamCoz, baglamKur, orneklemeKarari } from "./iz.mjs";
const [ad, port, ...ardil] = process.argv.slice(2);
const BILDIRIM = "9405";
const dosya = `iz-${ad}.txt`; writeFileSync(dosya, "");
const iz = new Iz(dosya, ad);
let oran = 1;
const bekle = (ms) => new Promise((c) => setTimeout(c, ms));
const uc = (p, u) => `http://127.0.0.1:${p}/is?uye=${u.get("uye")}&nusha=${u.get("nusha")}`;

createServer(async (istek, yanit) => {
  const u = new URL(istek.url, "http://y").searchParams;
  if (istek.url.startsWith("/oran")) {           // orani ayarla ve iz dosyasini bosalt
    oran = Number(u.get("deger")); writeFileSync(dosya, ""); yanit.end("tamam"); return;
  }
  const uye = u.get("uye"), nusha = Number(u.get("nusha"));
  let baglam = baglamCoz(istek.headers[BASLIK]);
  if (!baglam) {                                 // kok: iz kimligi ve ornekleme karari burada verilir
    const izNo = `${ad}-${nusha}`;
    baglam = { iz: izNo, ust: "", ornek: orneklemeKarari(izNo, oran) };
  }
  const a = iz.basla(`${ad}/is`, baglam);
  await bekle(ad === "katalog" && nusha % 5 === 0 ? 40 : 3);
  let durum = ad === "ucretlendirme" && uye === "4023" ? 402 : 200;
  for (const p of ardil) {
    const bas = p === BILDIRIM ? {}                // bildirim cagri yeri baglami tasimiyor
      : { [BASLIK]: baglamKur({ ...baglam, ust: a.aralik }) };
    const y = await fetch(uc(p, u), { headers: bas });
    if (y.status !== 200) durum = y.status;
  }
  iz.bitir(a);
  yanit.statusCode = durum; yanit.end("bitti");
}).listen(Number(port));
```

Bildirim servisi bağlamsız bir istek alınca kendini kök sanıyor ve kendi izini açıyor. Sonuç, kayıp
bir aralık değil, **fazladan bir iz**: ödünç isteğinin izi dört aralıkta bitiyor, bildirim işi ise
hiçbir yere bağlanmayan ayrı bir iz olarak duruyor.

## Ölçüm

Sorgu aracı iz dosyalarını okuyup aralıkları iz kimliğine göre topluyor. Ödünç kimliğiyle başlayan
izler gerçek izlerdir; bildirim kimliğiyle başlayanlar kopuk izlerdir. Sorunlu istek tanımı koddadır:
beşin katı nüshalar yavaş raftan geliyor, dört üyeden biri ödenmemiş ücret nedeniyle hata alıyor.

```js
// sor4.mjs — <oran>; iz butunlugu ve ornekleme oraninin sorunlu isteklere etkisi
import { readFileSync, statSync } from "node:fs";
const SERVIS = ["odunc", "uyelik", "katalog", "ucretlendirme", "bildirim"];
const N = 100;
const sorunlu = (n) => n % 5 === 0 || (n - 1) % 4 === 2;   // yavas raf ya da odenmemis ucret
const oran = process.argv[2];
const aralik = SERVIS.flatMap((s) =>
  readFileSync(`iz-${s}.txt`, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)));
const izler = new Map();
for (const a of aralik) { if (!izler.has(a.iz)) izler.set(a.iz, []); izler.get(a.iz).push(a); }
const kok = [...izler.keys()].filter((k) => k.startsWith("odunc"));
const kopuk = [...izler.keys()].filter((k) => k.startsWith("bildirim"));
const tam = kok.filter((k) => izler.get(k).length === 4).length;
const yakalanan = kok.filter((k) => sorunlu(Number(k.split("-")[1]))).length;
const hepsi = Array.from({ length: N }, (_, i) => i + 1).filter(sorunlu).length;
const bayt = SERVIS.reduce((t, s) => t + statSync(`iz-${s}.txt`).size, 0);
console.log(`${oran.padStart(5)}${String(aralik.length).padStart(9)}${String(kok.length).padStart(5)}` +
  `${String(tam).padStart(8)}${String(kopuk.length).padStart(10)}${`${yakalanan}/${hepsi}`.padStart(12)}` +
  `${`%${Math.round((100 * yakalanan) / hepsi)}`.padStart(7)}` +
  `${String(aralik.length ? Math.round(bayt / aralik.length) : 0).padStart(12)}`);
```

```bash
cat > kos.mjs <<'EOF'
const UYE = ["4021", "4022", "4023", "4024"];      // 4023 odenmemis ucreti olan uye
const PORT = [9401, 9402, 9403, 9404, 9405];
for (const oran of ["1.00", "0.50", "0.10", "0.02"]) {
  for (const p of PORT) await fetch(`http://127.0.0.1:${p}/oran?deger=${oran}`);
  for (let i = 1; i <= 100; i += 1)
    await fetch(`http://127.0.0.1:9401/is?uye=${UYE[(i - 1) % 4]}&nusha=${i}`);
  await new Promise((c) => setTimeout(c, 100));
  const { execSync } = await import("node:child_process");
  process.stdout.write(execSync(`node sor4.mjs ${oran}`).toString());
}
EOF
node servis4.mjs ucretlendirme 9404 &
node servis4.mjs katalog 9403 &
node servis4.mjs bildirim 9405 &
node servis4.mjs uyelik 9402 9404 &
node servis4.mjs odunc 9401 9402 9403 9405 &
sleep 1

printf '%5s%9s%5s%8s%10s%12s%7s%12s\n' oran aralik iz "tam iz" "kopuk iz" yakalanan yuzde "bayt/aralik"
node kos.mjs
pkill -f "node servis4.mjs"
```

```
 oran   aralik   iz  tam iz  kopuk iz   yakalanan  yuzde bayt/aralik
 1.00      500  100     100       100       40/40   %100         102
 0.50      246   49      49        50       22/40    %55         103
 0.10       46    8       8        14        4/40    %10         103
 0.02        2    0       0         2        0/40     %0         101
```

## Kopan İz ve Örneklemenin Bedeli

İlk satır bağlamın gerçekten sınırı geçtiğini gösteriyor: yüz dış istek, yüz iz ve her biri **tam**,
yani dört aralıklı. Ödünç aralığı üst, üyelik ve katalog aralıkları onun altında, ücretlendirme
aralığı üyeliğin altında. Önceki derslerin yanıtlayamadığı "bekleme nerede oldu" sorusu artık kaydın
kendi yapısında duruyor.

Aynı satırın yanında yüz **kopuk iz** var. Bildirim çağrı yeri bağlamı taşımadığı için o servisteki
her iş kendi kökünü açıyor: yüz istek için yüz ayrı, tek aralıklı iz. Ölçünün önemi şudur — kopan iz
eksik veri gibi görünmez, **fazla veri** gibi görünür. Kayıtlarda iki yüz iz duruyor ve hiçbir şey
bunların yüzünün aslında diğer yüzün parçası olduğunu söylemiyor. Bir isteğin yolunu izlemeye çalışan
kişi, bildirimin hiç çağrılmadığı sonucuna varır.

Alt üç satır örnekleme oranının bedelini veriyor. Oran yarıya inince yazılan aralık beş yüzden iki
yüz kırk altıya, onda bire inince kırk altıya, elliye bire inince ikiye düşüyor. Hacim oranla
neredeyse doğrusal azalıyor ve aralık başına boy 101–103 bayt aralığında sabit kalıyor: örnekleme
kaydın boyunu değil, sayısını değiştiriyor.

Karşılığında kaybedilen şey sağ sütunlarda. Kırk sorunlu isteğin tamamı ancak tam örneklemede
yakalandı. Yüzde ellilik oranda kırk sorunlu isteğin yirmi ikisi, onda birlik oranda dördü,
ellide birlik oranda **hiçbiri** yakalandı. Sayılar oranın kendisine yakın çıkıyor ve dersin
bulgusu tam olarak budur: **kökte verilen örnekleme kararı sorunlu isteği kayırmaz.** Karar
isteğin başında, henüz yavaşlayacağı ya da hata alacağı bilinmeden veriliyor; dolayısıyla sorunlu
istekler de diğerleri gibi oranla seyreltiliyor. Yüzde iki örnekleme, "izlerin yüzde ikisini
tutuyorum" demek değil, "sorunların yüzde doksan sekizini hiç görmeyeceğim" demektir.

Örnekleme kararının kökte verilmesi bir şeyi kazandırdı: kaydedilen izlerin **tamamı** tam. Yüzde
elli oranda yazılan kırk dokuz izin kırk dokuzu da dört aralıklı. Karar her serviste ayrı verilseydi
aynı hacimde çok daha fazla, ama yarım iz elde edilirdi — ve yarım iz, kopuk iz gibi, veriyi
yanıltıcı hâle getirirdi.

## Özet

- İz bağlamı üç değerden oluşuyor (iz kimliği, üst aralık, örnekleme kararı) ve tek başlıkla süreç
  sınırını geçiyor; tam örneklemede 100 istek 100 tam ize ve 400 bağlı aralığa dönüştü.
- Bağlamı taşımayan tek çağrı yeri 100 kopuk iz üretti; kopan iz eksik veri olarak değil, birbirine
  bağlanmamış fazla iz olarak görünüyor.
- Örnekleme oranı hacmi neredeyse doğrusal düşürüyor: 500, 246, 46 ve 2 aralık; aralık başına boy
  101–103 bayt sabit kaldı.
- Kökte verilen örnekleme kararı sorunlu isteği kayırmıyor: 40 sorunlu isteğin yakalananı sırasıyla
  40, 22, 4 ve 0 oldu.
- Kararın kökte verilmesi kaydedilen her izin tam olmasını sağladı: her oranda yazılan izlerin
  tamamı dört aralıklıydı.

## Sonraki Adım

Üç sinyal de artık kodda üretiliyor, ama üçü de kendi yolunu izliyor. Günlükçü kendi dosyasına
yazıyor, ölçütler bir uçta duruyor, aralıklar başka bir dosyaya düşüyor; her birinin nereye
yazacağı servis kodunun içine gömülü. Bu, uygulama kodunu tek bir toplama biçimine bağlar: yazma
yeri değişirse beş serviste de arama yapmak gerekir. Sonraki ders bu bağı keser ve bir arayüz
tasarlar. Ölçülecek olan tek şeydir: toplayıcı gerçekleştirimi değiştiğinde kaç dosyaya dokunulur.
