İçeriğe geç
academia.sh

Ders 15 / 16

Hat Gözlemlenebilirliği

Çalışan bir hattın üstüne konan üç göstergenin ne gördüğünün sayılması: tazelik, hacim ve şema göstergeleri toplam 14 gözlem noktasına bakar ve hiçbiri bir hücrenin değerini okumaz, bu yüzden altı bozulma sınıfından yalnız değeri değiştiren birim değişimi üçüne de görünmez kalır. Hacim üç sınıfı aynı dönemde gösterir, şema iki sınıfı aynı dönemde, tazelik alan adı değişimini bir dönem sonra; gösterge en çok bir dönem ateşlerken bozulma iki dönem sürer ve iki sınıfta gösterge ateşlemesine karşın sunum hiç değişmez. Bant 0,05'ten 0,30'a genişledikçe hacmin gördüğü sınıf 3'ten 0'a iner ve bandın gizlediği en büyük kayıp 10 satırdan 60 satıra çıkar; tazelik toleransı 0 olduğunda gecikme 1 dönemden 0'a iner ama sağlam hatta bir yanlış alarm doğar.

İçindekiler

Bir önceki ders düşen görevi ele aldı: yeniden deneme yinelemeye dayanıklı olmayan hatta satır çoğaltıyor, yarım yazılan bölüm sunumu her bölgede yanlışlıyor, atomik yazım bölümü hiç yazmayarak sapmayı −2,89 ile +12,80 arasına indiriyordu. Üç derste hat çalıştırıldı ve düştüğünde ne olacağı yazıldı.

Düşen görev kendini haber verir. Bu dersin konusu düşmeyen koşumdur: bütün görevler yeşil biter, çizge tamamlanır ve hat yanlış veri taşır. Orada tek kanıt hattın üstüne konan göstergedir. Ders üç tanesini kurar — tazelik, hacim ve şema değişimi — ve tek soru sorar: Veri Mühendisliğine Giriş kursunun altı bozulma sınıfını bunlar kaç dönem sonra gösterir, hangisini hiç göstermez.

  • OR41. Kaynak, beş aşamalı hat, altı bozulma sınıfı ve üç gösterge kurgudur ve ders içinde üretilir. Hiçbir orkestratör, gözlemlenebilirlik ürünü ya da veri deposu çağrılmaz. Tohum 20260218.
  • OR42. Gözlemlenebilirlik (observability) yordamı — ölçüt toplama, iz, günlükleme, uyarı tasarımı — Backend Geliştirme müfredatındaki Gözlemlenebilirlik ve Güvenilirlik, DevOps ve Platform Mühendisliği müfredatındaki Gözlemlenebilirlik ve İşletim ve Yapay Zekâ Mühendisliği müfredatındaki Yapay Zekâ Ajanları kurslarında ölçüldü; tekrarlanmaz. Buradaki tek ölçü veri hattına özgü üç göstergenin gecikmesidir.
  • OR43. Altı bozulma sınıfı Veri Mühendisliğine Giriş kursundan girdi alınır. Her biri yalnız 2026-07 dönemini bozar; kalan on bir dönem sağlamdır.
  • OR44. Tazelik (freshness), sunumdaki en yeni dönemin çalışılan dönemden en çok bir dönem geride olması; hacim, dönem satır sayısının önceki üç dönemin ortancasından bant kadar sapmaması; şema değişimi (schema evolution), alan adı ve tür çiftlerinin kayıtlı imzayla aynı kalmasıdır. Tolerans, bant ve imza birer seçimdir; son bölüm onları sayar.
  • OR45. Kayma (drift) girdinin dağılımının zamanla değişmesidir ve Makine Öğrenmesi ve Veri Bilimi müfredatındaki Model Değerlendirme, Yorumlanabilirlik ve Etik kursunda ölçüldü. Üç gösterge kaymayı görmez; nedeni ilk bölümde sayılır.
  • OR46. Taban çizgisi orkestrasyonsuz koşumdur: gösterge yok, görülen sınıf 0, gecikme tanımsız. Gecikme dönem olarak yazılır.

Göstergelerin Baktığı Yüzey

