İçeriğe geç

LLM Gözlemlenebilirliği: OpenTelemetry GenAI ile LLMOps (2026)

LLM ve ajan sistemlerini üretimde görünür kılmak için OpenTelemetry GenAI standartları. Token, maliyet, gecikme ve kaliteyi izlemek; satıcı kilidinden kurtulmak.

SYK
Şükrü Yusuf KAYA
AI Expert · Kurumsal AI Danışmanı

TL;DR — LLM ve ajan (agent) sistemlerini üretimde çalıştırıyorsanız, gözlemlenebilirlik (observability) artık lüks değil, hayatta kalma şartı. Sahada gördüğüm en büyük sorun şu: her ekip kendi izleme (tracing) formatını kullanıyor — Langfuse bir türlü, Helicone başka türlü, LangSmith bambaşka — ve altı ay sonra sağlayıcıyı değiştirmek istediğinizde bütün gözlem katmanını sıfırdan yazmanız gerekiyor. İşte bu parçalanmayı çözmek için OpenTelemetry topluluğu, Nisan 2024'ten beri GenAI Semantic Conventions (Üretken Yapay Zeka Anlamsal Sözleşmeleri) adında bir standart geliştiriyor. Bu standart; hangi modelin çağrıldığını, kaç token harcandığını, maliyeti, gecikmeyi (latency), araç çağrılarını (tool calls) ve isteğe bağlı olarak prompt/cevap içeriğini tek tip attribute isimleriyle kaydetmeyi sağlıyor. 2026'nın başı itibarıyla sözleşmelerin çoğu hâlâ "deneysel" (experimental) statüsünde, yani API tam oturmuş değil — ama Datadog, Honeycomb, New Relic bunu destekliyor; LangChain, CrewAI, AutoGen, AG2 gibi çatılar OTel span'lerini yerel olarak üretiyor. KVKK dünyasında ise en kritik nokta prompt içeriğini loglamak: bu bir kişisel veri işleme kararıdır, opt-in ve maskeleme (redaction) olmadan yapılmaz. Bu yazıda bütün resmi sahadan örneklerle açıyorum.

Önce Dürüst Bir İtiraf: LLM Sistemlerini Kör Uçuyoruz

Kurumsal projelerde en sık karşılaştığım sahne şu: Bir ajan sistemi kuruluyor, demo harika çalışıyor, herkes mutlu, üretime alınıyor. Sonra üç hafta geçiyor ve bir kullanıcı "sistem bana saçma bir cevap verdi" diye şikâyet ediyor. Ekip lideri bana dönüp soruyor: "Şükrü, bu neden oldu?" Ve ekip, o soruya cevap veremiyor.

Neden veremiyor? Çünkü sistemin içinde ne olup bittiğini görecek hiçbir mekanizma kurulmamış. Ajan hangi araçları çağırdı? Hangi belgeleri getirdi (retrieval)? Model kaç kez çağrıldı? Hangi prompt gitti? Kaç token yakıldı? Cevap neden 14 saniye sürdü? Bunların hiçbiri kaydedilmemiş. Sistem kapalı bir kutu gibi çalışıyor ve arıza anında elimizde sadece kullanıcının şikâyeti kalıyor.

Bu, geleneksel yazılımda çok yaşamadığımız bir durum. Klasik bir web uygulamasında bir hata olduğunda log'lara bakarsınız, stack trace'i görürsünüz, sorunlu satırı bulursunuz. Ama LLM sistemleri olasılıksal (probabilistic). Aynı girdi iki farklı çıktı üretebilir. Bir ajan aynı görevi iki farklı yoldan çözebilir. Bu yüzden "ne oldu?" sorusunun cevabı, sistemin o anki iç durumunu ne kadar iyi kaydettiğinize bağlı.

Bunu bir benzetmeyle anlatayım. Diyelim ki bir uçağınız var ama üzerinde hiç gösterge yok — ne yükseklik, ne hız, ne yakıt. Uçak havadayken her şey yolunda görünüyor. Ama bir sorun çıktığında, neyin ters gittiğini anlamanın hiçbir yolu yok. Üretimdeki gözlemlenemeyen bir LLM sistemi tam olarak budur: göstergesiz bir uçak. Gözlemlenebilirlik, o gösterge panelini kurmaktır.

