Azure'da Trace.WriteLine yapacak olsak?

0 dakikada yazıldı

22274 defa okundu

Düzenle

Development süreçlerinizde her ne kadar Azure SDK ile beraber gelen
emülatörü kullanacak olsanız da maalesef bazıt testleri doğrudan Azure
üzerinde yapmak zorunda da kalabiliyoruz. Bu çok da anormal bir durum
değil :) Sonuç itibari ile Azure üzerinde bir "Staging" ortamı tutmak
için gerekli altyapı Azure'da var. Tabi aslına bakarsanız Staging
dışında bir de Development ortamı tutmak gerekiyor ama şimdilik çok da
oraları karıştırmayalım :) Peki nedir çözüm aradığımız sorun? Basit bir
"code instrumentation" çözümü arıyoruz ve bunun da azure'daki
development ortamımızda çalışmasını istiyoruz. Eminim ki çoğunuzun
aklına "Trace"'ler gelecektir. En basit şekli ile development
süreçlerinde kullandığımız ve epey de işimize yarayan şeylerden biri
Trace'ler Azure ortamına geçince ilginç bir problem olabiliyor.

Diyelim ki attık uygulamayı Azure ortamına, scaling'i de hallettik vs...
Trace verisini nereden, nasıl toplayacaksınız? Uygulama birden çok
sunucuda çalışıyor unutmayın. Bu sunucuların her an "ReImage"
olabileceğini ve aslında state'lerinin saklanmadığını da düşünürsek
bizim Trace bilgilerini kalıcı olarak ve ortak bir yerde saklayabiliyor
olmamız gerek. Aklınıza birşey geldi mi? Azure'da kalıcı veri saklamak
için ne kullanıyorduk? Storage Servisleri :)

Trace Verilerini doğrudan Table Services'a alsak?

Bu fikri ilk duyduğunuzda hemen aklınıza "ya maliyeti?" sorusu gelebilir
:) Her Trace'de bir REST call ile veriyi merkezi bir yere atmak hem
performans açısından hem de maddi açıdan sıkıntı yaratabilir ama
unutmayın bunu Production için düşünmüyoruz aslında. Development
süreçlerimizde kullanmak için düşünüyoruz. Aslına bakarsanız Prod için
de kullanabilirsiniz :) ama en azından bu makalede bakacağımız kısmın
üzerine bir "instance seviyesinde" cache tutup önce Trace'leri oraya
dumb etseniz ve periyodik aralıklarla Table Services'a atsanız daha iyi
olur. Nitekim bu işi yapan Azure Diagnostics servisleri de var aslında
ama tüm bunlara bulaştığınızda zaten yavaş yavaş Production kalitesinde
bir çözüme doğru ilerlemiş oluyorsunuz. Bizim istediğimiz ise basit,
anlık, herhangi bir gecikme olmadan Development ortamımızda Trace'leri
görmek! O kadar! :)

O zaman başlayalım... Önce Table Services'a erişimimizi düzenleyelim.

Table Services konusunu daha önce detayları ile toplam üç yazıda
işlemiştik.
Yazılaraburadan
ulaşabilirsiniz. Çok detaylarına girmeden hızlıca Trace nesnemizi bir
yaratalım.

[C#]

public class TraceObject : TableServiceEntity
{
    public string Message { getset; }
}

Trace nesnemiz görüldüğü gibi epey basit :) Sadece Trace'de verilen tek
bir metni kaydedeceğiz. Siz isterseniz ileriki adımları da biraz daha
özelleştirecek ek verilerin kaydedilmesini de sağlayabilirsiniz.

[C#]

public class TraceContext : TableServiceContext
{
    private static CloudStorageAccount storageAccount =
      CloudStorageAccount.FromConfigurationSetting(Setup.ConfigurationSettingKey);

    public TraceContext()
        : base(storageAccount.TableEndpoint.AbsoluteUri,
            storageAccount.Credentials)
    {
    }

    public DataServiceQuery<TraceObject> Traces
    {
        get
        {
            return CreateQuery<TraceObject>("Traces");
        }
    }
}

Yukarıda Table Services'dan kullanacağımız "Traces" adındaki tabloya
erişim için gerekli TableContext'imizi yaratmış durumdayız. Böylece
artık işin Table Services tarafı tamamlandı gibi. Tabi söz konusu Traces
tablosunu yaratmayı da unutmayın :)

Bir sonraki adımda sıra geliyor özel bir Trace Listener yaratmaya.

[C#]

public class CustomTraceListener : System.Diagnostics.TraceListener
{
    public override void Write(string message)
    {
        WriteLine(message);
    }

    public override void WriteLine(string message)
    {
        var traceContext = new TraceContext();
        var newTrace = new TraceObject
        {
            PartitionKey = DateTime.Now.Year.ToString(),
            RowKey = DateTime.Now.ToOADate().ToString(),
            Message = message
        };
        traceContext.AddObject("Traces", newTrace);
        traceContext.SaveChanges();
    }
}

Yarattığımız bu CustomTraceListener'ın içinde Write veWriteLine
metodlarını implemente etmemiz gerek. Siz tercihinizi göre tabi ki
farklı hareketler de yapabilirsiniz :) Bu örnekte WriteLine
içerisinde yeni bir TraceObject yaratarak Table Services'daki
tablomuza Insert işlemini gerçekleştiriyoruz. Böylece
herTrace.WriteLine çağrıldığında mesaj doğrudan Table Services'a
aktarılacak.

[C#]

CustomTraceListener TListener = new CustomTraceListener();
Trace.Listeners.Add(TListener);

Son olarak yapmanız gereken uygulamanız başladığında bizim
CustomTraceListener'dan bir tane yaratıp uygulamanın Listener
listesine eklemek. Bunun ister WorkerRole'ün OnStart'ında ister web
sitenizin App_Start'ında yapabilirsiniz. Artık tüm Trace'ler doğrudan
Table Services'a gidecek.

Unutmadan, diğer detayları daha önceki yazılarda inceledik diye
bahsetmedim ama :) StorageClient için ConfigurationPublisher'ı set
etmeyi unutmayın. Yukarıdaki kodlarda "Setup.ConfigurationSettingKey"
diye geçen kısıma da Storage Account connection string'ini vermeniz
gerekecek.Table Services ve Storage Account konusunda blogda birçok
yazı var
. Göz
atmanızda fayda var.

Kolay gelsin.