Yazılımlarımızı Nasıl İzliyor ve Kontrol Altında Tutuyoruz?

“Şans, iyi bir plandan arta kalandır.”
Larry King

Amerikalı ünlü bir sunucunun sözüyle başlamak doğru olur diye düşündüm. Sonrasında ise aklıma bir Türk atasözü geldi, hani şu “kervanı yola koyalım, elbet bir yön buluruz” temalı sözümüz.

Sıcak iklim toplumu olmamızdan mütevellit olduğunu düşündüğüm, heyecanlı ve hızlı başlangıçlara müsait yapımız her alanda olduğu gibi bizim sektörümüzde de çokça meşhurdur. Planlı yaşamayı pek sevmeyiz, kontrol altında tutmak genlerimizde yoktur. Düşünür ve canlandırırız. Yazılım projelerinde de çoğunlukla bu yöntemin uygulandığına şahit oldum, hatta yöntemin bir parçası olmuşluğum bile vardır. Zaman ve müşteri baskısı, maliyet, kalite kriterleri gibi dinamikler de bu atakların genel tetikleyicileridir.

Hürriyet’te geçmişten bugüne yüzlerce proje geliştirildi ve geliştirilmeye devam ediyor. Bunların bazıları metodolojiler ışığında doğdu, büyüdü ve olgunlaştı. Bazıları akşamdan sabaha yayında idi. Kimisi yayın hayatını çoktan sonlandırmışken kimisi ise gelişerek/büyüyerek yoluna devam ediyor. Peki bu projelerde neler olup bittiğini, projelerin nasıl cevaplar verdiğini, hala nefes alıp almadığını nasıl kontrol ediyoruz? Bu yazıyı yazarken denk geldiğim bir görselle konuya giriş yapmak isterim:

Kabul ediyorum, şaşırtıcı bir cevap olmadı. Zaten amacım, bu satırları okuyan kişileri şaşırtmak da değildi. Amacım, kısa bir süre önce geliştirmesini tamamladığımız ve entegrasyon süreci devam eden “kayıt altında tutma — nam-ı diğer log —” sistemimizdeki yenilikleri ve bu süreçteki deneyimlerimizi değerli meslektaşlarımız ile paylaşabilmek.

Girişte bahsi geçen konu ise tam bu noktada asıl konumuz ile kesişiyor.

İçinde bulunduğumuz ekosistemdeki yazılımlar nasıl takip ediliyor ve yeni sisteme neden ihtiyaç duyduk?

Samimi bir itirafla başlamak doğru olur. Bizler de “önce log” diyerek projelerimize başlamadık. Yazdığımız kodun ürettiği çıktıyı bazen bir veritabanına yazdık, bazen bir metin dosyasına. Sonra bu metodu biraz evirdik, bir iki parametre alır hale getirdik ve sabit bir lokasyona kayıt etmesini sağladık. Böylece sistemde olup bitenleri artık tek bir noktadan takip edebiliyorduk. Ancak bu, bir noktadan sonra sadece yazılan, dönüp yüzüne bakılmayan ama sürekli büyüyen; bir sorun anında ulaştığımız ancak aradığımızı çoğu zaman bulamadığımız yığınlar haline geldi, geliyor. Üstelik, hatalar kendi ürünlerimizde, tüketicilerimiz ne zaman denk gelir ve raporlarsa o zaman karşılaşabildiğimiz ve müdahale çabasına girdiğimiz “yabancı nesneler” olarak karşımıza çıkıyor. Formal yapıda kayıtlar olmadığı için sadece sahibi tarafından anlaşılabilir, yorumlanabilir ifadeler ise projelerin bir ya da birden fazla kişiyle baba-oğul ilişkisi içinde kalmasına neden oluyor. Bu durumlar sebebiyle yeni bir sisteme ihtiyacımız olduğuna kanaat getirdik ve kolları sıvadık.

Araştırmalarımıza nereden başladık?

TSDB (Time Series Database) adı verilen sistemleri inceleyerek işe başladık. Sistem ekibimizin de desteği ile görseldeki iki ürünün test kurulumlarını gerçekleştirdik. Ancak farkettik ki, key-value mantığı ile çalışan bu veritabanı sistemleri bizim hayal ettiğimiz çıktıyı üzerinde taşıyabilecek nitelikte değildi. Kalite, hız, ölçeklenebilirlik gibi parametrelerden ziyade, içerisinde onlarca özelliği taşıyan objeleri taşıması ve önyüzde kullanıcı dostu bir şekilde gösterebilmesi bizim önceliklerimizden biri idi. Testlerimizde ve araştırmalarımızda bu yapıların genellikle metriklerin ölçümlenmesi amaçlı kullanıldığını gördük ki şu anda sistem ekibimiz de CPU değerleri, işlemci yükleri, sıcaklıklar vs gibi değerleri bu sistemler üzerinde saklıyor ve görselleştiriyor. Dolayısıyla yüzümüzü farklı bir yöne çevirme ihtiyacı duyduk ve globalde kabul edilmiş başka bir standardı sistemlerimize nasıl adapte ederiz sorusuna kanalize olduk.