Bu yazının ana tezi şu: LLM gözlemlenebilirliğini bir standart üzerine kurmalısınız, kendi özel formatınız üzerine değil. Ve bugün elimizdeki en olgun, satıcıdan bağımsız (vendor-neutral) standart, OpenTelemetry'nin GenAI Semantic Conventions'ı. Gelin bunu adım adım açalım.

Kavramlar: Trace, Span, Metric ve Event

OpenTelemetry'ye yeni girenler için önce temel kavramları netleştireyim, çünkü bu dört kelimeyi karıştırırsanız gerisi karışıyor.

Trace (iz): Bir isteğin baştan sona bütün yolculuğu. Kullanıcı bir soru sordu, ajan çalıştı, üç araç çağırdı, iki kez modele gitti, bir de vektör veritabanına sordu — bütün bu olaylar zinciri tek bir trace'tir. Trace, "bu istekte ne oldu?" sorusunun tam cevabıdır.

Span (aralık): Trace'in içindeki tek bir iş birimi. Modele yapılan bir çağrı bir span'dir. Bir araç çağrısı ayrı bir span'dir. Vektör veritabanı sorgusu başka bir span'dir. Span'ler iç içe geçer (parent-child): ajan span'i ana span'dir, onun altında model çağrısı ve araç çağrısı span'leri vardır. Bir span'in başlangıç zamanı, bitiş zamanı, süresi ve attribute'ları (nitelikleri) vardır.

Metric (metrik): Zaman içinde topladığınız sayısal ölçümler. Dakikada kaç istek geldi, ortalama gecikme ne, toplam kaç token harcandı, hata oranı ne. Metric'ler tek tek isteklerle değil, toplu davranışla ilgilenir. Gösterge panelinizdeki grafikler genelde metric'lerden beslenir.

Event (olay): Bir span'in içinde belirli bir anda olan işaretli bir nokta. GenAI dünyasında en önemli event'ler prompt ve completion içeriğidir — yani modele giden metin ve modelin döndürdüğü metin. Bunlar isteğe bağlı (opt-in) olarak kaydedilir çünkü içlerinde kişisel veri olabilir.

Bu dördünü bir araya getirince şöyle bir tablo çıkıyor:

KavramNe YakalarGenAI'da ÖrnekNe Zaman Bakarsınız
TraceTüm istek yolculuğuKullanıcı sorusundan cevaba kadar bütün ajan akışı"Bu istekte tam olarak ne oldu?"
SpanTek iş birimiBir model çağrısı, bir araç çağrısı, bir retrieval"Hangi adım yavaştı / hataldı?"
MetricZaman içinde toplu ölçümSaatlik token tüketimi, p95 gecikme"Genel durum nasıl gidiyor?"
EventSpan içi işaretli anGiden prompt, gelen completion"Modele tam olarak ne gitti / ne geldi?"

Bu ayrım önemli çünkü doğru soruyu doğru veriye sormanızı sağlıyor. Bir kullanıcı şikâyetini araştırırken trace'e ve span'lere bakarsınız. Genel maliyet ve performans trendini izlerken metric'lere bakarsınız. "Model neden bu cevabı verdi?" derken event'lerdeki prompt/completion içeriğine bakarsınız.

Asıl Sorun: Herkes Kendi Dilini Konuşuyor

Şimdi neden bir standarda ihtiyacımız olduğunu açayım, çünkü mesele sadece "veri kaydedelim" değil.

Bugün LLM gözlemlenebilirliği piyasasında bir sürü güzel araç var: Langfuse, Helicone, Traceloop, LangSmith ve daha niceleri. Her biri size prompt'ları, cevapları, token'ları, maliyeti gösteren şık bir gösterge paneli veriyor. Sorun ne? Sorun şu: her biri kendi özel, birbiriyle uyumsuz formatını kullanıyor.

