---
title: 'Denetim Kaydı Tasarımı'
source: 'https://academia.sh/tr/kurslar/uygulama-tespit-ve-uyumluluk/denetim-kaydi-tasarimi'
course: 'Tespit, Müdahale ve Uyumluluk'
language: tr
updated: '2026-08-17T18:06:41+00:00'
license: 'CC BY-SA 4.0'
---

# Denetim Kaydı Tasarımı

On altı soruluk bir soru kümesi üç kayıt kaynağıyla eşleştirildiğinde altısı cevaplanıyor, onu cevaplanamıyor: dördü yazılmayan alan, beşi kaynaklar arasında kurulmayan bağ, biri saklama penceresi yüzünden. Beş ek alan cevaplananı 13'e çıkarıyor, ama aynı alanlar günlük hacmi 1,45 kata çıkarıp sabit bütçedeki saklamayı 65 günden 45 güne indiriyor ve 60 günlük denetim dönemine uzanan beş soruyu yeniden cevapsız bırakıyor.

Çalışma Zamanı Güvenliği ve Sır Yönetimi kursu katmanları kurdu ve her katmanın neyi kaçırdığını
yazdı. Kaçırılan kalemin varlığı orada modelin doğrusundan okunuyordu. Gerçek bir kurumda böyle
bir doğru yoktur: kaçırılanın kaçırıldığı ancak bir kayıttan anlaşılır. Bu kurs o kaydı ölçer ve
tek soru sorar — olaydan sonra sorulacak soruların kaçı cevaplanabiliyor.

Ölçü birimi **cevaplanamayan sorudur**. Bir kayıt tasarımı "kapsamlı" ya da "yetersiz" diye
nitelenmez; önüne bir soru kümesi konur, eşleştirme koşturulur ve cevapsız kalan soru sayılır.
Aynı ölçünün ikinci yarısı bedeldir: cevaplanabilir kılmak kaç ek alan, kaç kat hacim ve kaç
kişisel veri kalemi getiriyor. Bu ders ikisini birlikte koşturur. Kaydın nasıl yazıldığı,
değiştirilemez biçimde tutulduğu ve bütünlüğünün korunduğu Arka Uç Güvenliği kursunda ölçülmüştü;
burada tekrarlanmaz, girdi olur.

- **UM1.** Örnek ağ **kurgudur**: bölgesel bir ölçüm ağının abone portalında bir yetkisiz erişim
  ihlali, dokuz servis, üç kayıt kaynağı ve 60 günlük bir denetim dönemi. Bütün sayılar bir
  modelin çıktısıdır.
- **UM2.** **Soru kümesi**, olaydan sonra sorulacak soruların veri yapısı olarak modellenmiş
  hâlidir. Her sorunun iki niteliği vardır: cevaplamak için gereken **alanlar** ve kaç gün geriye
  uzandığı.
- **UM3.** Bir soru ancak gereken alanlarının tamamı **tek bir eşlenebilir kaynak kümesi** içinde
  bulunuyorsa cevaplanır. İki ayrı kaynaktaki alan, aralarında ortak bir bağ alanı yoksa
  birleştirilemez; iki kayıt yan yana durur ama aynı olaya ait olduğu gösterilemez.
- **UM4.** Cevaplanamama üç nedene ayrılır: **alan yok** (hiçbir kaynak yazmıyor), **bağ yok**
  (alanlar var ama eşleşmiyor), **pencere** (alanlar ve bağ var ama kayıt o kadar geriye
  saklanmıyor).
- **UM5.** Saklama süresi kararla değil aritmetikle belirlenir: sabit bir saklama bütçesi günlük
  hacme bölünür. Bütçe modelde 600 GB, günlük olay sayısı 42 milyondur; 1 GB 10⁹ bayt sayılır.
- **UM6.** Kişisel veri **tür olarak** sayılır: istemci adresi, oturum tanımlayıcısı ve değişiklik
  öncesi alan değeri birer kalemdir. Her kalem saklama süresine ayrı bir üst sınır getirir.

## Soru Kümesini Şemayla Eşleştirmek

