Tüm yazılara dön

Arcade Oyuncu Ömrü: Elasticsearch ile LAI Games

LAI Games, dağınık arcade olaylarından güvenilir oyuncu ömrü ve aktiflik istedi. Kuralları ingest ve continuous transform katmanına taşıdık; dosyada olmayan maliyet yüzdesi yok.

Arcade Oyuncu Ömrü: Elasticsearch ile LAI Games

Ürün ekibi “ortalama oyuncu ömrü” ve “şu an kim aktif” dediğinde aslında yeni bir grafik istemiyor. Yüksek hacimli olaylar üzerinde doğru zaman matematiği ve Kibana’da filtre değişince bozulmayan tanımlar istiyor. LAI Games ile çalışırken mesele buydu: online arcade olaylarını Elasticsearch içinde güvenilir oyuncu alanlarına dönüştürmek.

LAI Games, lokasyon tabanlı eğlence ve dijital arcade deneyimleri sunuyor. Veri tarafında kayıt, kabin oturumu, kredi, token, ticket ve oyuna özel ekonomi var. Sorun olayları saklamak değil; “aktif” kimdir, churn öncesi ömür nasıl ölçülür gibi iş kurallarını her görselleştirmede yeniden yazmamak.

Sorun

Ekip, operasyon ve ürünün aynı dilde konuşacağı analitiklere ihtiyaç duyuyordu:

  • Ortalama oyuncu ömrü — zaman damgalarının naif ortalaması değil; kayıttan “inaktif” kabul edilene kadar geçen süre.
  • Aktif / inaktif ayrımı; böylece ömür ortalamalarına hâlâ oynayanlar karışmaz.
  • Tutarlı monetizasyon — paket fiyatları birden fazla para biriminde (USD/SGD/AUD), oyun başına token maliyetleri de oyundan oyuna farklı; panolarda doğru alan seçilmezse pasta grafikleri yanıltıyor.

Bunlar tek mapping ile gelmiyor. Ingest zamanında hesap ve oyuncu bazlı özet için continuous transform şart; aksi halde her analist farklı bir Painless yazar.

Teşhis

“Aktif” neden dokümanda hazır alan değil?

Olaylarda joined (başlangıç) ve timestamp (olay anı) var. “Aktif”, son aktivite ile ingest zamanı arasındaki farka bağlı türetilmiş bir alan.

Notların erken sürümlerinde gün bazlı farklar (ChronoUnit.DAYS, yaklaşık üç gün eşiği) vardı. Üretime yakın pipeline’larda ChronoUnit.HOURS ile saat düzeyi kullanıldı: son aktiviteden itibaren 72 saat içinde hareket varsa oyuncu aktif (time_diff_hours <= 72). Dashboard gereksinimlerinde ise churn dili takvim günleriyle yazılmıştı: üst üste üç gün aktivite yok → inaktif (ömür tarzı metrikler için). İkisi farklı katmanlara hizmet ediyor; tutarlı kalması için tek yerde hesaplanıp kuralların yazılı olması gerekir.

Oyuncu düzeyinde özet için continuous transform, stabil bir oyuncu anahtarına pivot yapıp max timestamp, max joined topluyor ve çıktıyı hedef ingest pipeline üzerinden geçiriyordu. Dosyalardaki profil: 1 dakikalık sıklık, 60 saniye sync gecikmesi, max_page_search_size 500. Lifetime örneklemine de KQL koruması kondu: soru “yerleşik oyuncular ne kadar kalır” ise son üç günde kayıt olanlar hariç tutuldu.

Çözüm

Üç katmanda standartlaştırdık:

  1. Ingest pipeline — ingest zamanı set; son aktivite ve joined alanlarını ZonedDateTime olarak parse; saat farkından is_active; inaktiflerde lifetime tarzı alanları üret (aktiflerle karışmasın).

  2. Continuous transform — olay indekslerinden analitik hedef indekse; dest pipeline ile aynı tanımlar her dokümana yazılsın.

  3. Kibana — leaderboard, token, session, payout, ticket panoları yorumlanmış alanlar üzerinden; scripted field bağımlılığı azalsın. Token pasta grafiklerinde yanlış AbsUsd kullanımı gibi alan hijyeni hataları ürün kurallarına göre düzeltildi.

Pratikte bu üç katman, “her sprintte yeni bir scripted field” döngüsünü kırdı. Ürün “unique top-up oyuncu sayısı” gibi sorular sorduğunda (aynı oyuncu bir aralıkta iki kez yükleme yapsa bile unique sayılmalı) cevap artık her görselde farklı formülle değil, üzerinde anlaşılmış alan ve KQL ile geliyordu — tanım net olunca doğrulama da net oluyor.

