Makale Özeti

Log dosyalarını, dizin yapısını veya text dosyalarını hızlı taramanın yolları Microsoftun Log Parser aracıyla, artık SQL dil yapısı ile log dosyalarını rahatlıkla sorgulayabilirsiniz.

Makale

Özet:

Log dosyalarını, dizin yapısını veya text dosyalarını hızlı taramanın yolları Microsoftun Log Parser aracıyla, artık SQL dil yapısı ile log dosyalarını rahatlıkla sorgulayabilirsiniz.

Gerekli Araçlar

Giriş:

Genellikle çok yoğun hit alan sitelerde log raporları almak, zaman alıcı bir iştir. Web sitelerinde rapor almak için genellikle WebTrends adlı program kullanılır. Bu uygulama bir hayli detaylı rapor üretebilmektedir. Ancak problem, özel bir rapor alınmak istendiğinde ortaya çıkar. Örneğin adres satırında geçen bir değer, özel bir anlam ifade edebilir ve bunun sorgulanması istenebilir. Webtrends bu gibi işlerde zayıf kalmaktadır.

Alternatif olarak IISin, log bilgilerini SQL veritabanına yazması sağlanabilir. Ancak bu da, zamana yayılsa bile, SQL serverın yorulmasına, zaten çok büyük olan log bilgilerinin gereksiz yere veritabanını şişirmesine sebep olur.

Geçenlerde, bir sitenin  log dosyalarının incelenip, duruma özel bir rapor oluşturulması istendi. Sistemde 5 adet IIS, hergün yaklaşık 2GBlık log dosyası oluşturuyordu. Her log dosyasında da yaklaşık 500,000 satır vardı. Log dosyaları her gece özel bir makinaya taşınıp, her makina için ayrı bir dizine kopyalanıyordu. İlk önce .Net ile bir program yazıp satırların tek tek sorgulanarak raporun üretilmesini düşündüm. Sonuç çok yavaştı uygulanabilirdi, ama çözüm daha hızlı olmalıydı. Ayrıca daha çok geliştirme zamanına ihtiyaç vardı. Veritabanı çözümünü düşünmedim bile, yer sorunu ve indeksleme olmadan hızlı sorgulama yapmak, problemi sadece değişik boyutlara taşıyordu. Çözüm Log Parserla geldi. İnceleyince, çok enteresan bir uygulama ve çok performanslı çalışıyor. Bahsi geçen log dosyalarını bu uygulama sayesinde 2-3 dakika içinde tarayabildim.

Log Parserı indirip kurduğunuzda, dizine iki farklı uygulama kurar biri "LogParser.dll" diğeri de "LogParser.exe". Tahmin edeceğiniz üzere biri komut satırından çalıştırılabilir uygulama, diğeri de bir ActiveX nesnesi. Exe versiyonu komut satırından çalıştırıp çabuk sorgulamalar yapmanızı sağlıyor. Eski günlerdeki gibi, batch dosyalarıyla uğraşmayı severseniz veya test amaçlı kullanmak için iyi bir çözüm. Esas güç ise ActiveX versiyonunda geliyor Uygulama, kurulum sırasında kendisini "MS Utility 1.0 Type Library - LogParser Interfaces collection" olarak register ediyor. Bu noktada uygulamaya ActiveX nesnesi olarak erişebildiğiniz için istediğiniz gibi programlayabiliyorsunuz. Dilerseniz VBScript ile, dilerseniz VB ile, dilerseniz JScript ile, dilerseniz Interop sayesinde .Net ile program yazabiliyorsunuz. Script dillerinde LogParser Nesnesi yaratabilmek için gereken ProgId; "MSUtil.LogQuery".

Aşağıdaki örnekleri kullanabilmek için,  http://www.microsoft.com/technet/community/scriptcenter/logs/logparser/default.mspx  adresinden Log Parser 2.0 uygulamasını indirip kurmanız gerekiyor. Uygulama kurulduktan sonra, LogParser.exe dosyasını "\Program Files" klasörünün altında "Log Parser" dizininde bulabilirsiniz.

LogParserı komut satırında kullanmak (LogParser.exe):

LogParser ile en basitinden şöyle bir ifade yazmak mümkün (ex040412.log dosyasının aynı dizinde olduğunu var sayarak);

LogParser "SELECT top 4 sc-status, cs-uri-stem FROM ex040412.log"

sonuçta aşağıdaki gibi bir sonuç geliyor.

sc-status cs-uri-stem
--------- ---------------------------------
200       /SSO/vs-72742184429620088_tmp.htm
200       /_vti_inf.html
404       /SSO/_vti_bin/shtml.dll/_vti_rpc
200       /_vti_inf.html
200       /_vti_bin/shtml.dll/_vti_rpc

Statistics:
-----------
Elements processed: 5
Elements output: 5
Execution time: 0.05 seconds

Bu ifade yerine;

LogParser "SELECT * FROM <1>"