```js
// kayit-esleme.mjs — soru kumesi kayit semasiyla eslestirilir; cevaplanamayan soru
// bu kursun olcu birimidir. MODELDIR: ag, kayitlar ve sorular kurgudur.
export const BUTCE_B = 600e9, GUN_OLAY = 42e6;  // sabit saklama butcesi ve gunluk olay

// Kaynak = bir kayit akisi. `iz` alani olan kaynaklar birbirine eslenebilir;
// olmayan kaynak tek basina kalir ve alanlari baska alanla birlestirilemez.
export const KAYNAK = [
  { ad: "uygulama denetim kaydi", pay: 0.18, bayt: 240,
    alan: ["zaman", "iz", "aktor", "eylem", "sonuc"] },
  { ad: "ag gecidi erisim kaydi", pay: 0.62, bayt: 180,
    alan: ["zaman", "iz", "yol", "yontem", "durum", "istemci_ip"] },
  { ad: "veritabani degisiklik kaydi", pay: 0.20, bayt: 320,
    alan: ["zaman", "tablo", "nesne", "islem"] },
];

// Soru = [metin, gereken alanlar, kac gun geriye uzandigi]. Denetim donemi 60 gundur.
export const SORU = [
  ["hangi hesap hangi abone kaydini okudu", ["aktor", "nesne", "eylem"], 30],
  ["okuma kabul mu edildi ret mi", ["aktor", "eylem", "sonuc"], 30],
  ["istek hangi istemci adresinden geldi", ["istemci_ip", "iz"], 7],
  ["hangi hesap hangi tabloyu degistirdi", ["aktor", "tablo", "islem"], 30],
  ["degisiklik oncesi deger neydi", ["tablo", "once_deger"], 30],
  ["hangi uygulama surumu calisiyordu", ["aktor", "eylem", "surum"], 30],
  ["ayni oturumda baska ne yapildi", ["oturum", "eylem"], 7],
  ["yetki karari neydi ve neye dayandi", ["aktor", "eylem", "yetki_karari"], 30],
  ["donem basindaki ilk ret ne zaman", ["aktor", "eylem", "sonuc"], 60],
  ["donem boyunca kac abone kaydi okundu", ["nesne", "eylem"], 60],
  ["hangi uc noktalar cagrildi", ["yol", "yontem", "durum"], 30],
  ["hangi istek hangi satiri degistirdi", ["iz", "tablo", "nesne"], 60],
  ["ayni adresten kac hesap denendi", ["istemci_ip", "aktor"], 30],
  ["olaydan onceki ceyrekte ayni hesap ne yapti", ["aktor", "eylem"], 90],
  ["disari yazilan kayit kumesi neydi", ["aktor", "eylem", "nesne", "sonuc"], 60],
  ["donem boyunca kac satir degisti", ["tablo", "islem"], 60],
];

// Bir soru ancak gereken alanlarinin tamami TEK bir eslenebilir kume icindeyse
// cevaplanir; ayri kumelerdeki alanlar birlestirilemez.
export function kumeler(k) {
  const bagli = k.filter((s) => s.alan.includes("iz"));
  const tekil = k.filter((s) => !s.alan.includes("iz"));
  const birlesik = [...new Set(bagli.flatMap((s) => s.alan))];
  return [birlesik, ...tekil.map((s) => s.alan)].filter((a) => a.length);
}

export function esle(k, saklama) {
  const kume = kumeler(k), tum = new Set(k.flatMap((s) => s.alan));
  return SORU.map(([metin, alanlar, gun]) => {
    const eksik = alanlar.filter((a) => !tum.has(a));
    if (eksik.length) return { metin, gun, durum: "alan yok", eksik: eksik[0] };
    if (!kume.some((c) => alanlar.every((a) => c.includes(a))))
      return { metin, gun, durum: "bag yok", eksik: "-" };
    if (gun > saklama) return { metin, gun, durum: "pencere", eksik: "-" };
    return { metin, gun, durum: "cevaplanir", eksik: "-" };
  });
}

export const gunlukBayt = (k) =>
  k.reduce((t, s) => t + GUN_OLAY * s.pay * s.bayt, 0);
export const saklamaGun = (k) => Math.floor(BUTCE_B / gunlukBayt(k));

export const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const gb = gunlukBayt(KAYNAK) / 1e9, saklama = saklamaGun(KAYNAK);
  console.log(`model: ${KAYNAK.length} kaynak, ${SORU.length} soru, gunluk ` +
    `${gb.toFixed(2)} GB, ${BUTCE_B / 1e9} GB butce -> ${saklama} gun saklama`);
  console.log(`eslenebilir alan kumeleri: ` +
    kumeler(KAYNAK).map((c) => c.length).join(" ve ") + " alan");
  const y = gen([44, 6, 13, 13]);
  console.log("\n" + y(["soru", "gun", "durum", "eksik alan"]));
  for (const s of esle(KAYNAK, saklama)) console.log(y([s.metin, s.gun, s.durum, s.eksik]));
  const d = esle(KAYNAK, saklama);
  const say = (t) => d.filter((s) => s.durum === t).length;
  console.log(`\ncevaplanir ${say("cevaplanir")}, cevaplanamaz ` +
    `${SORU.length - say("cevaplanir")}: alan yok ${say("alan yok")}, ` +
    `bag yok ${say("bag yok")}, pencere ${say("pencere")}`);
}
```

