Cumartesi, Kasım 18, 2006

Log4A (Log for Admins)

Hepimizin bildiği gibi test ve production ortamlarında bir hata alındığında, bu hatanın esas kaynağını tespit etmek epey vakit alan bir işlemdir. Eğer hata bir de kritik bir süreci durduruyorsa, bir sürü insan seferber edilmek zorunda kalınır. Hataların kaynağının tespitinin zor olmasının başlıca nedenlerinden biri de Java'da exception durumunda yapılan loglamanın System Admin'ler düşünerek yapılmıyor olmasıdır.

Bir Developer olarak eğer daha evvel Application veya Database Adminliği yapmadıysanız, kodlarınız içinde yapacağınız loglama daha çok development amaçlı olacaktır. Halbuki test ve production ortamlarında ihtiyaç duyulan loglama çok farklıdır. Log4j kullanıyor dahi olsalar eğer loglama yaparken kendini Admin yerine koyabilenler çok daha yararlı loglar yazdırdığınızı fark edeceklerdir.

Peki bir Developer kodlama yaparken kendini Admin yerine nasıl koyar. Öncelikle local'inizde development yaparken, sorunun nerden kaynaklandığını bir bakışta anlayamadığınız bir hata almayı bekleyin. Bu hatayı aldığınızda normalde ilk olarak yaptığınız şey debug etmek olacaktır. İşte bu noktada kesinlikle debug yapmayın, unutmayın kendinizi Admin yerine koydunuz, production ortamında debug imkanı yok. Şimdi debug yapmadan mevcut loglara bakarak hatanızı bulmaya çalışın, yarım saat geçtikten sonra hala bulamadıysanız, bir de akşam saatleri ise artık kesin Admin gibi hissetmeye başlamış olmanız lazım. Bu kadar duygu sömürüsü yaptıktan sonra isterseniz Log4A örneklerine geçelim ve hangi durumlardaki loglamaların önemli olduğuna bir bakalım.

Test ve production ortamlarındaki hataların yaklaşık %75'i entegrasyon hatalarından oluşur. Özellikle bir çok katmanın bulunduğu mimarilerde bu tip entegrasyon hataları daha çok olur. Bu tip hataların en çok çıktığı durumları özetlersek:
  1. Database Connection (JDBC Connection)
  2. File System Access (file read, write)
  3. Classpath Access (Configuration file, class loading, etc.)
  4. Remote Application Server Access (RMI, Remote EJB Call, etc.)
Yukarıdaki özetlediğimiz şekilde, kod içerisinde uygulamanızın dışındaki bir ortama erişimde bir hata alındığında aşağıdaki örneklerdeki gibi loglama yapmanız çok faydalı olacaktır. Öncelikle bir tane loglama yapılmış ama Log4A kullanılmamış bir kod örneğine bakalım. Aşağıdaki kod parçasında sql query'sindeki tablonun production ortamına atılmamış olduğunu varsayalım:

public static String getCustomerName(String customerID){

String customerName="";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:TEST", USERNAME, PASSWORD);
String query = "SELECT * from CUSTOMER_INFO where CUSTOMER_ID="+customerID;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
customerName = rs.getString("CUSTOMER_NAME");
}
connection.close();
} catch (Exception e) {
logger.error(e);
e.printStackTrace();
}
return customerName;
}

Bu kodu çalıştırdığımızda şu şekilde bir hata alıyoruz.

java.sql.SQLException: ORA-00942: tablo veya görüntü mevcut degil

Gördüğünüz gibi Admin olarak tablonun hangisi olduğunu, hangi veritabanında olduğunu bilmemiz mümkün değil. Saolsun Oracle da tablo adını vermediği için elimiz ayağımız bağlı. Developer'a ulaşıp yardım almaktan başka çaremiz yok. Stacktrace'ten koda bakıp tabloyu tespit etmeye de çalışabiliriz ama aynı metod içinde birden fazla sql de olduğu durumlar olabilir. Bunun yerine aşağıdaki şekilde Log4A yaparsak Admin'lerin hatanın kaynağını hemen tespit edebilir:

public static String getCustomerName(String customerID){
String query = "";
String dbUrl = "";
String customerName="";
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
dbUrl = "jdbc:oracle:thin:@localhost:1521:TEST";
Connection connection = DriverManager.getConnection(dbUrl, USERNAME, PASSWORD);

String query = "SELECT * from CUSTOMER_INFO where CUSTOMER_ID="+customerID;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
customerName = rs.getString("CUSTOMER_NAME");
}
connection.close();
} catch (Exception e) {
logger.error("query= "+query); //Log4A
logger.error("dbUrl= "+dbUrl); //Log4A

logger.error(e);
e.printStackTrace();
}
return customerName;
}


Bu kodu çalıştırdığımızda ise şu şekilde çok daha açıklayıcı bir hata alıyoruz:

query= SELECT * from CUSTOMER_INFO where CUSTOMER_ID=12345678
dbUrl= jdbc:oracle:thin:@localhost:1521:TEST
java.sql.SQLException: ORA-00942: tablo veya görüntü mevcut degil

Gördüğünüz gibi hatanın hangi veritabanında, hangi tabloda olduğu apaçık belli. Bu sayede hatanın sebebini tespit etmek artık çok daha kolay. Bizim örneğimizde parametre olarak
connection url vardı , EJB uygulamalarında bu parametre DataSource olabilir, sql yerine store procedure olabilir. Benzer örnekleri aynı mantıkla çoğaltabiliriz ama sanırım gerek yok.

Özetle bir hata alındığında hataya sebep olabilecek kritik parametrelerin try bloğundan önce initiliaze edilip, exception bloğunda loglanmasına Log4A diyoruz. Bu sayede Adminler test ortamlarında günlerce, production ortamlarında saatlerce hataların sebeplerini aramak zorunda kalmazlar.

0 Yorum:

Yorum Gönder

Kaydol: Kayıt Yorumları [Atom]

<< Ana Sayfa