yazarsanız, IISteki ilk aplikasyonun bütün log dosyalarındaki, tüm kayıtların, tüm alanlarını seçersiniz.
Örneğin sitede olmayan sayfaları bulmak için;

LogParser "SELECT * FROM <1> WHERE sc-status=404"

şeklinde bir ifade yazabilirsiniz.

LogParserı .Net ile kullanmak (LogParser.dll):

LogParser.dll, kullanıcıya ADOya çok benzeyen bir arayüz sunmaktadır. Fakat fiziksel olarak ADO ile uzaktan yakından ilgisi yoktur.
C# ile bir konsol uygulaması yazalım. Amacımızın başarılı gösterilen sayfaları listelemek olduğunu varsayalım. (İpucu: log dosyasında "sc-status" değeri 200 ise bu sayfa başarıyla gösterilmiş demektir. "cs-uri-stem" alanı ise bize sayfa adını verir). İlk olarak Proje oluşturalım;

  1. Visual Studio.Neti başlatıp, "File>New>Project"i seçin
  2. Açılan dialogda sol taraftan "Visual C# Project"i seçtikten sonra, sağdan "Console Application"ı seçin
  3. "Name", "Location" ve "New Solution Name" değerlerini dilediğiniz gibi ayarlayın.
    Ben bu örnekte uygulama adını "ConsoleApplication1" olarak kaydettim.
  4. Diyalog kutusunda OKi seçtikten sonra, Visual Studio.Net bizim için "Class1" sınıfını "Main" metodu ile yaratacaktır.
  5. Kod yazmaya başlamadan önce, LogParserı proje Referanslarına eklememiz gerekiyor. Bunun için
    1. Ekranın sağındaki "Solution Explorer"dan "Refrences"i sağ tıklayın
    2. Açılan Context menüsünden "Add Refrence..." seçeneğini seçin
    3. Açılan diyalog kutusundan üst taraftaki "COM" tabını açın, böylece ActiveX nesnelerini ekleyebileceğiz
    4. Listeden "MS Utility 1.0 Type Library - LogParser Interfaces collection" nesnesini seçin.
    5. Sağdaki "Select" düğmesine basarak nesnenin "Selected Components:" listesine eklenmesini sağlayın
    6. OK düğmesine basın.
  6. Böylece "References" bölümüne "MSUtil" satırının eklendiğini göreceksiniz.
  7. Artık LogParser nesnesini kullanabilirsiniz.

Koddaki en üstteki "using System;" satırının altına "using MSUtil;" satırını ekleyelim.

using System;
using MSUtil;

LogParser.dll içinde LogQuery sınıfını barındırır. Bu sınıf LogParser.exenin nesne halidir.
Artık Main metodunun içini yazmaya başlayab
iliriz. Main metodunu aşağıdaki şekilde değiştirin;

[STAThread]
static void Main(string [] args)
{

ILogQuery logQuery = new LogQueryClassClass();
ILogRecordset recordSet;
ILogRecord record;

recordSet = logQuery.Execute("select cs-uri-stem from <1> where sc-status=200", null);
for(; !recordSet.atEnd(); recordSet.moveNext())
{

record=recordSet.getRecord();
string val = record.getValue(0).ToString();
Console.WriteLine(val);

}
recordSet.close();

}

Kodu F5 tuşuna basarak çalıştırdığınızda, eğer daha önce IISte bir şeyler yapmışsanız, uzun bir çıktısı olacaktır.

Kodda üç adet değişken tanımladık;

  1. logQuery değişkeni; LogQueryClassClasstan türetilmiş. Bu sınıf LogParserın nesne yapısını tanımlayan temel sınıftır.
    logQuery değişkeninin tipi ILogQuery. Bu tip bir interfacedir (arabirim). Temel sınıfa bir referans gösterir.
  2. recordSet değişkeni; logQuerynin Execute metodu çağrıldığında geri döndürülen, tablodur.
  3. record değişkeni ise recordSetteki bir kayıda karşılık gelen değişkendir.

İlk iş olarak logQuery değişkeninin Execute metodu çağrılıyor ve sonuç recordSet değişkenine atanıyor. Bu metod iki parametre alır. İlki bir SQL ifadesi, diğeri de logun okunacağı girdi tipini belirtir, biz bu değere, SQL ifadesinin FROM kısmından belirlensin diye null atadık. Bu parametre hakkında daha detaylı bilgiyi uygulamayla gelen Word dokümanında bulabilirsiniz.
Execute metodu hemen çalışmaz, sadece sorguyu hazırlar ve dosya imlecini uygun yere getirir. Esas işlem recordSetin moveNext metodunda yapılır. Bu metod belirlenen şartlara uygun bir sonraki satırı bulur ve kayıt içeriğini hazırlar. recordSetin atEnd metodu ise dosyanın sonuna gelinip gelinmediğini gösterir. Böylece çok rahat bir şekilde log dosyası içinde, ileriye doğru hareket etmemiz sağlanır. Bu döngünün içinde record değişkenine, recordSetin getRecord metodu çağrılarak kayıt (satır) bilgisi alınır. recordun da getValue adlı bir metdou vardır. Bu metod bir int değeri alır ve uygun alan değerini döndürür. Böylece bir recordSetteki recordun herhangi bir alanının değeri okunabilir. Bizim uygulamamız sadece bu değeri ekrana yazıyor. recordSeti de dosya sonuna geldiğinde de kapatıyor.

