---
title: Bağıntılandırma
source: 'https://academia.sh/tr/kurslar/gozlemlenebilirlik/bagintilandirma'
course: 'Gözlemlenebilirlik ve Güvenilirlik'
language: tr
updated: '2026-08-17T18:06:52+00:00'
license: 'CC BY-SA 4.0'
---

# Bağıntılandırma

Üç sinyalin bağıntı kimliği üzerinden tek olayda birleştirilmesi: aynı sorunun birleştirmesiz ve birleştirmeli kaç adımda ve kaç sinyalle yanıtlandığı, birleştirmenin bir kez ödenen maliyeti ve örnekleme oranının üç sinyalli olay sayısına etkisi.

Üç sinyal de kodda üretiliyor, hiçbiri toplayıcıya bağlı değil, hepsi aynı bağıntı kimliğini
taşıyor. Ama hâlâ üç ayrı yerde duruyorlar. Bir soru sorulduğunda günlük ayrı, ölçüt ayrı, iz ayrı
okunuyor ve aralarındaki bağ her seferinde yeniden kuruluyor. Bu ders o bağı bir kez kurup saklar
ve iki yolun maliyetini karşılaştırır.

Sorulan soru üç parçalıdır ve üçü de ayrı bir sinyale düşer: bu istek **neden** başarısız oldu
(günlük), **nerede** yavaşladı (iz), bu yavaşlık **olağan mı** (ölçüt). Hedef, hem yavaş raftan
gelen hem ödenmemiş ücreti olan üyeye ait bir istektir; üç sorunun üçü de aynı anda geçerlidir.

## Üç Sinyal, Tek Kimlik

Servis üç sinyali de yazar ve üçünde de aynı bağıntı kimliği vardır. İkinci dersin kapsanmayan
çağrı yeri burada kapatılmıştır: bildirim çağrısı da bağlamı taşır, dolayısıyla kopuk iz kalmaz.

**TL6 — histogramın kovaladığı nicelik, isteğin harcadığı bildirilen iş süresidir.** Gerekçe: duvar
saati süresi koşumdan koşuma değişir ve kova sınırına yakın istekler koşuma göre yer değiştirir;
bildirilen iş her koşumda aynıdır, dolayısıyla kova payları karşılaştırılabilir kalır. Duvar saati
süresi ayrıca iz aralığında durur ve "nerede yavaşladı" sorusunu o yanıtlar.

```js
// servis6.mjs — <ad> <port> [ardil...]; uc sinyal de ayni baginti kimligini tasir
import { createServer } from "node:http";
import { appendFileSync, writeFileSync } from "node:fs";
const [ad, port, ...ardil] = process.argv.slice(2);
const SINIR = [10, 45, 150, 400];                  // bildirilen is kovalari (ms)
const kova = new Array(SINIR.length + 1).fill(0);
const sayac = { istek: 0, hata: 0 };
let oran = 1, no = 0;
const karma = (s) => { let h = 2166136261; for (const c of s) { h ^= c.charCodeAt(0); h = Math.imul(h, 16777619) >>> 0; } return h; };
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")}`;
const sifirla = () => { writeFileSync(`gunluk-${ad}.txt`, ""); writeFileSync(`iz-${ad}.txt`, ""); };
sifirla();

