Android uygulamalarda loglama pratikleri Log4Net Crashlytics Slack

OpenSignal’in Android fragmentasyon verilerine göre, Ağustos 2014 itibariyle piyasada 18,796 farklı Android cihaz bulunuyor. Bu cihaz çeşitliliğine, çözünürlük, versiyon, yüzlerce 3rd party kütüphaneyi de eklersek Android uygulamaların bakımı ve desteği, geliştirme süreçlerinden çok daha zorlayıcı bir hal alıyor. Mobil uygulama geliştirmek zaten zorken, Android bu zorluğu bence biraz daha perçinliyor. Bu yüzden hata raporları ve client loglama çok fazla önem kazanıyor. Sunucu tarafında ise genelde kendi API’mızı kullandığımız için, hata raporlarının ötesinde istekleri izleyebilmemiz önemli. Daha fazla loglamanın öneminden bahsedip sıkmamak için, kafa ütülemeden direk konuya gireceğim. Ancak yine de hepimizin bildiği bir gerçeği tekrar edeyim; “Loglama her çeşit uygulamanın en hayati parçasıdır.”.

Loglama için uzun süre RDBMS vs metin dosyaları kullandım ancak log tabloları/dosyaları genellikle (özellikle yüksek hacimli uygulamalarda) en fazla depolama alanı tüketen kısım oluyor. Ve tablo/dosya büyüdükçe analiz etmek, arama yapmak çok daha zor bir hal alıyor. Bu yüzden bir süredir cloud uygulamalardan faydalanıyorum. Bu yazının sonunda aşağıdaki tabloda göstermeye çalıştığım yapıyı kurmuş olacağız. Sebepleri ve kurulum adımları için yazının devamını okuyabilirsiniz.

Android’de hata raporlama maceralarım

Manuel loglama denemeleri

Denediğim en primitif yöntemlerdi. Önce hata raporu ve logları eşzamanlı olarak sunucuya göndermeyi planladım. Ancak bu yöntemin en önemli handikapı, network katmanında oluşan hataları yakalayamıyor olmamdı. Ayrıca analiz zamanlarında loglanacak seviyeyi düşürdüğümde, sunucudaki yükü birden artıyordum. Ardından logları client üzerinde log dosyalarına yazmaya ve gerektiğinde bu dosyalara erişebilmeyi planladım ama bu daha kötü bir fikirdi. Çünkü io ile çalışmak sorun yaratabiliyordu, hem de log dosyaları güvenlik problemi oluşturuyordu.
Ardından bazı loglama frameworklerinden faydalandım. slf4j AndroLog gibi frameworklerin ciddi faydasını görsem de production ortamında hata raporu ve loglara uzaktan erişmek için hala sağlıklı bir yöntem üretememiştim. Hazır bir çözüm arayışına girdim.

ACRA

  • ACRA çok başarılı bir kütüphane. Kurulumu çok kolay. Ancak benim denediğim zamanlarda büyük bir dezavantajı vardı. Backend’i yoktu, logları yazmak için Google Docs kulanıyordu. Oldukça verimsiz bir yöntemdi. İlişkimiz kısa sürdü.
  • Not: Artık Acralyzer adında open source bir backend varmış. Ama henüz denemedim.

Bulut servisler

Mobil analitik konusunda özelleşmiş bir çok servis, artık hata raporlama araçları ile birlikte geliyor. Geliştiriciler arasında yaygın olarak kullanıldığını gördüğüm 3 farklı servis;

Ben 2 önemli sebepten Crashlytics’i tercih ettim;

  • Ücretsiz
  • Hazır slack entegrasyonu var

Crashlytics

2011 yılında ortaya çıkan Crashlytics, 2013 yılında Twitter tarafından 100 milyon $’a satın aldıktan sonra kurumsal planı da dahil olmak üzere tamamen ücretsiz hale geldi.

Kurulumu

Kullanımı

try { HataFırlatanKodBlogum(); } catch (Exception e) { Crashlytics.logException(e); }

Eğer isterseniz raporlarınıza, mevcut kullanıcıyı tanımlayan bir ifade atayabilirsiniz;

Crashlytics.setUserIdentifier("Login adı, eposta vs..");

Ya da farklı veri tipleri için tamamen özelleşmiş ifadeler tanımlayabilirsiniz;

Crashlytics.setInt("versiyon", 3); Crashlytics.setString("konum_saglayici", "network"); Crashlytics.setBool("sim_takili", true);

Hata raporunun dışında, seviye seviye normal log da tutabilirsiniz.

Crashlytics.log(Log.INFO, "TAG", "Bu cihaz rootlanmış.");

Not: Crashlytics, veri kullanımını minimize edebilmek için, önce logları biriktirip ardından belirli aralıklarla sunucuya gönderiyor.

Nitekim Android tarafında loglama konusuna çözüm ürettik, peki ya sunucu?

Sunucu logları