```
model: 3 kaynak, 16 soru, gunluk 9.19 GB, 600 GB butce -> 65 gun saklama
eslenebilir alan kumeleri: 9 ve 4 alan

soru                                           gun        durum   eksik alan
hangi hesap hangi abone kaydini okudu           30      bag yok            -
okuma kabul mu edildi ret mi                    30   cevaplanir            -
istek hangi istemci adresinden geldi             7   cevaplanir            -
hangi hesap hangi tabloyu degistirdi            30      bag yok            -
degisiklik oncesi deger neydi                   30     alan yok   once_deger
hangi uygulama surumu calisiyordu               30     alan yok        surum
ayni oturumda baska ne yapildi                   7     alan yok       oturum
yetki karari neydi ve neye dayandi              30     alan yok yetki_karari
donem basindaki ilk ret ne zaman                60   cevaplanir            -
donem boyunca kac abone kaydi okundu            60      bag yok            -
hangi uc noktalar cagrildi                      30   cevaplanir            -
hangi istek hangi satiri degistirdi             60      bag yok            -
ayni adresten kac hesap denendi                 30   cevaplanir            -
olaydan onceki ceyrekte ayni hesap ne yapti     90      pencere            -
disari yazilan kayit kumesi neydi               60      bag yok            -
donem boyunca kac satir degisti                 60   cevaplanir            -

cevaplanir 6, cevaplanamaz 10: alan yok 4, bag yok 5, pencere 1
```

Üç kaynak da düzenli yazılıyor, hiçbiri kapalı değil, günde 9,19 GB kayıt üretiliyor. Buna
rağmen on altı sorunun onu cevapsız. Bu tablonun asıl bilgisi cevaplanamayan sayısı değil,
üçüncü sütundaki **nedenlerin dağılımıdır**; çünkü üç neden üç ayrı işle çözülür ve bedelleri
farklıdır.

En büyük yığın **bağ yok** satırlarındadır: beş soru. Bu sorularda gereken alanların hepsi
yazılıyor. "Hangi hesap hangi tabloyu değiştirdi" sorusunun ihtiyacı olan `aktor` uygulama
denetim kaydında, `tablo` ve `islem` veritabanı değişiklik kaydında duruyor. İki kayıt aynı
saniyede yazılmış olabilir, ama veritabanı kaydında `iz` alanı olmadığı için hangi isteğin hangi
satır değişikliğini doğurduğu gösterilemez. Yoğun bir dönemde aynı saniyede yüzlerce istek ve
yüzlerce satır değişikliği vardır; zaman damgasına dayanan bir eşleme iddia üretir, kanıt
üretmez. **Bağ alanı olmayan iki kayıt kaynağı, toplamı kadar değil, ayrı ayrı topladıkları
kadar soru cevaplar.**

İkinci yığın **alan yok**: dört soru. Bunlar tasarım eksiğidir ve yeni alan yazmakla kapanır.
Üçüncüsü tek satırdır ama en sinsisidir: `pencere`. "Olaydan önceki çeyrekte aynı hesap ne yaptı"
sorusunun bütün alanları var, bağı da var; 90 gün geriye uzandığı için cevapsız kalıyor. Bu soru
şemaya bakılarak asla bulunamaz. Şema doğru, alanlar tam, bağ kurulmuş görünür — cevaplanamama
saklama aritmetiğinden gelir ve ancak soru kümesi pencereyle birlikte modellendiğinde ortaya
çıkar.

## Cevaplanabilir Kılmanın Bedeli

Dört eksik alan ile bir bağ alanı yazılabilir. Her ek alan her kayda girer ve günlük hacmi
büyütür; bütçe sabit olduğu için hacim doğrudan saklama gününe dönüşür.