createServer(async (istek, yanit) => {
  const u = new URL(istek.url, "http://y").searchParams;
  if (istek.url.startsWith("/oran")) {
    oran = Number(u.get("deger")); sayac.istek = 0; sayac.hata = 0; kova.fill(0); no = 0;
    sifirla(); yanit.end("tamam"); return;
  }
  if (istek.url === "/olcut") { yanit.end(JSON.stringify({ servis: ad, ...sayac, sinir: SINIR, kova })); return; }
  const uye = u.get("uye"), nusha = Number(u.get("nusha"));
  const gelen = istek.headers["x-iz"];
  const [izNo, ust, orn] = gelen ? gelen.split("|") : [`odunc-${nusha}`, "", ""];
  const ornek = gelen ? orn === "1" : karma(izNo) % 1000 < oran * 1000;
  const aralik = `${ad}${(no += 1)}`, t0 = performance.now();
  sayac.istek += 1;
  const kendiIs = ad === "katalog" && nusha % 5 === 0 ? 80 : 3;   // bildirilen is: kosumdan bagimsiz
  await bekle(kendiIs);
  let durum = ad === "ucretlendirme" && uye === "4023" ? 402 : 200, altIs = 0;
  for (const p of ardil) {
    const y = await fetch(uc(p, u), { headers: { "x-iz": `${izNo}|${aralik}|${ornek ? 1 : 0}` } });
    const govde = await y.json(); altIs += govde.is;
    if (y.status !== 200) durum = y.status;
  }
  const is = kendiIs + altIs, sure = Math.round(performance.now() - t0);
  if (durum !== 200) sayac.hata += 1;
  let k = 0; while (k < SINIR.length && is > SINIR[k]) k += 1; kova[k] += 1;
  appendFileSync(`gunluk-${ad}.txt`, JSON.stringify({ baginti: izNo, servis: ad, uye, nusha, durum }) + "\n");
  if (ornek) appendFileSync(`iz-${ad}.txt`,
    JSON.stringify({ iz: izNo, aralik, ust, servis: ad, sure, is, kova: k }) + "\n");
  yanit.statusCode = durum; yanit.end(JSON.stringify({ is, durum }));
}).listen(Number(port));
```

## İki Yol

Sorgu aracı aynı soruyu iki kez yanıtlar. Birinci yolda üç depo ayrı ayrı okunur, her biri hedef
kimliğe göre süzülür ve üç sonuç elde hizalanır. İkinci yolda önce bütün kayıtlar bağıntı kimliğine
göre tek olayda toplanır, sonra soru o tek depodan sorulur. Adım tanımı bütün konuda olduğu gibidir:
bir dosya ya da uç okuma, bir ayrıştırma, bir süzme, bir hizalama birer adımdır.

```js
// sor6.mjs — <oran> [soru]; ayni soru once uc depodan, sonra birlesik olaydan yanitlanir
import { readFileSync } from "node:fs";
const SERVIS = ["odunc", "uyelik", "katalog", "ucretlendirme", "bildirim"];
const PORT = { odunc: 9601, uyelik: 9602, katalog: 9603, ucretlendirme: 9604, bildirim: 9605 };
const HEDEF = "odunc-15";                          // hem yavas raf hem odenmemis ucret
const [oran, kip] = process.argv.slice(2);
let adim = 0; const say = () => { adim += 1; };
const oku = (on, alan) => {                        // 5 dosya okuma + 1 ayristirma gecisi
  const k = SERVIS.flatMap((s) => { say(); return readFileSync(`${on}-${s}.txt`, "utf8").split("\n").filter(Boolean); });
  say(); return k.map((l) => JSON.parse(l)).map((r) => ({ ...r, anahtar: r[alan] }));
};
const olcutOku = async () => { const o = {}; for (const s of SERVIS) { say(); o[s] = await (await fetch(`http://127.0.0.1:${PORT[s]}/olcut`)).json(); } return o; };
const etiket = (m, k) => `[${k === 0 ? 0 : m.sinir[k - 1]},${k < m.sinir.length ? m.sinir[k] : "+"})`;

// birlestirmesiz: her sinyal ayri okunur, sonuclar elde hizalanir
adim = 0;
const g = oku("gunluk", "baginti"), iz = oku("iz", "iz"), m = await olcutOku();
const gh = g.filter((r) => r.anahtar === HEDEF); say();
const ih = iz.filter((r) => r.anahtar === HEDEF); say();
const kaynak = gh.find((r) => r.durum !== 200 && r.servis !== "odunc" && r.servis !== "uyelik");
const enUzun = ih.filter((r) => r.servis !== "odunc").sort((a, b) => b.sure - a.sure)[0];
const kokIz = ih.find((r) => r.servis === "odunc");
const pay = Math.round((100 * m.odunc.kova[kokIz.kova]) / m.odunc.istek);
say();
const yanit = `uye ${gh[0].uye}, durum ${gh[0].durum} (kaynak ${kaynak.servis}); en uzun ardil ` +
  `${enUzun.servis}; is ${etiket(m.odunc, kokIz.kova)} kovasinda, isteklerin %${pay}'si`;
if (kip === "soru") {
  console.log(`soru: ${HEDEF} istegi neden basarisiz oldu, nerede yavasladi, bu is olagan mi`);
  console.log(`${"yontem".padEnd(17)}${"adim".padStart(5)}${"sinyal".padStart(8)}  yanit`);
  console.log(`${"birlestirmesiz".padEnd(17)}${String(adim).padStart(5)}${"3".padStart(8)}  ${yanit}`);
}