Langfuse bir isteği kendi "trace/observation" modeliyle kaydeder. LangSmith kendi "run" yapısını kullanır. Helicone proxy tabanlı kendi şemasını dayatır. Traceloop ise zaten OTel'e yakın durur ama yine de kendi eklemeleri vardır. Sonuç şu: bir aracı seçtiğinizde, bütün gözlem katmanınız o aracın diline göre şekillenir. SDK'sını kodunuza gömersiniz, attribute isimlerini onun kurallarına göre yazarsınız, gösterge panellerinizi onun API'sine bağlarsınız.

Altı ay sonra ne oluyor? Diyelim ki fiyat politikası değişti, ya da veri egemenliği (data sovereignty) nedeniyle verinin yurt dışına çıkmasını istemiyorsunuz, ya da başka bir aracın özellikleri daha iyi geldi. Sağlayıcıyı değiştirmek istiyorsunuz. Ve fark ediyorsunuz ki bu, basit bir "SDK'yı değiştir" işi değil — bütün enstrümantasyonunuzu (instrumentation) yeniden yazmanız gerekiyor. Bu, klasik satıcıya bağımlılık (vendor lock-in) tuzağıdır.

Sahada bir müşterimde tam olarak bunu yaşadık. Ekip önce bir izleme aracıyla başlamıştı, sistem büyüdü, sonra kurumsal güvenlik ekibi verinin kendi ortamlarında (on-prem / VPC) kalmasını şart koştu. Aracı değiştirmek gerekti. Ama bütün ajan kodunun içine o aracın çağrıları serpiştirilmişti. Göç (migration) haftalar sürdü. Eğer en baştan satıcıdan bağımsız bir standartla başlasalardı, bu geçiş bir "exporter'ı (dışa aktarıcı) değiştir" işlemine inerdi.

İşte OpenTelemetry'nin GenAI Semantic Conventions'ı tam bu sorunu çözmek için var. Fikir çok basit ama güçlü: Enstrümantasyon standart olsun, backend değiştirilebilir olsun. Kodunuz standart OTel attribute isimleriyle span üretsin (gen_ai.request.model, gen_ai.usage.input_tokens gibi), sonra o span'leri hangi backend'e göndereceğinize ayrı bir katmanda karar verin. Backend'i değiştirmek, kodu değil sadece exporter yapılandırmasını değiştirmek olsun.

GenAI Semantic Conventions Tam Olarak Neyi Standartlaştırıyor?

OpenTelemetry içinde bu işi GenAI SIG (Special Interest Group, Özel İlgi Grubu) yürütüyor ve Nisan 2024'ten beri aktif. Amaç, LLM çağrıları, ajan adımları, vektör veritabanı sorguları, token kullanımı, maliyet ve kalite metrikleri için attribute isimlerini ve tiplerini tek tipleştirmek. Kabaca dört alanı kapsıyor:

1. LLM istemci span'leri (client spans): Bir modele yapılan tek bir çağrının anatomisi. Hangi model (gen_ai.request.model), hangi sistem/sağlayıcı (gen_ai.system), istenen parametreler (sıcaklık/temperature, max token), ve en önemlisi kullanım bilgisi — girdi token sayısı (gen_ai.usage.input_tokens) ve çıktı token sayısı (gen_ai.usage.output_tokens). Bu span, "modele bir çağrı gitti ve şu kadar sürdü, şu kadar token yaktı" bilgisini standart isimlerle taşır.

2. Ajan span'leri (agent spans): Ajan tabanlı sistemlerde bir ajanın veya bir adımın çalışması. Ajanın adı, rolü, hangi görevi yürüttüğü. Çok ajanlı (multi-agent) bir sistemde her ajanın span'i, ana iş akışının altında iç içe durur, böylece "hangi ajan neyi yaptı" görünür olur.

3. Event'ler (prompt/completion içeriği): İsteğe bağlı olarak, modele giden tam prompt, dönen tam completion, araç çağrıları ve araç sonuçları. Bu, gözlemlenebilirliğin en güçlü ama aynı zamanda en hassas kısmı — çünkü burada gerçek kullanıcı metni, yani potansiyel kişisel veri var. Standart, bu içeriğin opt-in olmasını, yani varsayılan olarak kapalı gelmesini tavsiye ediyor.

4. Metric'ler: Token kullanımı, gecikme, istek sayısı gibi ölçümlerin standart metrik isimleri. Böylece farklı framework'lerden ve farklı modellerden gelen metrikleri aynı gösterge panelinde toplayabilirsiniz.