Loglama hassas bir konudur. Çünkü sistemi izlemek ve analiz etmek için kullandığımız bir aracın sorun çıkartmasını istemezsiniz. Kendini kanıtlamış yöntemler kullanırsanız, kafanızı yastığa daha huzurlu koyabilirsiniz.

Apache log4Net

Kurulum

Yapısı

Loggers

Logger, log tutmak için kullanılan arayüzünün genel ifadesidir. Bu bileşen ile hiyerarşik loglama yapılabilir. Örneğin; “eferhatg.forms” adında bir logger’ımız olsun. Bu loggerda ERROR seviyesinde log tuttuğumuzu varsayalım. Bu logger’ın altındaki tüm classlarınızda bu seviyede log tutulacaktır. Ancak eğer isterseniz “eferhatg.forms.login” hiyerarşisini FATAL, ya da “eferhatg.forms.payment” hiyerarşisini INFO seviyesinde tanımlayabilirsiniz.
Logger sınıfı bize 7 farklı seviye verir. Bunlar ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF ‘dur. Açıklamaya gerek duymuyorum.

Appenders

Appender logun nerede tutulacağı ile ilgilidir. Yaygın olarak webconfig üzerinde XML ile tanımlanır. Bu sayede koda müdahale etmeden loglama için yeni hedefler tanımlayabilir ve yönetebilirsiniz. Örneğin aynı anda hem MSSQL üzerinde, hem metin dosyası üzerinde veya bir bulut servis üzerinde log tutabilir, istediğiniz zaman seviyelerini değiştirebilir, kapatıp açabilirsiniz. Log4Net standart olarak şu appenderları içerir.

Layouts

Layout adından da anlaşılacağı gibi logun nasıl tutulacağı ile ilgilidir. Layout, logda nelerin yazacağı ve nasıl yazacağı ile ilgili patterni tanımlr. Örn ilk satırdaki pattern, ikinci satırdaki gibi bir sonuç üretir.

"%date %thread %-5level %logger %message%newline" "[2015-05-29 12:37:12,860] [69] [INFO] [eferhatg.forms.payment] [Ödeme alındı.] "

Eğer mevcut ifadelerin yanı sıra kendi özelleşmiş ifadelerinizi eklemek isterseniz, Context nesnesinden faydalanabilirsiniz.

Konfigürasyon

<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a"/> ... </configSections>

Şimdi konfigurasyonu halletmeliyiz. <configuration> taginin altına <log4net> adında bir tag oluşturup içerisinde appender'larımızı tanımlıyoruz. Tasarımınıza uygun appender'a şuradan erişebilirsiniz. Ben şimdilik RollingFileAppender kullanacağım.

RollingFileAppender’ın text dosyaya log tutan ve belirleyeceğiniz şartlarda log dosyalarını arşivleyen bir yapısı var. Aşağıdaki örnekte log dosyası 10MB’a ulaştığında, mevcut olanı arşivleyip yeni log dosyası oluşturuyor.

<log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="LOG\log.txt"/> <appendToFile value="true"/> <rollingStyle value="Size"/> <maxSizeRollBackups value="50"/> <maximumFileSize value="10MB"/> <staticLogFileName value="true"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date %thread %-5level %logger %message%newline"/> </layout> </appender> ... <log4net>

Örnekte gördüğünüz üzere her appender için layout oluşturuyoruz. Bu sayede tuttuğumuz logu her depolama tercihi için ayrı ayrı özelleştirebiliriz.

Şimdi <log4net> taginin sonuna <root> diye bir tag oluşturuyor ve hangi appender'ın hangi seviye için çalışacağını belirtiyoruz. Örneğin RollingFileAppender'ımızı INFO seviyesi için çalıştıracaksak log4net için yaptığımız tüm konfigurasyonun son hali aşağıdaki gibi olacaktır.

<configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a"/> </configSections> <log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="LOG\log.txt"/> <appendToFile value="true"/> <rollingStyle value="Size"/> <maxSizeRollBackups value="50"/> <maximumFileSize value="10MB"/> <staticLogFileName value="true"/> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date %thread %-5level %logger %message%newline"/> </layout> </appender> <root> <level value="INFO"/> <appender-ref ref="RollingFileAppender"/> </root> <log4net> </configuration>

Son olarak uygulamanızın başlangıç kısmında yukarıda yazdığımız konfigürasyonu başlatmalısınız;
WebApi için WebApiConfig.cs içerisine veya
MVC için RouteConfig.cs içerisine veya
Web Uygulaması için Global.asax içerisine aşağıdaki satırı eklemelisiniz.

log4net.Config.XmlConfigurator.Configure();

Not 1: Diğer yolu da AssemblyInfo.cs içerisine aşağıdaki satırı eklemek;

//ConfigFile masaüstü uygulamalar için app.config olacak. [assembly: log4net.Config.XmlConfigurator(ConfigFile="Web.config", Watch = true)]