// birlestirme: uc sinyal baginti kimligine gore tek olayda toplanir
adim = 0;
const g2 = oku("gunluk", "baginti"), iz2 = oku("iz", "iz"), m2 = await olcutOku();
const olay = new Map();
for (const r of g2) {
  if (!olay.has(r.anahtar)) olay.set(r.anahtar, { baginti: r.anahtar, sinyal: 2, aralik: 0 });
  const o = olay.get(r.anahtar);
  if (r.servis === "odunc") { o.uye = r.uye; o.durum = r.durum; }
  if (r.durum !== 200 && r.servis !== "odunc" && r.servis !== "uyelik") o.kaynak = r.servis;
}
for (const r of iz2) {
  const o = olay.get(r.anahtar); o.aralik += 1;
  if (o.sinyal === 2) o.sinyal = 3;
  if (r.servis === "odunc") { o.kova = etiket(m2.odunc, r.kova); o.pay = Math.round((100 * m2.odunc.kova[r.kova]) / m2.odunc.istek); }
  else if (!o.enUzun || r.sure > o.enUzunSure) { o.enUzun = r.servis; o.enUzunSure = r.sure; }
}
say();
const birlestirme = adim;
adim = 0; say(); const o = olay.get(HEDEF); say();
if (kip === "soru") {
  console.log(`${"birlestirmeli".padEnd(17)}${String(adim).padStart(5)}${"1".padStart(8)}  ` +
    `uye ${o.uye}, durum ${o.durum} (kaynak ${o.kaynak}); en uzun ardil ${o.enUzun}; ` +
    `is ${o.kova} kovasinda, isteklerin %${o.pay}'si`);
  console.log(`birlestirme maliyeti: ${birlestirme} adim, ${g2.length + iz2.length} kayit -> ` +
    `${olay.size} olay (bir kez odenir, her sorguda degil)`);
  console.log(`\n${"oran".padStart(5)}${"olay".padStart(6)}${"3 sinyalli".padStart(12)}${"2 sinyalli".padStart(12)}  eksik sinyal`);
}
const uc = [...olay.values()].filter((x) => x.sinyal === 3).length;
console.log(`${oran.padStart(5)}${String(olay.size).padStart(6)}${String(uc).padStart(12)}` +
  `${String(olay.size - uc).padStart(12)}  ${olay.size - uc === 0 ? "-" : "iz (orneklenmeyen istek)"}`);
```

```bash
cat > kos.mjs <<'EOF'
const UYE = ["4021", "4022", "4023", "4024"];      // 4023 odenmemis ucreti olan uye
const PORT = [9601, 9602, 9603, 9604, 9605];
const oran = process.argv[2];
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:9601/is?uye=${UYE[(i - 1) % 4]}&nusha=${i}`);
EOF
node servis6.mjs ucretlendirme 9604 &
node servis6.mjs katalog 9603 &
node servis6.mjs bildirim 9605 &
node servis6.mjs uyelik 9602 9604 &
node servis6.mjs odunc 9601 9602 9603 9605 &
sleep 1

node kos.mjs 1.00 && node sor6.mjs 1.00 soru
node kos.mjs 0.50 && node sor6.mjs 0.50
pkill -f "node servis6.mjs"
```

```
soru: odunc-15 istegi neden basarisiz oldu, nerede yavasladi, bu is olagan mi
yontem            adim  sinyal  yanit
birlestirmesiz      20       3  uye 4023, durum 402 (kaynak ucretlendirme); en uzun ardil katalog; is [45,150) kovasinda, isteklerin %20'si
birlestirmeli        2       1  uye 4023, durum 402 (kaynak ucretlendirme); en uzun ardil katalog; is [45,150) kovasinda, isteklerin %20'si
birlestirme maliyeti: 18 adim, 1000 kayit -> 100 olay (bir kez odenir, her sorguda degil)

 oran  olay  3 sinyalli  2 sinyalli  eksik sinyal
 1.00   100         100           0  -
 0.50   100          49          51  iz (orneklenmeyen istek)
```

## Yirmi Adım ile İki Adım

İki yanıt kelimesi kelimesine aynı. Fark maliyettedir: birleştirmesiz yol yirmi adım harcadı ve üç
sinyale ayrı ayrı gitti, birleştirmeli yol iki adım harcadı ve tek bir olaya baktı. Yirmi adımın
dağılımı da öğreticidir — on beşi yalnız okuma (beş günlük dosyası, beş iz dosyası, beş ölçüt ucu),
ikisi ayrıştırma, üçü süzme ve hizalama. Soru üç parçalı olduğu için üç depoya da gitmek zorunluydu.

Birleştirme bu işi ortadan kaldırmıyor, **bir kere** yapıyor. On sekiz adımlık maliyet çıktıda ayrıca
duruyor ve şu cümleyle işaretli: bir kez ödenir, her sorguda değil. Bin kayıt okunup yüz olaya
indirgendi. İkinci soru sorulduğunda birleştirmesiz yol yine yirmi adım harcayacak, birleştirmeli yol
yine iki. Bağıntılandırmanın kazancı tek bir sorguda değil, sorgu sayısında büyür.