Burada dürüst olmam gereken bir nokta var: 2026'nın başı/Mart 2026 itibarıyla bu sözleşmelerin çoğu hâlâ "experimental" (deneysel) statüsünde. Yani API tam olarak stabil değil, attribute isimleri sürümler arasında değişebiliyor. Bu, "kullanmayın" demek değil — tam tersine, erkenden benimseyip topluluğa geri bildirim vermek değerli. Ama şu anlama geliyor: OTel SDK sürümlerinizi takip edin, attribute isimlerinin değişebileceğini bilin ve gösterge panellerinizi buna göre biraz esnek kurun. Deneysel demek, "işe yaramıyor" değil; "isimler henüz betona dökülmedi" demek.

Ne Loglamalı? Sahadan Bir Kontrol Listesi

"Gözlemlenebilirlik kuralım" demek kolay; asıl soru "tam olarak neyi kaydedeceğiz?" Sahada işe yarayan pratik listem şu. Her LLM/ajan isteğinde şunları yakalamaya çalışın:

  • Gecikme (latency): Toplam istek süresi ve her adımın (model çağrısı, araç çağrısı, retrieval) ayrı süresi. p50, p95, p99 ayrımıyla — ortalama yalan söyler, kuyruğa (tail) bakın.
  • Token'lar: Her çağrı için girdi ve çıktı token sayısı. Bu, hem maliyetin hem de bağlam penceresi (context window) doluluğunun temelidir.
  • Maliyet (cost): Çağrı başına maliyet. Token sayısını modelin fiyatıyla çarparak hesaplanır. Bunu span attribute'u olarak taşımak, sonradan maliyet dağılımı (attribution) yapmayı çok kolaylaştırır.
  • Araç çağrıları (tool calls): Ajan hangi aracı, hangi argümanlarla çağırdı, ne sonuç döndü. MCP (Model Context Protocol) araçları kullanıyorsanız her araç çağrısı ayrı bir span olmalı.
  • Retrieval isabetleri (retrieval hits): RAG kullanıyorsanız hangi belgeler getirildi, benzerlik skorları neydi, kaç tanesi cevaba katkı sağladı.
  • Hatalar (errors): Model zaman aşımı, rate limit, geçersiz çıktı, JSON parse hatası. Hata span'i açıkça işaretlenmeli.
  • Guardrail tetiklenmeleri: Bir güvenlik filtresi, içerik moderasyonu ya da politika kontrolü devreye girdi mi? Girdiyse hangisi, hangi girdide?

Bu listeyi bir tabloya dökeyim, çünkü her sinyalin farklı bir işe yaradığını görmek önemli:

SinyalHangi Soruyu Cevaplarİlgili OTel Alanı
Gecikme (p95/p99)"SLO'yu tutturuyor muyuz?"Span süresi, metric
Girdi/çıktı token"Maliyet ve bağlam nasıl?"gen_ai.usage.*
Çağrı başı maliyet"Para nereye gidiyor?"Span attribute, metric
Araç çağrıları"Ajan doğru araçları mı seçti?"Ajan/araç span'leri
Retrieval isabetleri"Doğru belgeleri mi getirdik?"Retrieval span'i, event
Hatalar"Nerede kırılıyor?"Span status, metric
Guardrail tetikleri"Güvenlik filtreleri çalışıyor mu?"Span event/attribute

Bu tabloyu bir müşteride pano (dashboard) tasarımının iskeleti olarak kullandık. Her satır, panoda bir grafik ya da bir uyarı (alert) kuralına dönüştü. Böylece "her şeyi loglayalım" gibi belirsiz bir hedef yerine, her sinyalin somut bir amacı oldu.

Ajan Muhakemesini Ayıklamak: Trace'in Asıl Gücü

Şimdi gelin en can alıcı senaryoya bakalım: bir ajan sisteminde hata ayıklama (debugging). Bu, gözlemlenebilirliğin gerçekten parladığı yer.

