Herkese Selamlar!
Bugün sizlere özellikle PHP dünyasında popüler loglama aracı olan Monolog’tan bahsedeceğim.
Değinelecek konular:
1 - Loglamak neden önemli yazılımcılar için?
2 - Monolog nimetleri ve Symfony içerisinde gösterilmesi
Log yapısının kurulu olduğu ve olmadığı farklı projelerde geliştirme yapmış birisi olarak, zaman maliyetini düşürüyor diyebilirim. Hepimizin bildiği gibi zamanı satın alamıyoruz. En verimli şekilde kullanmamız gerekiyor. Biz yazılım geliştiricileri için bir uygulama geliştirirken en önemli olgu, birim zamanda yapılan iş. Sonuç olarak clean code yazmak veya yazmamak ya da doğru design patternları kullanmak ya da en modern teknolojileri kullanmak business tarafı için veya müşteri için önemli değil. Kullanıcılar bunu bilmez, bilemez, bilmeside gerekmez. Tabii ki de dolaylı olarak bu bahsettiğimiz kavramlar, doğru sistemi oluşturmada çok önemli etkenler. Dolaylı olarak etkiliyor. Ama loglamak biraz bunların dışında olduğunu düşünüyorum.
Teknik olarak çok kötü bir uygulama geliştirilmiş bir projede çalıştığınızı düşünün. Spagetti kodlar her tarafta. Bir bug fix geliyor ve problemin ne olduğu, nerede olduğunu bulmak için vakit kaybediyorsunuz. Önceki yazılımcının kulaklarını çınlatıyorsunuz. Projede domain bilginiz varsa şanslısınız. Yoksa ? Bence tamamen gereksiz yere kaybedilen zaman, bu da bizim için(yazılımcı veya firma) para kaybı demek.
Hadi bir ütopya düşünelim. Öyle bir sistem varki elimizde, her hatanın nerede olduğu, neden olduğunu, hangi süreçte olduğunu, ne kadar sürede veya ne kadar zamandır olduğunu gösteren bir log servisimiz var. Alertler geliyor, test ortamlarında bile belki hataları yakalaya biliriz. (Ah bir de bunu legacy projelerde olduğunu hayal ediyorum) Bu bence işleri daha eğlenceli hale getirirdi. Yazılımcı mutlu olurdu. Problemler daha çabuk fixlenirdi. Patronlar mutlu olurdu.
Monolog bizlere neler sunuyor?
İlk öncelikle şunu söylemekte fayda var. Symfony ve Laravel default olarak zaten monolog kullanıyor.
Community tarafından geliştirilmiş, hala geliştirilen, open source bir yazılım projesi. Loglarımızı dosyalara, veri tabanlarına, socketlere veya farklı kurgularla(sisteminze ve ihtiyacınıza göre) servislere yazabiliyoruz. Alert sistemleri oluşturabiliriz. Farklı caseler için durum mesajları mevcut. Slack ve bunun gibi benzeri haberleşme uygulamalarıyla entegre şekilde çalışabiliyor. Esnek bir yapıda olduğunu iddia ediyor. Derin caselerde kullanmadım. Ama kullananlar vardır diye düşünüyorum. PSR-3 standartını uyguluyor. Projeye liderlik eden abimizde Jordi Boggiano. (http://twitter.com/seldaek) Aynı zamanda packagist co-founder.
İlk başta monolog içerisindeki log levelleriden bahsetmek istiyorum.
- DEBUG(100) debug bilgileri anlamına gelir.
- INFO(200) kullanıcı logları, sql logları, session vb.
- NOTICE(250) pek kullanmadım, eventler için kullanılabilir.
- WARNING(300) hata olmayan, depracate olmuş herhangi bir ürün,
- CRITICAL(500) exceptionlar, cevap vermeyen veya veremeyen servisler
- ALERT(550) gece uykunuzdan uyandıran mesajlar :)
- EMERGENCY(600) kimseye nasip olmasın
Kendi caselerinze göre standart bir yapı oluşturup, projelerinizde ortak bir log dili oluştura bilirsiniz. Her projede standart outputlar,mesajlar güzel küçük detaylar olabilir.
use Psr\Log\LoggerInterface;public function index(LoggerInterface $logger)
{
$logger->info('I just got the logger');
$logger->error('An error occurred');$logger->critical('I left the oven on!', [
// include extra "context" info in your logs
'cause' => 'in_hurry',
]);// ...
}symfony.com üzerinden alındı bu örnek.
Controller içerisinde default loggerı inject edebiliyoruz. Bu logger servisinde yukarıda bahsettiğim farklı log statuslerini kullanabileceğiniz metotları LoggerInterface içerisinde görebilirsiniz.
Symfony içerisinde logger mevcut olduğunu söylemiştim zaten.
composer require symfony/monolog-bundle
Composer(dependency manager) ile projemize dahil ediyoruz.
Dev ortamında var/log/dev.log, prod ortamda var/log/prod.log üzerinde loglar tutuluyor. Prod ortamında default olarak error(), critical(), alert() ve emergency() statuslerini observe edebiliyoruz. Tabii ki de bunun ayarlarını değiştire biliyoruz.
Birden çok handlers mevcut. Bunların amacı farklı yerlere log atabilmek(files, database, chat apps).
Smyfony’nin güzel yanlarından birisi, bütün config işlerini yaml formatında yapabiliyor olmamız(tamamen kişisel görüş). Okunabilir, anlaşılır kılıyor.
Custom bir config görüyoruz. Görselde en tatlı yer fingers_crossed. Bunun sebebi, prod ortamlarında gelen requestler action_level seviyesinde ise, direk loga düşüyor ve bütün detaylarıyla. Ben genellikle fingers_crossed kullandım. Özellikle kibana üzerinde loglara bakarken çok fazla parametre geliyor. Çok fazlada yardımcı oluyor.
Bu görselde ise log formatını belirliyoruz.
Bu görselde ise gelf portlarını bağlıyoruz, böylelikle gerekli confları yapınca da kibana/graylog da görebiliyoruz.
Default olarak gelen config listlerini aşağıda paylaşıyorum. Mongo, elasticsearch, redif, gelf gibi bir sürü durumlar için bu linkte bulabilirsiniz.
Peki kod tarafında nasıl kullanacağız?
Auto-wiring’ten bahsetmek gerek. Kısaca D.I(dependency njection) container üzerinden bir classın instance alabiliriz. Böylelikle type-hint yaparak interface üzerine, içerideki fonksiyonları kullanabiliriz.
Bir class içerisinde,
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
Yararlı olabilecek başka bir konu ise, bir servis içerisinde error oluşursa, mail yoluyla logları atabiliyoruz. Farklı olarak config içerisine swiftmailer configlerini ekliyoruz. İstediğiniz level seviyesine göre düzenleye biliyorsunuz. Bunun için gerekli linki aşağıya bırakıyorum.
Daha fazlası için(custom servisler içerisinde kullanma gibi)
https://symfony.com/doc/current/logging.html#learn-more
Kaynaklar:
- https://symfony.com/doc/current/logging.html#using-a-logger-inside-a-service
- https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md
Elimden geldiğince basit haliyle anlatmaya çalıştım. Bir kusur görürseniz lütfen belirtiniz.