Birleştirmenin mümkün olmasını sağlayan tek şey, üç sinyalin de aynı kimliği taşımasıdır. O kimlik
ikinci derste günlüğe, dördüncü derste iz bağlamına girdi; ölçüt ise kimlik taşımıyor ve taşıyamaz —
üçüncü ders bunu kimliğin toplamın içinde kaybolması olarak ölçmüştü. Ölçütün olaya katılma biçimi
bu yüzden farklıdır: tekil istek ölçüte bağlanamaz, ama isteğin **hangi kovaya** düştüğü ve o
kovanın popülasyondaki payı bağlanabilir. Birleşik olayın son alanı budur ve "bu yavaşlık olağan mı"
sorusunu yanıtlayan tek şeydir: 15 numaralı isteğin işi, isteklerin yüzde yirmisinin düştüğü kovada.
Tek başına iz "seksen milisaniye katalogda geçti" der, tek başına ölçüt "isteklerin yüzde yirmisi bu
kovada" der; ikisi birleşince "bu istek, olağan olan yavaş yüzde yirmiden biri" olur.

Alt tablo birleştirmenin sınırını veriyor. Tam örneklemede yüz olayın yüzü de üç sinyal taşıyor.
Örnekleme oranı yarıya inince olay sayısı değişmiyor — günlük her istek için yazıldığı için yüz olay
duruyor — ama elli biri yalnız iki sinyal taşıyor: izleri hiç yazılmamış. Bu olaylarda "neden" ve
"olağan mı" sorulabiliyor, "nerede" sorulamıyor. Dördüncü dersin örnekleme ölçüsü burada ikinci kez
görünüyor: seyreltilen şey iz kayıtlarının hacmi, kaybedilen şey birleşik olayların çözünürlüğü.

Üç sinyalin bölüşümü de son hâlini alıyor. **Günlük** her istekte yazılır, kimlik taşır ve "kim,
ne, neden" sorularını yanıtlar; maliyeti istek sayısıyla büyür. **İz** örneklenen isteklerde yazılır,
kimlik ve yapı taşır, "nerede" sorusunu yanıtlar; maliyeti örnekleme oranıyla ayarlanır. **Ölçüt**
kimlik taşımaz, sabit alan sayısı tutar ve "olağan mı, ne kadar sık" sorularını yanıtlar. Üçü aynı
kimlikte buluşunca tek bir kayıttan üç ayrı soruya yanıt çıkıyor.

## Özet

- Üç sinyal de aynı bağıntı kimliğini taşıyınca tek olayda birleştirilebildi: 1000 kayıt 100 olaya
  indi.
- Aynı soru birleştirmesiz 20 adım ve 3 sinyal, birleştirmeli 2 adım ve 1 sinyal harcadı; iki yanıt
  birebir aynı çıktı.
- Birleştirmenin 18 adımlık maliyeti bir kez ödeniyor; kazanç tek sorguda değil, sorgu sayısında
  birikiyor.
- Ölçüt kimlik taşımadığı için olaya tekil olarak değil, isteğin düştüğü kova ve o kovanın payı
  olarak katıldı — "bu yavaşlık olağan mı" sorusunu yanıtlayan tek alan bu oldu.
- Örnekleme birleştirmenin çözünürlüğünü sınırlıyor: oran 0,50'ye inince 100 olayın 51'i iz
  sinyalinden yoksun kaldı ve "nerede" sorusu o olaylarda kapandı.

## Sonraki Adım

Konu burada kapanıyor. Bir isteğin yolu artık görünüyor: kim istedi, nerede yavaşladı, hangi serviste
hata doğdu, bu istek popülasyonun neresine düşüyor — hepsi tek kayıttan, iki adımda. Beş süreç
arasında kaybolan istek diye bir şey kalmadı.

Kalan şey şu: bu kayıtların hiçbiri isteğin **iyi mi kötü mü** olduğunu söylemiyor. Ölçüm 15
numaralı isteğin işinin isteklerin yüzde yirmisinin düştüğü kovada olduğunu söylüyor; o yüzde
yirminin kabul edilebilir olup olmadığını söylemiyor. Ücretlendirme servisinin 402 döndürdüğünü
söylüyor; yüz istekte yirmi beş hatanın normal mi felaket mi olduğunu söylemiyor. Telemetri
**gözlem** üretir, **karar** üretmez; kararın dayanacağı şey henüz kurulmadı. Sonraki ders o eksiği
kapatır: ölçülen sinyalden bir gösterge tanımlanır, göstergeye bir hedef bağlanır ve hedefin dışarıya
verilen sözle ilişkisi kurulur.