Çok adımlı bir ajan düşünün. Kullanıcı "Geçen çeyrekteki en çok satan üç ürünün stok durumunu kontrol et ve düşük olanlar için tedarik önerisi hazırla" diyor. Ajan bunu çözmek için şunları yapıyor: önce satış veritabanına sorgu atıyor (bir araç), sonra üç ürünün stoğunu ayrı ayrı kontrol ediyor (üç araç çağrısı), sonra bir tedarik politikası belgesini getiriyor (retrieval), sonra bütün bunları sentezleyip bir öneri üretiyor (model çağrısı).

Şimdi diyelim ki cevap yanlış çıktı — ajan yanlış üç ürünü seçti. Trace olmadan bu hatayı bulmak neredeyse imkânsız. Ama düzgün enstrümante edilmiş bir trace ile, adım adım açabilirsiniz:

"

Trace'e baktığınızda ajan span'inin altında iç içe span'leri görürsünüz. İlk araç çağrısında satış sorgusuna bakarsınız — hangi tarih aralığı gitti? "Geçen çeyrek"i doğru mu yorumladı? Belki ajan "geçen çeyrek"i yanlış tarihe çevirdi ve baştan yanlış ürünleri getirdi. İşte kök neden (root cause) burada, ilk span'de görünür hâle gelir.

Bu, ajan sistemlerinde son derece yaygın bir kalıp: hata genellikle en görünür yerde (son cevap) değil, zincirin ortasında bir yerde ortaya çıkar. Ajan bir aracı yanlış argümanla çağırır, o araç yanlış veri döndürür, sonraki bütün adımlar o yanlış veri üzerine inşa edilir ve sonunda cevap saçmalar. Trace olmadan sadece saçma cevabı görürsünüz; trace ile zincirin nerede koptuğunu tam olarak görürsünüz.

MCP araçları söz konusu olduğunda bu daha da kritik. MCP, ajanların dış araçlara ve veri kaynaklarına standart bir arayüzle bağlandığı bir protokol. Bir ajan üç farklı MCP sunucusuna bağlıysa ve biri yavaş cevap veriyorsa ya da hatalı veri döndürüyorsa, MCP çağrılarının her birini ayrı span olarak enstrümante etmediğiniz sürece hangisinin sorunlu olduğunu bilemezsiniz. GenAI Semantic Conventions'ın güzelliği, bu araç çağrılarını standart attribute'larla kaydedebilmenizi sağlaması — böylece hangi MCP aracının ne kadar sürdüğü, ne döndürdüğü tek tip biçimde izlenebilir hâle gelir.

Maliyet Dağılımı: "Bu Fatura Neden Bu Kadar Kabardı?"

Kurumsal LLM projelerinde bir gün mutlaka gelen soru şu: "Bu ay OpenAI/Anthropic faturası neden iki katına çıktı?" Ve gözlemlenebilirlik yoksa bu sorunun cevabı bir tahmin oyununa dönüşür.

Token kullanımını ve maliyeti span'lerde standart olarak kaydediyorsanız, maliyeti istediğiniz boyutta dilimleyebilirsiniz (attribution). Hangi özellik (feature) en çok token yakıyor? Hangi kullanıcı segmenti? Hangi model? Hangi ajan adımı? Bir müşteride tam olarak bunu yaptık: maliyeti özellik bazında dilimlediğimizde, faturanın %60'ının tek bir özellikten geldiğini gördük — ve o özellik, gereksiz yere devasa bir sistem prompt'unu her çağrıda tekrar tekrar gönderiyordu. Prompt'u sadeleştirip önbelleğe (prompt caching) alınca maliyet ciddi biçimde düştü.

Bu, gözlemlenebilirliğin doğrudan paraya dönüştüğü an. Token'ları ve maliyeti standart attribute'larla kaydetmek, sonradan "para nereye gidiyor?" sorusunu bir SQL sorgusu kadar kolay hâle getiriyor. Standart olmadan, her modelin, her framework'ün kendi maliyet formatını ayrı ayrı ayrıştırmanız gerekir.

Burada bir uyarı: çıktı token'ları genelde girdi token'larından çok daha pahalıdır. Bu yüzden maliyet dağılımına bakarken sadece toplam token'a değil, girdi/çıktı ayrımına da bakın. Bazen bir özellik az çağrılıyor ama her çağrıda çok uzun cevaplar üretiyor ve fatura orada şişiyor.