Not 2: Eğer kurulum ile ilgili sorun yaşarsanız, log4net’i debug edebilmek için <appSettings> taginin altına aşağıdaki key'i ekleyebilirsiniz. Böylelikle console'da log4net'in kendi loglarını görebilirsiniz.

<appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings>

Kullanımı

namespace eferhatg.forms { public class payment { private static readonly ILog Log = LogManager.GetLogger(typeof(payment)); } }

Ve artık log tutmaya başlayabilirsiniz;

namespace eferhatg.forms { public class payment { private static readonly ILog Log = LogManager.GetLogger(typeof(payment)); public void pay(){ Log.Info("Ödeme Alınacak."); //Bu satırın ürettiği log aşağıdaki gibi olacaktır. //[2015-05-29 12:37:12,860] [69] [INFO] [eferhatg.forms.payment] [Ödeme Alınacak.] } } }

Logentries

Şu an log4net kullanarak metin dosyalarına loglama yapabiliyoruz. Ama log tutmak analiz için tam anlamıyla yeterli değil, logları canlı izleyebilmek, loglar içerisinde (full-text search) detaylı arama yapabilmek, gerektiğinde alarm üretmek gerekecektir. Eğer bulutta log tutmak ile ilgili bir engeliniz yoksa, tüm bunlar için en doğru yöntem bir loglama servisi olacaktır.

Papertrail ve Logentries yaptığımız testler sonucunda, biz Logentries’de karar kıldık. İkisi de çok iyi servisler, ancak biz Logentries’in fiyat modelini ve yeteneklerini daha çok beğendik.

Peki log4net ile tuttuğumuz sunucu loglarını Logentries’e nasıl aktarırız?

Kurulum ve Entegrasyon

  • Bir Logentries hesabı yarat
    https://logentries.com adresinden bir hesap yaratıyoruz. Sonra arayüzden [Logs->Add New Log] diyerek .NET için Token TCP bir log kaydı oluşturuyoruz.
  • Logentries plugin’ini kurmak
    Nuget kullanarak projemize logentries.log4net plugin’ini kuruyoruz.
  • Web.Config’e logentries için bir appender eklemek.
    Web.config’i açıp <log4net> tagi içerisine aşağıdaki appender'i ekliyoruz.
<appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net"> <Debug value="true" /> <HttpPut value="false" /> <Ssl value="false" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%date %thread %-5level %logger %message%newline" /> </layout> </appender>
  • <appSettings>'e LOGENTRIES_TOKEN değeri eklemek
    Oluşturduğunuz log'un TOKEN değerini(Logentries arayüzünden edinebilirsiniz.) appSettings altına LOGENTRIES_TOKEN key'i ile ekliyoruz.
<appSettings> <add key="LOGENTRIES_TOKEN" value="***Burada sizin TOKEN'ınız olacak"/> ... </appSettings>

Bu kadar! Artık loglarınızı Logentries üzerinde görebilirsiniz.

İletişim Güçtür

Neden Slack

Slack’i denemek, aslında anlatmaktan daha kolay. Kabaca “onlarca farklı bulut uygulama ile entegre olabilen bir haberleşme servisi.” diyebiliriz.

  1. Email alternatifi
    Özellikle projeye ekiplerinde şimdiye kadarki en güçlü email alternatifi.
  2. Tüm gelişmeler tek bir yerde
    Projeye ait tartışmalarız, alarmlar, dosyalar, testler… aklınıza gelebilecek tüm bileşenler ve gelişmeler tek bir ekranda.
  3. Çok güçlü bir iletişim aracı
    Kanallar(channels) yardımı ile, email ile chat arasında, ikisinden de güçlü bir ekip iletişimi sağlıyor.
  4. Bir çok servis ile entegrasyon seçeneği
    Crashlytics, Logentries, Papertrail, Google Drive, Bitbucket, Dropbox, Heroku, Jenkins ve onlarcası.
  5. Arama yapmak kolay ve efektif
    Emailde arama yapmak bazen işkenceye dönüşebiliyor. Slack ile derinlerdeki bir bilgiye tek bir arama kutusuyla kolayca erişebiliyoruz.
  6. Dosya paylaşmak kolay
    İster Google Drive veya Dropbox’ı entegre ederek, ister direk upload ederek.
  7. Kod parçaları paylaşımı
    İstediğiniz syntaxda kod paylaşabilirsiniz.
  8. Mobil uygulaması var
    Projenize dair tüm gelişmelerden 7/24 haberdar olabilirsiniz.

Özellikle bizim gibi home-office çalışan bireylerseniz, eminim Slack ekip iletişiminizi önemli ölçüde arttıracaktır. Kullanmasanız bile mutlaka deneyin. ;)

Loglama candır

Projelerinizle konuşmanın tek yolu loglama.

İyi çalışmalar.

Originally published at www.eferhatg.com on June 2, 2015.

Mostly developer, almost traveller, already gamer http://eferhatg.com/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store