Operasyon panoları (DAU/MAU, stickiness, kapasite, eşzamanlı kullanım) ile ürün panoları (hangi oyun daha çok kazandırır / oynanır, token–ticket zaman serisi) aynı cluster’da yaşayabiliyordu; ama önceden hesaplanan alanlar farklıydı. Transform’u her şeyi “bir mega dashboard”a yığmak için değil, oyuncu durumu gibi paylaşılan sözleşmeleri sabitlemek için kullandık. AU / US / SG kırılımları ve çoklu para birimi toplama da aynı hijyen meselesinin parçası: yanlış alan seçimi, yanlış kur formülü kadar hızlı bozar.

_ingest/pipeline/_simulate ile kuralları önce küçük örnek dokümanlarda doğrulamak, üretim transform’una bağlamadan önce birim ve eşik hatalarını yakaladı. Erken simulate örneğinde gün bazlı eşik kullanıldığında ingest farkı üç günü aşınca is_active: false ve joined→timestamp farkından lifetime üretildiği görülüyordu; üretimde saat birimine geçince aynı iş kuralını 72 saat dilinde konuşmak mümkün oldu. Bu tür iterasyonları Kibana’da “görsel düzeltene kadar dene” yerine pipeline katmanında yapmak, hem mühendis hem analist zamanını kurtarıyor.

Dışa dönük metinde dahili indeks adlarını ve cluster URL’lerini maskeliyorum. Desenin kendisi için Elasticsearch transforms dokümantasyonu iyi bir referans; burada mesele arcade olaylarına uygulanışı. Aynı disiplini arama ve gözlemlenebilirlik projelerinde de uyguluyoruz: iş kuralı bir yerde, tüketen panolar birden fazla yerde.

Sonuçlar

Ham dosyalarda dolar cinsinden cluster faturası veya yüzde maliyet düşüşü yok; uydurmuyorum. Kanıtlanabilir profil:

  • Aktiflik kuralı: son aktivite → ingest ≤72 saatis_active: true.
  • Transform profili: 1 dk sıklık, 60 sn sync, max_page_search_size 500.
  • İş dili: lifetime tarzı metriklerde üst üste 3 gün aktivite yokluğu inaktif.
  • Ekonomi referansları: çoklu para biriminde paket fiyat noktaları ve oyuna göre değişen token maliyetleri — KPI’ları ürün ekonomisiyle uzlaştırmak için kullanıldı (kesin rakamlar müşteri materyallerinde kalır).

Bunlar müşteri notlarında olduğu için yazılabilir. Bulut faturası veya transform sıklığı A/B’si ayrı ölçüm işi — başlık süslemek için uydurulmaz.

Öğrendiklerimiz

  • Aktif ve lifetime tanımlarını tek katmanda kilitleyin; panolar alan okusun, script yeniden yazmasın.
  • Saat ve gün dilimlerini karıştırmayın; biri recency, diğeri churn dili olabilir — ikisini de belgeleyin.
  • Continuous transform, olay akışından oyuncu başına “son durum” üretmek için doğru araçtır; dest pipeline disiplini şarttır. 1 dk / 60 sn / 500 gibi ayarlar “garanti performans” değil; tazelik–yük dengesi için kayıt altına alınan kollardır.
  • Görselleştirme hatalarının çoğu alan seçiminden gelir; token/para birimi alanlarını ürün kurallarıyla doğrulayın. Bir oyun örneğinde notlar, mutlak token alanı ile oyuncu kredisi alanını yan yana koyarak pasta ile zaman serisinin neden farklı göründüğünü çözmüştü — Elasticsearch “bozuk” değildi, sözleşme eksikti.
  • Evidence’da olmayan metrik yok. Güvenilirlik, uydurma yüzdeden değerlidir. LAI Games dosyalarında maliyet yüzdesi olmadığı için yazmıyoruz; bunu bilinçli bir red olarak okuyun.

Elasticsearch üzerinde oyuncu durumu, e-ticaret arama veya gözlemlenebilirlik fark etmeksizin aynı ilkede duruyor: tanımı bir kez yaz, her yerde oku. Arcade ölçeğinde olay hacmi bu disiplini zorunlu kılar; aksi halde her yeni pano yeni bir “doğru” üretir.

Elasticsearch analitik mimarisi için: searchali.com.

Arama altyapınızı sınırların ötesine taşıyalım.

Yüksek performanslı ve hatasız bir arama deneyimi için hemen iletişime geçin.