Kalite ve Kayma (Drift) İzleme: Sistem Sessizce Bozulur

Şimdi daha ince bir konuya gelelim. LLM sistemlerinin sinsi bir özelliği var: çökmeden bozulabilirler. Klasik yazılım çöktüğünde alarm çalar, herkes koşar. Ama bir LLM sistemi çökmeden, sadece cevap kalitesi yavaş yavaş düşerek bozulabilir. Buna genel olarak drift (kayma) diyoruz.

Kayma birkaç şekilde olur. Sağlayıcı arka planda modeli günceller, davranış değişir. Kullanıcıların sorduğu soruların dağılımı zamanla kayar (yeni bir ürün çıkar, yeni bir konu gündeme gelir) ve sisteminiz bu yeni dağılıma hazır değildir. Ya da RAG'daki belgeler eskir ve sistem eski bilgiyle cevap vermeye başlar. Bunların hiçbiri "hata" olarak görünmez — sistem çalışmaya devam eder, sadece giderek daha kötü çalışır.

Gözlemlenebilirlik burada erken uyarı sistemi görevi görür. Kalite metriklerini zaman içinde izlerseniz (örneğin cevap uzunluğu dağılımı, belirli anahtar kelimelerin sıklığı, guardrail tetiklenme oranı, kullanıcı geri bildirimi/beğeni oranları), kaymayı çökmeden önce yakalayabilirsiniz. GenAI Semantic Conventions bu metrikleri standart isimlerle taşımanıza izin verdiği için, farklı zaman dilimlerini ve farklı sürümleri karşılaştırmak kolaylaşır.

Sahada bunu şöyle kuruyorum: kritik metrikler için temel çizgi (baseline) belirlenir ve o çizgiden belirli bir sapma olduğunda alarm çalar. Örneğin guardrail tetiklenme oranı normalde %2 ise ve birden %8'e çıkarsa, bir şeyler değişmiş demektir — belki bir prompt injection saldırısı, belki modelin davranışı kaydı, belki kullanıcı davranışı değişti. Sebep ne olursa olsun, artık haberiniz var ve araştırabilirsiniz.

KVKK ve Prompt İçeriği: En Hassas Karar

Şimdi Türkiye bağlamında en kritik konuya geliyoruz: prompt ve completion içeriğini loglamak. Bu, teknik olduğu kadar hukuki bir karardır ve hafife alınmamalı.

GenAI Semantic Conventions, prompt ve completion içeriğini kaydetmeyi mümkün kılar ama bunu isteğe bağlı (opt-in) yapar — yani varsayılan olarak kapalıdır, siz bilinçli olarak açarsınız. Bu tesadüf değil. Çünkü modele giden prompt'un içinde ne olduğunu tam olarak kontrol edemezsiniz: kullanıcı adını, TC kimlik numarasını, sağlık bilgisini, banka hesap detayını, adresini yazmış olabilir. Bu içeriği ham hâliyle bir izleme sistemine kaydettiğiniz an, bir kişisel veri işleme faaliyeti başlatmış olursunuz.

KVKK açısından bu şu soruları doğurur:

  • Hukuki dayanak (işleme şartı): Bu kişisel veriyi izleme/hata ayıklama amacıyla işlemenin hukuki dayanağı ne? Açık rıza mı, meşru menfaat mi? Bunu belgelemeniz gerekir.
  • Veri minimizasyonu: Gerçekten prompt'un tamamını kaydetmeniz gerekiyor mu, yoksa metadata (token sayısı, gecikme, model) yeterli mi? Çoğu hata ayıklama senaryosunda ham içeriğe ihtiyaç yoktur.
  • Maskeleme (redaction): İçeriği kaydediyorsanız, hassas alanları (TC, kart numarası, telefon, e-posta) kayıttan önce maskeliyor musunuz? Bu, teknik bir zorunluluk hâline gelmeli.
  • Saklama süresi (retention): Bu izleme verileri ne kadar tutulacak? Süresiz saklamak hem risk hem de KVKK ilkelerine aykırı. Belirli bir süre sonra otomatik silinmeli.
  • Yurt dışı aktarımı: İzleme verisi (içinde kişisel veri varsa) hangi ülkedeki sunuculara gidiyor? Yönetilen (managed) bir SaaS izleme aracı verinizi yurt dışına taşıyorsa, bu KVKK'nın yurt dışı aktarım kurallarına tabidir.