ELK (Elastic — Logstash — Kibana)

“Kayıtlarımızı Logstash ile A noktasından B noktasına formal bir şekilde taşır, hızlı bir şekilde sorgulayabileceğimiz ve güvenli bir şekilde muhafaz edebileceğimiz ElasticSearch’te tutar, Kibana ile gözlemleriz” fikri oldukça cazip geldi. Aslında Amerika’yı yeniden keşfetmedik. Yıllardır yazılım dünyasında kullanılan bir sistemin entegrasyonuna karar verdik. Ancak bu noktada aklımızı kurcalayan en önemli soru/sorun şu idi: Onlarca makineye dağılmış uygulamaların “data transportation” sürecini nasıl yöneteceğiz? Tabii ki çılgınca fikirleri masaya yatırdık. En çılgıncası, en yorgun anımıza geldi: “Her makineye Logstash kuralım!” Sonra bu fikri sunan arkadaş sırra kadem bastı, hala bir haber alamıyoruz kendisinden. Görenlerin 0(212) … Bu fikir benimdi evet, bu zihin açıcı çılgınlığı yaptığım için de kendimden utanmıyorum :)

Son olarak varmış olduğumuz karar ise şu oldu: Kayıtları kuyruğa at!

Gün Sonu

“Uygulamalar log’ları arka kapıdan RabbitMQ’ya teslim edecek, Logstash RabbitMQ’ya consumer kılığında gizlice yaklaşıp gerekli bilgileri alacak ve vakit kaybetmeden Elasticsearch’e iletecek; Elasticsearch’teki bilgiler ise karanlık odada Kibana ile basılacak.”

Bu senaryo hoşumuza gitti ve hemen uygulamaya koyulduk.

İçeride genellikle .NET tabanlı uygulamalar geliştirmekle birlikte, Python dilini de aktif olarak kullanıyoruz. Özellikle zamanlanmış görevlerde bizim için biçilmiş kaftan diyebiliriz. Dolayısıyla uygulamaları log sistemi ile haberleştirecek yapıyı her iki dilde de geliştirme ihtiyacı ortaya çıktı.

.NET uygulamalarımızda kullanmak üzere meşhur NLog kütüphanesini kullandık. Bizim bu kararı verdiğimizde henüz NLog’un RabbitMQ ile haberleşebileceği bir Target desteği yoktu, var olan bir-iki açık kaynak kodlu kütüphane ise kullanabileceğimiz seviyede değildi. Biz de bunun üzerine NLog’un “genişletilebilirlik” özelliğini kullandık ve kendi NLog target kütüphanemizi geliştirdik: Hurriyet.NLog.HurRabbitMQ

Python’un logging kütüphanesini de yine NLog’a benzer bir şekilde extend ettik ve Python uygulamalarımızdan RabbitMQ’ye aktarımı sağlayabilecek olgunluğa ulaştık.

Araştırma ve geliştirme aşamamızın sonuna geldiğimizde aslında çokça istediğimiz noktaya varmış idik. Log sisteminin çekirdeği stabil bir şekilde varlığını sürdürebilir durumda iken, consume&transport işlemini yapacak katmandan soyutlamayı başardık. Günün sonunda RabbitMQ’dan farklı bir sisteme geçiş yapmaya karar verdiğimizde (örneğin; Kafka) suyun toplanma noktasını değiştirmeden kaynağı dilediğimiz yere çevirebileceğiz.

Ve tabii ki, ürün ekibimizden sistem ekibimize, analiz ekibimizden yazılım ekibimize herkes, sistemin aksayan noktalarını tespit edip gerekli yerde gerekli refleksi gösterebilecek duruma gelecek ve böylece ziyaretçilerimize — ya da iç uygulamalar ile bizlere — daha az aksayan ve daha stabil uygulamalar sunma şansına sahip olacağız.

Sabrınız için teşekkürler,

Başka deneyimlerde ve heyecanlarda görüşmek dileğiyle.