```js
// ekleme.mjs — her ek alan cevaplanan soruyu artirir ama gunluk hacmi buyutur;
// sabit butcede hacim saklama gunune, saklama gunu de cevaba geri doner. MODELDIR.
import { KAYNAK, SORU, esle, gunlukBayt, saklamaGun, gen } from "./kayit-esleme.mjs";

// Her ekleme: hangi kaynaklara hangi alan, kayit basina kac bayt, kisisel veri mi.
const EKLEME = [
  { alan: "iz", hedef: ["veritabani degisiklik kaydi"], bayt: 18, kisisel: false },
  { alan: "yetki_karari", hedef: ["uygulama denetim kaydi"], bayt: 16, kisisel: false },
  { alan: "surum", hedef: ["uygulama denetim kaydi"], bayt: 12, kisisel: false },
  { alan: "oturum", hedef: ["uygulama denetim kaydi", "ag gecidi erisim kaydi"],
    bayt: 26, kisisel: true },
  { alan: "once_deger", hedef: ["veritabani degisiklik kaydi"], bayt: 340, kisisel: true },
];

const uygula = (k, e) => k.map((s) => e.hedef.includes(s.ad)
  ? { ...s, bayt: s.bayt + e.bayt, alan: [...s.alan, e.alan] } : { ...s });

const TABAN_GB = gunlukBayt(KAYNAK) / 1e9;
const y = gen([16, 10, 6, 9, 12, 14, 9]);
console.log(y(["eklenen alan", "gunluk GB", "kat", "saklama", "cevaplanir", "cevaplanamaz",
  "kisisel"]));
let k = KAYNAK.map((s) => ({ ...s })), kisisel = 1;   // istemci_ip zaten kisisel
const satir = (ad) => {
  const gb = gunlukBayt(k) / 1e9, sak = saklamaGun(k);
  const c = esle(k, sak).filter((s) => s.durum === "cevaplanir").length;
  console.log(y([ad, gb.toFixed(2), (gb / TABAN_GB).toFixed(2), sak, c, SORU.length - c,
    kisisel]));
  return { sak, c };
};
const iz = [satir("(taban sema)")];
for (const e of EKLEME) {
  k = uygula(k, e);
  if (e.kisisel) kisisel++;
  iz.push(satir(e.alan));
}
const enIyi = iz.reduce((a, b) => (b.c > a.c ? b : a)), son = iz.at(-1);
console.log(`\nen cok cevap veren sema ${enIyi.sak} gun saklamali olan: ${enIyi.c} soru`);
console.log(`son sema ${enIyi.c - son.c} soru daha az cevapliyor, cunku saklama ` +
  `${enIyi.sak} gunden ${son.sak} gune indi ve denetim donemi 60 gun`);
console.log(`taban semadan son semaya: cevaplanan ${iz[0].c} -> ${son.c}, ` +
  `hacim ${(gunlukBayt(k) / 1e9 / TABAN_GB).toFixed(2)} kat, kisisel veri 1 -> ${kisisel} kalem`);
```

```
eklenen alan     gunluk GB   kat  saklama  cevaplanir  cevaplanamaz  kisisel
(taban sema)          9.19  1.00       65           6            10        1
iz                    9.34  1.02       64          11             5        1
yetki_karari          9.46  1.03       63          12             4        1
surum                 9.55  1.04       62          13             3        1
oturum               10.43  1.13       57           9             7        2
once_deger           13.28  1.45       45          10             6        3

en cok cevap veren sema 62 gun saklamali olan: 13 soru
son sema 3 soru daha az cevapliyor, cunku saklama 62 gunden 45 gune indi ve denetim donemi 60 gun
taban semadan son semaya: cevaplanan 6 -> 10, hacim 1.45 kat, kisisel veri 1 -> 3 kalem
```

İlk ekleme tabloda en ucuz olanıdır ve en çok kazandırandır: veritabanı kaydına 18 baytlık bir
`iz` alanı, günlük hacmi yüzde iki büyütüp cevaplanan soruyu 6'dan 11'e çıkarıyor. Tek başına
hiçbir yeni olgu kaydetmez; yalnız zaten yazılan iki kaydı birbirine bağlar. **Bir kayıt
tasarımında en yüksek getirili alan, çoğu zaman yeni bir olguyu değil, var olan iki olgunun aynı
işe ait olduğunu yazan alandır.**