İşte tam bu noktada OpenTelemetry'nin satıcıdan bağımsız mimarisi bir avantaja dönüşüyor. Çünkü OTel ile içeriği kendi ortamınızda (on-prem / VPC) tutan bir backend'e gönderebilirsiniz; verinin yurt dışına çıkmasını istemiyorsanız exporter'ı kendi altyapınıza yönlendirirsiniz. Prompt içeriğini kaydetmeden önce bir maskeleme katmanı (processor) ekleyebilirsiniz — OTel'in span processor mimarisi buna izin verir. Yani "içeriği logla" ile "içeriği loglama" arasında ikili bir seçim yapmak zorunda değilsiniz; "içeriği maskeleyerek ve kendi ortamımda logla" gibi bir orta yol kurabilirsiniz.

Sahadaki pratiğim şu: Varsayılan kapalı, gerektiğinde ve maskeleyerek aç. Üretimde ham prompt içeriğini herkese açık loglamam. Hata ayıklama gerektiğinde, sınırlı bir süre için, maskelenmiş içerikle, erişimi kısıtlı bir ortamda açarım. Bu, hem hata ayıklama ihtiyacını hem de KVKK sorumluluğunu dengeler.

Örnekleme (Sampling): Her Şeyi Kaydetmek Zorunda Değilsiniz

Ölçek büyüdüğünde bir gerçekle yüzleşirsiniz: her isteğin tam trace'ini, prompt/completion içeriğiyle birlikte kaydetmek hem pahalıdır hem de gereksizdir. İşte burada sampling (örnekleme) devreye girer.

Sampling, tüm istekler yerine bir alt kümesinin ayrıntılı izini tutmak demektir. İki ana yaklaşım var:

  • Head-based sampling (baştan örnekleme): İstek başladığı anda "bunu izleyecek miyim?" kararını verirsiniz, örneğin isteklerin %10'unu. Basit ve ucuz ama sorunlu isteği kaçırma riski var — belki tam da izlemediğiniz %90'da bir hata vardı.
  • Tail-based sampling (sondan örnekleme): İstek bittikten sonra karar verirsiniz. Böylece "hatalı olan ve yavaş olan bütün istekleri kaydet, başarılı ve hızlı olanların sadece %5'ini kaydet" gibi akıllı kurallar kurabilirsiniz. Daha güçlü ama altyapısı daha karmaşıktır.

Sahada tavsiyem şu: hataları ve anomalileri her zaman kaydedin, normal işleyişi örnekleyin. Bir istek hata verdiyse, yavaşladıysa ya da bir guardrail tetiklediyse, onun tam trace'ini istisnasız tutun — çünkü hata ayıklayacağınız istekler tam da bunlar. Sıradan, başarılı, hızlı istekleri ise örnekleyerek maliyeti kontrol altında tutun. Metric'ler zaten toplu resmi verdiği için, her isteğin ayrıntılı trace'ini tutmak gerekmez.

Bir de KVKK açısından ek bir fayda var: örnekleme, kaydettiğiniz kişisel veri miktarını doğal olarak azaltır. Ne kadar az ham içerik kaydederseniz, veri minimizasyonu ilkesine o kadar yakın olursunuz.

Ekosistem: Kim Destekliyor, Nasıl Başlanır?

İyi haber şu: bu standart teoride kalmadı, ekosistem hızla büyüyor. İzleme backend'leri tarafında Datadog, Honeycomb ve New Relic GenAI Semantic Conventions'ı destekliyor — yani OTel formatında span gönderirseniz, bu araçlar bunları anlıyor ve LLM'e özel görünümler sunuyor.

Framework tarafında ise LangChain, CrewAI, AutoGen ve AG2 gibi popüler ajan çatıları OTel span'lerini ya yerel olarak ya da enstrümantasyon kütüphaneleriyle üretiyor. Yani bu framework'lerden birini kullanıyorsanız, gözlemlenebilirliği sıfırdan yazmak zorunda değilsiniz — çoğu zaman doğru enstrümantasyon paketini ekleyip exporter'ı yapılandırmak yetiyor.