Aşağıdaki blok ortak tanımı kurar ve tek bir şey basar: üç göstergenin koşumdan bağımsız ölçüsü, yani her birinin baktığı nitelik sayısı. Bu sayı hat hiç çalıştırılmadan bilinir.

# KURGUDUR. Olcum aginin sayac okumalari , bes asamali hat , alti bozulma sinifi
# ve uc gosterge ders icinde uretilir; hicbir orkestrator , gozlemlenebilirlik
# urunu ya da veri deposu cagrilmaz. Tohum 20260218.
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


BOZULMA = ["gec_gelen", "yinelenen", "sema_degisti", "birim_degisti", "eksik_bolum", "kayan_tip"]


def boz(kayit, sinif, donem="2026-07"):
    """Tek bir donemi bozar , kalan donemler saglam kalir."""
    yeni, sayac = [], 0
    for k in kayit:
        if k["donem"] != donem:
            yeni.append(k)
            continue
        if sinif == "gec_gelen":
            if k["abone"] <= "A040":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "yinelenen":
            yeni.append(k)
            if k["abone"] <= "A060":
                yeni.append(dict(k))
                sayac += 1
        elif sinif == "sema_degisti":
            y = dict(k)
            y["endeks_degeri"] = y.pop("endeks")
            sayac += 1
            yeni.append(y)
        elif sinif == "birim_degisti":
            y = dict(k)
            y["endeks"] = k["endeks"] * 1000
            y["birim"] = "m3"                       # ETIKET DEGISMEDI
            sayac += 1
            yeni.append(y)
        elif sinif == "eksik_bolum":
            if k["bolge"] == "kuzey":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "kayan_tip":
            y = dict(k)
            y["endeks"] = str(k["endeks"])
            sayac += 1
            yeni.append(y)
    return yeni, sayac


def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad not in gor:
            gor.add(ad)
            tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


def a4_ozet(kayit):
    top = {}
    for k in kayit:
        ad = (k["bolge"], k["donem"])
        top[ad] = top.get(ad, 0) + k["m3"]
    return top, 0


def a5_sun(ozet):
    bolge = {}
    for (b, d), v in ozet.items():
        bolge.setdefault(b, []).append(v)
    return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0


# ---- UC GOSTERGE. Her biri kaydin bir izdusumune bakar.
KAYITLI = {("abone", "str"), ("donem", "str"), ("bolge", "str"), ("tip", "str"),
           ("endeks", "int"), ("birim", "str")}
NITELIK = {"tazelik": 1, "hacim": 1, "sema": 2 * len(KAYITLI)}
print(f"kaynak {200 * len(DONEM)} satir x {len(KAYITLI)} alan ="
      f" {200 * len(DONEM) * len(KAYITLI)} hucre")
print("gosterge  baktigi sey                      nitelik")
print(f"tazelik   sunumdaki en yeni donem         {NITELIK['tazelik']:>7}")
print(f"hacim     donem basina satir sayisi       {NITELIK['hacim']:>7}")
print(f"sema      alan adi ve turu ciftleri       {NITELIK['sema']:>7}")
print(f"toplam gozlem noktasi {sum(NITELIK.values())} ,"
      f" degeri okunan hucre 0")
kaynak 2400 satir x 6 alan = 14400 hucre
gosterge  baktigi sey                      nitelik
tazelik   sunumdaki en yeni donem               1
hacim     donem basina satir sayisi             1
sema      alan adi ve turu ciftleri            12
toplam gozlem noktasi 14 , degeri okunan hucre 0

Kaynak 14400 hücre taşıyor, üç gösterge 14 noktaya bakıyor. Önemli olan son satırdır: değeri okunan hücre sıfır. Tazelik bir dönemin var olup olmadığını, hacim satırların kaç tane olduğunu, şema alanların adını ve türünü sorar. Hiçbiri bir sayacın kaç metreküp yazdığına bakmaz; kayma görülmemesinin nedeni de budur.

Bu satır koşumdan önce bir kestirim verir: altı sınıftan yalnız değeri değiştiren biri varsa, o sınıf üç göstergenin hiçbirine görünmeyecektir. Listede tanıma uyan bir sınıf vardır. birim_degisti endeksi bine katlar, birim etiketini m3 bırakır, alan adını ve türünü korur, satır sayısını değiştirmez. Kestirim odur; koşum onu sınar.

