Photo by Emile Perron on Unsplash

Flutter’da FirebaseCrashlytics ve EasyLogger ile Gelişmiş Log Sistemi

Buğra Göksu
Team Kraken
Published in
4 min readSep 23, 2021

--

Herkese merhaba! Bu yazıda sizlerle kapsamlı, geliştirilebilir ve test edilebilir bir log sisteminin Flutter’da nasıl geliştirebileceğinizden bahsedeceğim. Aslında bu yapıyı sadece Flutter’a özgü değil, kullandığınız tüm dillerde de rahatlıkla implemente edebilirsiniz. Tabii, bu sistem en iyisi, daha iyisi olamaz gibi bir iddiam yok. Ancak kapsamlı projelerde de rahatlıkla kullabilirsiniz keza Team Kraken olarak yeni projemizde bu sistemi kullanmayı seçtik!

Öncelikle sistemin tasarımına ve implementasyonuna geçmeden önce sizlere genel olarak bu sistem hakkında bir bilgi vereyim. Sistemimiz local ve remote olarak loglarını iki farklı yere yazabiliyor. Bu şekilde production’da iken loglarınızı remote servislere (biz burda FirebaseCrashlytics kullanmayı seçtik) yazabilirken, development sürecinde ise loglama işlemlerinizi locale yapabilirsiniz. Bu sayede daha temiz bir sistem inşa etmiş oluruz ve production ve development loglarımız birbirine karışmaz.

Remote loglama işlemi için FirebaseCrashlytics’i kullanmayı seçtiğimizi söylemiştim. Local log süreci için ise kullandığımız paket easy_logger oldu. Bu paketi seçmemizdeki sebep aslında localization işlemleri için kullandığımız easy_localization paketinin içerisinde default olarak gelmesi. Bu yüzden başka bir paket ihtiyacı hissetmedik. Tabii siz kendinize uygun başka paketlere de göz atabilirsiniz.

Kullanacağımız paketlere karar verdiğimize göre artık sistemin mimarisinden biraz bahsedebiliriz! Aşağıdaki diagramdan sisteme bir göz atalım.

Şemada’da gördüğünüz gibi Logger isimli bir base class’ımız var. Bu class’ta methodlarımızı tanımlayıp parametre ve geri dönüş tiplerini belirledik. Buradaki amaç loglarımızı ister remote’a ister isek locale kaydedelim kullanacağımız methodların benzer olmasıydı. Hem de bu sayede kodumuzu rahatça test edebilir ve ileride paket değişikliğine gitmek istersek bu değişikliği minimum kod ile yapabiliriz. Gelin şimdi methodlarımızı yakından inceleyelim!

Base class’ımızda tanımladığımız 3 tane method var, bunlar;

log (Object object, {bool toRemote = false});setCustomKey (Map<String,Object>keys);logException (Exception e, {LogSeverity logSeverity = LogSeverity.error});

Bu methodların ne yaptığını az çok anlamışızdır. log methodumuz adı üzerinde verilen objeyi implemente edildiği yere loglayan bir methodumuz. Burada optional olarak toRemote parametresi ise aslında gereksiz gibi görünse de developerın gözünden kaçacak gereksiz logları production ortamına (yani Firebase’e) göndermesini engellemek için koyduk (Geliştirme sürecinde bazen çok dikkatsiz olabiliyoruz…). Yani eğer bir log’u remote’a göndermek istiyorsak her seferinde `toRemote = true` dememiz gerekiyor. Bu sayede gerçekten bilerek remote’a log göndermiş oluyoruz. Burayı kendinize göre editlemeniz mümkün tabii.

Diğer methodumuz ise setCustomKey. Bu method aslında biraz remote loglar için kullanılan bir method. Aslında tam anlamıyla remote logger için kullandığımız bir method çünkü local logger implementasyonu no operation yani hiçbir işlem yapmıyor! Bu methodun amacı ise FirebaseCrashlytics’e exception ya da log yazarken custom key ekleyip panel üzerinde bize ipucu verecek bilgiler eklemek ve filtreleri geliştirmek.

Son olarak logException methodumuz ise parametre olarak aldığı exception’ı loglamak. Ek olarak burda kendi oluşturduğumuz LogSeverity enum’ını da parametre olarak geçiyoruz. Şimdilik error ve fatal olarak iki adet seviye belirledik. Bu değerlere göre exception’ın seviyesini belirtiyoruz.

Genel olarak sistemi çizdiğimize göre artık implementasyonuna geçebiliriz. FirebaseCrashlytics ve EasyLogger paketlerini projemize import etmemiz gerekiyor. Yazının uzamaması adına Firebase proje oluşturma, projeye dahil etme gibi işlemleri atlıyorum. Firebase’i projeye dahil etmek için buraya göz atabilirsiniz.

Paketlerimizi projeye eklediğimize göre ilk önce base class’ımızı yazarak başlayabiliriz :

Yukarıda da belirtiğimiz gibi Logger adında bir abstract class oluşturuyoruz ve methodlarımızı tanımlıyoruz. Burada ayrıyeten bu class’ın ve methodların ne yaptığına dair açıklamaları üstüne dökümente edebilirsiniz.

Base Logger class’ımızı yazdığımıza göre şimdi remote ve local logger class’larını yazmaya başlayabiliriz. İlk olarak RemoteLogger’dan başlayalım :

RemoteLogger class’ı içerisinde FirebaseCrashlytics’i tanımlıyoruz. Bu sınıfı oluştururken FirebaseCrashlytics instans’ını parametre olarak geçeceğiz. Bu tarz Dependency Injection’lar için biz injectable ve get_it paketlerini kullandık. Bu sayede bağımlıkları kolay bir şekilde yönetebilirsiniz. Ayrıca injectable paketinden gelen prod ve dev annotationlarını kullanarak RemoteLogger class’ını prod olarak işaretleyebilirsiniz. Bu sayede release aldığınızda çalışacak olan logger class’ı RemoteLogger olacaktır. Daha fazla detay için buraya bakabilirsiniz.

Bu class içerisinde Logger base class’ımızdan gelen methodları override ederek içlerini FirebaseCrashlytics paketinin ilgili methodları ile dolduruyoruz.

Son olarak LocalLogger’ımızı implemente edelim :

Genel olarak implementasyonumuz bu şekildeydi. Production veya dev ortamına göre istediğiniz logger class’ını kullanabilirsiniz.

Bir yazının daha sonuna geldik! Umarım sizler için faydalı bir yazı olmuştur. Team Kraken olarak bu tarz yazılar yazmaya devam edeceğiz. Bizi takip etmeyi unutmayın! Başka bir yazıda görüşmek üzere.

Team Kraken Twitter hesabına buradan,
Kişisel Twitter hesabıma buradan ulaşabilirsiniz!

--

--

Buğra Göksu
Team Kraken

Senior Application Developer @Parasut | Organizer @gdgadana | | Jedi @starwars | https://www.linkedin.com/in/bugragoksu/