Özellikler:

Şu ana kadar LogParserin kullanımını gördük. Biraz desteklenen SQL özelliklerinden bahsetmek gerek. Uygulama sadece SELECT ifadesini destekliyor, yani INSERT, UPDATE veya DELETE yapamıyorsunuz. Zaten amacı da bu değil. SQL standardı olarak herhangi bir standart derdi yok. Yani ANSI, ODBC, Microsoft SQL Server uyumluluğu düşünülmemiş. JOIN yapamıyorsunuz (gerek yok), matematiksel operasyonlar ADD, SUBTRACT gibi fonksiyonlar kullanılarak yapılabiliyor . Buna karşılık ek olarak pek çok eklenti fonksiyonu var, bunları uygulamayla gelen Word dosyasından okuyabilirsiniz. GROUP BY, ORDER BY, HAVING ifadeleri kullanılabiliyor. Aggregate (Sum, Count, Avg) fonksiyonları kullanabiliyorsunuz. FROM ifadesi biraz değişik çalışıyor, Burada dosya adı verebiliyorsunuz (Örn: ex040412.log), dosya adlarında maskeleme kullanabilirsiniz. Yani (ex*.log) yazdığınızda o dizindeki bütün "ex" ile başlayan, tipi "log" olan dosyalar incelenebilir. "<n>" ifadesi IISin "n"inci applikasyonunun o anki aktif loglarını inceler. Dosya adlarında boşluk kullanmanız gerekirse, boşluk yerine \u0020 yazın. Bu UNICODEda boşluk demektir. Örnek vermek gerekirse "C:\Program Files\a.log" yerine "C:\Program\u0020Files\xxx.log", C#ta ise şöyle yazılmalı @"C:\Program\u0020Files\a.log" veya "C:\\Program\\u0020Files\\a.log".

Uygulamanın okuyabildiği formatlar;

  1. Dizin yapısı: Bir dizindeki folderları bu uygulama sayesinde sorgulayabilirsiniz. Yani dosya adlarını, tarihlerini, boyutlarını sorgulayabilirsiniz.
  2. Text dosyaları: Bir dizinde içinde belirli text geçen dosyaları sorgulayabilirsiniz.
  3. Loglar: Makinanızdaki logları sorgulayabilirsiniz. Desteklenen formatlar:
    IIS W3C uyumlu loglar,
    IIS NCSA uyumlu loglar,
    IIS IIS uyumlu loglar,
    IIS ODBC uyumlu loglar,
    IIS BIN uyumlu loglar
    URLScan Log formatı
    System Event Logları
    CSV dosyaları (Virgülle ayrılmış dosyalar)

Ayrıca SELECT ifadesinde FROM ifadesinden sonra TO komutu da eklenmiştir. Bu komutla çıktının nereye yapılacağı belirlenir:

  1. Ekran
  2. IIS logu (Bir logdan sorgulama yaparak (FROM ile), başka bir log dosyasına çıktı üretebilirisiniz)
  3. W3C logu (amacı 2. madde ile aynıdır sadece dosya alan adları farklıdır)
  4. SQL çıktısı. Bu çok hoş bir özellik. Sonuçları bu özellik sayesinde bir veritabanına yazdırabilirsiniz.
  5. CSV formatında çıktı,
  6. XML dosyasına
  7. Template ile belirlenen şekilde. Bu özellik sayesinde template dosyaları oluşturup belirlenen formata uygun dosyalar üretebilirsiniz.

Uygulamayla beraber, detaylı bir Word dokümanı ve hem Scriptler için, hem de SQL ifadelerini açıklayan pek çok örnek dosya geliyor. Mesela IIS saldırılarını listeleyen script kodu var.

Kullanırken her makinaya tüm uygulamayı koymanıza gerek yok. Bir web farmda çalışıyorsanız sadece exe versiyonu kurabilir veya sadece dll versiyonu register edebilirsiniz. İki uygulama birbirinden bağımsız çalışmaktadır.

Sonuç:

Eğer Log dosyalarıyla uğraşmanız gerekiyorsa, bunu LogParser ile yapmanızı tavsiye ederim. Size alışık olduğunuz SQL ortamını veriyor ve elle pek çok kodlama yapma zahmetinden kurtarıyor. Ayrıca performansı kolay kolay geçilemiyor. Eğer ben daha hızlısını yaparım diyorsanız, o size ve vaktinize kalmış.

Mert Sakarya
Uygulama Mimarı
Doğan Online