Sonraki iki ekleme doğrusal ilerliyor: `yetki_karari` ve `surum`, hacmi yüzde dört büyütüp cevabı
13'e çıkarıyor. Bu satır tablonun en iyi noktasıdır ve tabloya bakmadan bulunamaz. Ek alanların
**sırası** da rastgele değildir: listedeki her alan, kayıt başına baytının o kaynağın günlük
payıyla çarpımı kadar hacim getirir. `surum` alanı 12 baytlıktır ama yalnız olayların yüzde
18'ini taşıyan kaynağa girer; `oturum` 26 baytlıktır ve yüzde 80'ine girer. İkincisi birincinin
iki katından biraz fazla yer kaplar gibi görünür, gerçekte dokuz katından fazlasını kaplar.
**Bir alanın bedeli baytıyla değil, baytının yazıldığı kayıt sayısıyla ölçülür.**

Dördüncü satır kırılmayı gösteriyor. `oturum` alanı iki yüksek hacimli kaynağa girer ve günlük
hacim 10,43 GB'ye çıkar; sabit bütçede saklama 62 günden 57 güne iner. Bu ekleme bir soruyu
cevaplanır kılar ve **60 güne uzanan beş soruyu birden cevapsız bırakır**: cevaplanan 13'ten
9'a düşer. Beşinci satırda değişiklik öncesi değerin yazılması hacmi 1,45 kata çıkarır, saklamayı
45 güne indirir ve tablo 10'da kapanır — taban şemadan yalnız dört soru daha iyi, en iyi
şemadan üç soru daha kötü.

Bu, tabloda tek bir eğri olarak duran şeyin adıdır: **daha çok kayıt, sabit bütçede daha az
cevap.** Kırılma kayıt hacmi arttığı için değil, saklama penceresi soru kümesinin uzandığı
sürenin altına indiği için olur. Denetim dönemi 60 gündür; 57 günlük saklama, kaydın kendisi
kusursuz olsa bile dönemin ilk üç gününü cevapsız bırakır.

Bedelin üçüncü sütunu tabloda tek haneli görünür ama en uzun ömürlüsüdür. Kişisel veri kalemi
1'den 3'e çıkar: oturum tanımlayıcısı ile değişiklik öncesi alan değeri, abonenin doğrudan
kimliğine bağlanabilen kalemlerdir. Bu iki alan yalnız hacim getirmez; kayda erişimi kısıtlar,
saklamaya ayrı bir üst sınır koyar ve dışarı verilen her kanıt kopyasında ayıklanmasını
gerektirir. Bir alanı "her ihtimale karşı" yazmanın bedeli bu üç sütunda birden okunur.

## Özet

- Bir kayıt tasarımı nitelemeyle değil, önüne konan soru kümesiyle ölçülür; ölçü birimi
  cevaplanamayan sorudur. Modelde 16 sorunun 10'u taban şemayla cevapsızdır.
- Cevaplanamama üç ayrı nedene ayrılır ve üçü ayrı işle çözülür: alan yok (4 soru), bağ yok
  (5 soru), saklama penceresi yetmiyor (1 soru).
- En yüksek getirili alan yeni bir olguyu değil, iki kaydın aynı işe ait olduğunu yazan bağ
  alanıdır: 18 bayt hacim karşılığında cevaplanan soru 6'dan 11'e çıkar.
- Sabit saklama bütçesinde her ek alan saklama gününe dönüşür: beş alan hacmi 1,45 kata çıkarır,
  saklamayı 65 günden 45 güne indirir.
- Daha çok kayıt daha az cevap verebilir: en iyi şema 62 günlük saklamayla 13 soru cevaplarken,
  iki alan daha eklenmiş şema 45 günle 10 soruda kalır, çünkü denetim dönemi 60 gündür.
- Bedelin kalıcı sütunu kişisel veri kalemidir: 1'den 3'e çıkan bu sayı erişim kısıtı, ayrı
  saklama sınırı ve her kanıt kopyasında ayıklama yükü doğurur.

## Sonraki Adım

Bu dersin bütün ölçümü olaydan **sonra** yapıldı: soru zaten sorulmuştu ve kayıtta cevabı olup
olmadığına bakıldı. Aynı kayıtların ikinci bir işi daha vardır — soruyu doğuran olayı, olay
sürerken haber vermek. Ama uygulama düzeyinde bir kötüye kullanım, protokol düzeyinde bir
saldırıya benzemez: istekler geçerli, oturum açık, yetki kararı çoğu zaman olumludur ve tek
anormallik iş kuralının ölçtüğü bir sayıdadır. Sonraki ders bu sayılar üzerine kurulan tespit
senaryolarını olay akışında koşturur ve eşik seçiminin iki bedelini birlikte ölçer: kaç kötüye
kullanım oturumu kaçıyor ve kaç kez boşuna uyandırılıyor.