Traceloop gibi araçlar zaten OTel merkezli çalışıyor, bu yüzden geçiş sürtünmesi düşük. Langfuse, Helicone ve LangSmith gibi kendi formatı olan araçlar da giderek OTel uyumluluğu ekliyor, çünkü piyasa standarda doğru kayıyor. Bu yönde bir momentum var ve doğru tarafta durmak isterseniz standartla başlamak mantıklı.

Pratik başlangıç için sahadaki önerdiğim yol haritası şöyle:

  1. OTel SDK'sını ekleyin ve temel trace/span altyapısını kurun. Önce içerik olmadan, sadece metadata (model, token, gecikme) ile başlayın.
  2. Framework enstrümantasyonunu açın. LangChain/CrewAI vb. kullanıyorsanız ilgili OTel enstrümantasyon paketini ekleyin, ajan ve model span'leri otomatik gelsin.
  3. Bir OTel Collector kurun. Bu, span'leri toplayan ve backend'e yönlendiren ara katman. Sağlayıcıyı değiştirmek istediğinizde sadece burayı değiştirirsiniz — kodunuza dokunmazsınız.
  4. Metric ve alert kurun. Yukarıdaki sinyal tablosunu temel alarak token, maliyet, gecikme ve hata için panolar ve uyarılar oluşturun.
  5. İçerik loglamayı en son ve dikkatle açın. KVKK değerlendirmesini yapın, maskeleme katmanını ekleyin, opt-in olarak ve sınırlı erişimle açın.

Bu sırayı özellikle öneriyorum çünkü en riskli adımı (içerik loglama) en sona bırakıyor ve en çok değeri en erken (metadata gözlemlenebilirliği) veriyor.

Bugün Atacağınız Somut Adımlar

Bu yazıyı okuduktan sonra ekibinizle oturup şu üç şeyi yapın. Birincisi, mevcut LLM sisteminizde hangi izleme formatını kullandığınızı tespit edin — özel bir aracın formatı mı, yoksa OTel mi? Eğer özel bir formata kilitlendiyseniz, OTel'e geçiş planını gündeme alın; henüz gözlemlenebilirlik yoksa doğrudan OTel ile başlayın.

İkincisi, yukarıdaki sinyal tablosunu alın ve her satır için "bunu şu an kaydediyor muyuz?" diye işaretleyin. Gecikme, token, maliyet, araç çağrıları, retrieval, hatalar, guardrail'ler — hangileri eksik? Eksik olanları önceliklendirin. Genelde token ve maliyet en hızlı geri dönüşü veren yerlerdir; oradan başlayın.

Üçüncüsü, KVKK açısından prompt içeriği loglama kararınızı yazılı hâle getirin. İçeriği logluyor musunuz? Logluyorsanız hukuki dayanağınız ne, maskeliyor musunuz, ne kadar saklıyorsunuz, nerede tutuyorsunuz? Bu kararı belgelemek, hem denetimde işinizi kolaylaştırır hem de ekibin ortak bir anlayışla hareket etmesini sağlar. Eğer bugün ham prompt'ları maskesiz loglayıp süresiz saklıyorsanız, bunu bugün durdurun — bu, sessizce biriken bir risktir.

Gözlemlenebilirlik, LLM sistemlerinde "sonra hallederiz" denecek bir konu değil. Sistem üretime çıktığı andan itibaren ona ihtiyacınız var, çünkü ilk ciddi sorun geldiğinde elinizde ya bir trace olacak ya da sadece bir tahmin. Ben her zaman trace'i tercih ediyorum — ve standart bir trace'i, satıcıya bağımlı bir trace'e her gün tercih ederim.

Danismanlik Baglantilari

Bu yazıya en yakın consulting sayfaları

Bu içerikten sonraki mantıklı adım için en ilgili solution, role ve industry landing'lerini burada görebilirsin.

Yorumlar

Yorumlar

Bağlantılı Pillar Konular

Bu yazının bağlandığı pillar konular