Kaç Dönem Sonra

Aşağıdaki blok hattı on iki dönem boyunca dönem dönem koşturur ve her dönemden sonra üç göstergeyi değerlendirir. Sınıf başına üç gecikme, ilk gösteren gösterge, bozulmanın kaç dönem sürdüğü ve sunumun değişip değişmediği basılır.

# Bu blok ilk bloktaki kaynak_uret , boz , a1..a5 ve KAYITLI tanimlarini surdurur.
KAYNAK = kaynak_uret()
GOSTERGE = ("tazelik", "hacim", "sema")
BOZUK = "2026-07"


def imza(kayitlar):
    return set((a, type(v).__name__) for k in kayitlar for a, v in k.items())


def ortanca(x):
    y = sorted(x)
    return y[len(y) // 2]


def ozetle(kayitlar):
    v, _ = a1_ayikla(kayitlar)
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    oz, _ = a4_ozet(v)
    return oz


def izle(kayitlar, band=0.05, tol=1):
    """Her donem hat kosturulur ve uc gosterge degerlendirilir. Tazelik tol donem
    tolerans tasir; hacim son uc donemin ortancasindan sapmaya bakar."""
    ates, gecmis = {g: [] for g in GOSTERGE}, []
    for i, d in enumerate(DONEM):
        bu = [k for k in kayitlar if k.get("donem") == d]
        oz = ozetle([k for k in kayitlar if DONEM.index(k["donem"]) <= i])
        if i - max([DONEM.index(x) for _, x in oz], default=-1) > tol:
            ates["tazelik"].append(d)
        if len(gecmis) >= 3:
            t = ortanca(gecmis[-3:])
            if abs(len(bu) - t) / t > band:
                ates["hacim"].append(d)
        gecmis.append(len(bu))
        if imza(bu) != KAYITLI:
            ates["sema"].append(d)
    return ates


def gecikme(donemler):
    """Kac donem sonra gosterdi. Hic gostermediyse tire."""
    sonra = [x for x in donemler if x >= BOZUK]
    return DONEM.index(sonra[0]) - DONEM.index(BOZUK) if sonra else "-"


TABAN = ozetle(KAYNAK)
TABAN_SUN, _ = a5_sun(TABAN)
print(f"saglam hat: ateslenen gosterge yok , sunum {TABAN_SUN}")
print("\nbozulma         tazelik  hacim  sema   ilk gosterge  etkilenen donem  sunum")
for s in BOZULMA:
    v, _ = boz(KAYNAK, s)
    a, oz = izle(v), ozetle(v)
    sun, _ = a5_sun(oz)
    g = {x: gecikme(a[x]) for x in GOSTERGE}
    goren = [(v2, x) for x, v2 in g.items() if v2 != "-"]
    etki = [d for (b, d) in set(TABAN) | set(oz) if TABAN.get((b, d)) != oz.get((b, d))]
    print(f"{s:<14} {g['tazelik']:>8} {g['hacim']:>6} {g['sema']:>5}"
          f"   {(min(goren)[1] if goren else 'yok'):<13} {len(set(etki)):>15}"
          f"  {'degisti' if sun != TABAN_SUN else 'ayni'}")

print("\nbant  gizledigi en buyuk kayip  hacmin gordugu sinif")
for band in (0.05, 0.10, 0.20, 0.25, 0.30):
    goren = [s for s in BOZULMA if izle(boz(KAYNAK, s)[0], band=band)["hacim"]]
    print(f"{band:<5} {int(band * 200):<24} {len(goren)}  {goren}")

print("\ntolerans  saglam hatta yanlis alarm  sema_degisti gecikmesi")
for tol in (0, 1, 2):
    yanlis = izle(KAYNAK, tol=tol)["tazelik"]
    bozuk = izle(boz(KAYNAK, "sema_degisti")[0], tol=tol)["tazelik"]
    print(f"{tol:<9} {len(yanlis):<26} {gecikme(bozuk)}")
saglam hat: ateslenen gosterge yok , sunum {'merkez': 1321.45, 'kuzey': 1212.55, 'dogu': 881.36, 'bati': 833.09, 'guney': 1065.55}

bozulma         tazelik  hacim  sema   ilk gosterge  etkilenen donem  sunum
gec_gelen             -      0     -   hacim                       2  degisti
yinelenen             -      0     -   hacim                       0  ayni
sema_degisti          1      -     0   sema                        2  degisti
birim_degisti         -      -     -   yok                         2  ayni
eksik_bolum           -      0     -   hacim                       2  degisti
kayan_tip             -      -     0   sema                        0  ayni

bant  gizledigi en buyuk kayip  hacmin gordugu sinif
0.05  10                       3  ['gec_gelen', 'yinelenen', 'eksik_bolum']
0.1   20                       3  ['gec_gelen', 'yinelenen', 'eksik_bolum']
0.2   40                       2  ['yinelenen', 'eksik_bolum']
0.25  50                       1  ['yinelenen']
0.3   60                       0  []

tolerans  saglam hatta yanlis alarm  sema_degisti gecikmesi
0         1                          0
1         0                          1
2         0                          -

Sağlam hatta hiçbir gösterge ateşlemiyor; yanlış alarm sıfır ve sunum ortak tanımın sunumudur.

Hacim sütunu üç sınıfı aynı dönemde gösteriyor: gec_gelen 40 satır eksiltiyor, eksik_bolum 46, yinelenen 60 ekliyor, üçü de 0,05 bandını aşıyor. Hacim ne olduğunu söylemiyor, yalnız sayının kaydığını söylüyor; 46 satırın hangi bölgeden düştüğünü göstermez, çünkü bölge kırılımı taşımaz. Onu K01’in dönem duyarlı bütünlük denetimi söyler.

sema_degisti iki gösterge tarafından iki ayrı dönemde gösteriliyor. Şema aynı dönemde ateşler, imzada endeks yerine endeks_degeri vardır. Tazelik bir dönem sonra ateşler: alan adı değişen 200 satır ayıklamada düşer, o dönemin sunum hücresi hiç oluşmaz, tazelik bir dönem tolerans taşıdığı için 2026-07’de susar ve 2026-08’de konuşur. Tek olay, iki gösterge, bir dönem fark.

kayan_tip yalnız şemaya görünür ve sunum değişmez: metne dönen endeks tüketim hesabında tamsayıya geri çevrilebiliyor. Gösterge ateşler, hasar yoktur. yinelenen de öyledir: hacim ateşler, tekilleştirme aşaması 60 kopyayı yutar, etkilenen dönem 0’dır.

birim_degisti satırında üç tire ve yok yazıyor. Kestirim tuttu. Sunum da değişmiyor; K01 mekanizmasını ölçtü — ara katmanda iki dönem yaklaşık 1,8 milyar oynar ve birbirini götürür, on iki dönemin ortalaması aynı kalır. Etkilenen dönem sütunu yine de 2 yazar: iki özet hücresi çöptür. Bunu gören tek şey K01’in dağılım denetimidir ve o bir hat göstergesi değil, bir veri kalitesi denetimidir. Farkı tek sözcükle söylenir: değere bakar.

En sert okuma sütunlar arasındadır. Gösterge en çok bir dönem ateşler, bozulma iki dönem sürer. Nedeni çizgenin dönemler arası kenarıdır: tüketim bir önceki dönemin okumasına bağlı olduğu için 2026-07’de kaybolan 40 abonenin 2026-08 satırı da hesaplanamaz. Uyarı sustuktan bir dönem sonra hat hâlâ bozuktur. Ters yön daha da kötüdür: yinelenen ile kayan_tip’te gösterge ateşler ve hasar sıfırdır, birim_degisti’de gösterge susar ve iki dönem çöptür. Ateşleme ile hasar arasında bağ yoktur.

Bant ve Tolerans Birer Seçimdir

Son iki tablo göstergenin kendi bedelini sayar. Hacmin gördüğü sınıf 0,05 ve 0,10 bandında üç, 0,20’de iki, 0,25’te bir, 0,30’da sıfırdır. İkinci sütun bandın gerçek anlamıdır: bir dönem 200 satır taşıdığı için bant, gizlediği en büyük kayıptır — 0,05 on satıra kadar, 0,30 altmış satıra kadar sessiz kalır. Kümenin çözünürlüğü bir satır, yani 0,005’tir; bandın altındaki her şey görünmezdir ve bu bir kusur değil, tanımın kendisidir.

Bu kurgu kaynakta dar bant bedavadır, çünkü her dönem tam 200 satır taşır ve sağlam hatta yanlış alarm sıfırdır. Gerçek bir kaynakta dönem satır sayısı oynar ve bant tam da yanlış alarmı (false positive) azaltmak için genişletilir. Genişledikçe üç sınıf boy sırasıyla kaybolur: önce 40 satırlık gec_gelen, sonra 46 satırlık eksik_bolum, en son 60 satırlık yinelenen. Bant, yanlış alarm ile görmezliğin takas edildiği yerdir ve para birimi satırdır.

Tolerans tablosu aynı takası tazelikte, daha çıplak biçimde gösterir. Tolerans 0’da sema_degisti gecikmesi 1 dönemden 0’a iner; bedeli sağlam hatta bir yanlış alarmdır, çünkü ilk dönem öncesi olmadığı için tüketim üretmez ve toleranssız tazelik bunu boş sunum sayar. Tolerans 2’de yanlış alarm sıfır kalır ama tazelik hiçbir şey görmez, sütun tiredir. Üç ayar, üç ayrı gösterge.

Şema göstergesinin böyle bir satırı yoktur. Eşiği olmadığı için ayarlanamaz: imza ya tutar ya tutmaz. Karşılığında yalnız imzaya yazılmış olanı görür, birim_degisti imzayı bozmadığı için ona kördür. Ayarlanabilir gösterge neyi kaçıracağını seçer; ayarlanamaz gösterge neyi göreceğini tanımıyla baştan sabitler.

Özet

  • Üç gösterge toplam 14 niteliğe bakar ve hiçbiri bir hücrenin değerini okumaz; bu koşumdan bağımsız ölçü, yalnız değeri değiştiren birim_degisti sınıfının görünmez kalacağını önceden söyler ve koşum bunu doğrular.
  • Hacim gec_gelen, eksik_bolum ve yinelenen’i aynı dönemde gösterir; şema sema_degisti ve kayan_tip’i aynı dönemde; tazelik sema_degisti’yi bir dönem sonra, çünkü bir dönem tolerans taşır.
  • Gösterge en çok bir dönem ateşler, bozulma iki dönem sürer: tüketim bir önceki dönemin okumasına bağlıdır. yinelenen ve kayan_tip’te gösterge ateşlerken hasar 0 dönemdir, birim_degisti’de gösterge susarken hasar 2 dönemdir.
  • Bant 0,05’ten 0,30’a genişledikçe hacmin gördüğü sınıf 3’ten 0’a iner ve gizlenen en büyük kayıp 10 satırdan 60 satıra çıkar; bant, yanlış alarm ile görmezliğin satır cinsinden takasıdır.
  • Tazelik toleransı 0’a indirildiğinde gecikme 1 dönemden 0’a iner ama sağlam hatta bir yanlış alarm doğar; tolerans 2’de yanlış alarm yoktur ve gösterge hiçbir şey görmez.

Sonraki Adım

Bu dersteki her sayı tek bir sessiz varsayıma yaslandı: hattı çalıştıran kod hep aynı koddur, hep aynı ayarla ve hep aynı veri kümesi üzerinde koşar. Gösterge bandı 0,05’ti, tolerans 1’di, yüklenen dönem sayısı on ikiydi — hiçbiri hattın kodunda yazılı değil, koşumun çevresinde duruyordu. Sonraki ders aynı hat kodunu iki ortamda koşturur ve ortam ayarı değiştiğinde sunumun ne kadar saptığını ölçer; ardından, koşumun üstüne bir sürüm damgası yazılmadığında elinizdeki raporun hangi kodla üretildiğinin neden bilinemez olduğunu sayar.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat