2012-11-02 21 views
8

İşte genel kabul görmüş gibi görünüyor iki ifade vardır, ama gerçekten üstesinden edemez:slf4j'de parametrelenmiş günlüğe kaydetme - scala'nın ad parametrelerine göre nasıl karşılaştırılır?

1) Scala'nın by-name incelikle yerine params o kadar da can sıkıcı log4j kullanım deseni:

if (l.isDebugEnabled()) { 
     logger.debug("expensive string representation, eg: godObject.toString()") 
    } 

çünkü by-name-parametresi (Scala'ya özgü dil özelliği) yöntem çağırma işleminden önce değerlendirilmiyor.

2) Ancak, bu sorun slf4f içinde parametrized giriş yaparak çözüldü :

logger.debug("expensive string representation, eg {}:", godObject[.toString()]); 

Yani, bu nasıl çalışır? slf4j kitaplığında, "hata ayıklama" yöntemi yürütme işleminden önce parametrenin değerlendirilmesini engelleyen bazı düşük düzeyli sihir var mı? (Bu mümkün mü? kütüphanesi, dilin böyle temel bir yönünü etkileyebilir mi?)

Veya bir nesnenin bir String'den ziyade yönteme geçirilmesi basit bir gerçektir? (ve belki de bu nesnenin toString() öğesi, varsa, debug() yönteminde çağrılır).

Fakat o zaman, log4j için de geçerli değil mi? (Nesne paramları ile yöntemleri vardır). Ve bu, bir dizgeyi iletirseniz - yukarıdaki kodda olduğu gibi - log4j ile aynı şekilde davranacağı anlamına gelmez mi?

Bu konuda biraz ışık tutmayı çok isterim.

Teşekkürler!

cevap

24

slf4j'de sihir yok. günlüğü ile sorun eğer ayıklama seviyesi pahalı bir işlem olabilen Logger'da etkin veya, her zaman godObject.toString() değerlendirdi olmasaydı o sırada

logger.debug("expensive string representation: " + godObject) 

olursa olsun diyelim log istediğini eskiden ve sonra ayrıca dizgi birleştirme. Bu, Java (ve çoğu dilde) argümanlarının bir işleve geçmeden önce değerlendirilmesinden gelir.

Bu nedenle, slf4j, logger.debug(String msg, Object arg)'u (ve daha fazla argüman için diğer türevleri) sunmuştur. Tüm fikir, debug işlevine ucuz argümanları iletmeniz ve bunlara toString numaralı telefonu çağırmanız ve bunları yalnızca hata ayıklama düzeyi açıksa bir iletiyle birleştirmenizdir. Eğer debug için geçirmeden önce

logger.debug("expensive string representation, eg: {}", godObject.toString()); 

arayarak size ölçüde olursa olsun düzeyi ne olduğunu ayıklama, sen her zaman godObject dönüştürmek bu yolu olarak, bu avantajı azaltmak olduğunu

Not. Buna hala ideal değildir, ancak sadece

logger.debug("expensive string representation, eg: {}", godObject); 

kullanmalıdır. Yalnızca toString numaralı telefonu ve dizgi birleştirmeyi yedekler. Ancak, günlüğe kaydetme mesajınız, mesajı oluşturmak için başka bir pahalı işlem gerektiriyorsa, yardımcı olmaz.Gibi iletiyi oluşturmak için bazı expensiveMethod aramak gerekirse:

logger.debug("expensive method, eg: {}", 
    godObject.expensiveMethod()); 

sonra expensiveMethod hep logger geçirilmeden önce değerlendirilir. verimli slf4j ile bu işi yapmak için, hala

if (logger.isDebugEnabled()) 
    logger.debug("expensive method, eg: {}", 
     godObject.expensiveMethod()); 

geri başvurmak zorunda Eğer bir işlev nesnesine kod keyfi parçasını sarmak ve izin verdiğinden, bu konuda çok yardımcı olur Call-by-name Scala'nın Bu kodu sadece gerektiğinde değerlendirin. Bu tam da ihtiyacımız olan şey. Örneğin, slf4s'a bir bakalım. Bu kütüphane slf4j en Logger yılında Neden hiç argümanlar gibi

def debug(msg: => String) { ... } 

gibi yöntemler sunar? Çünkü artık onlara ihtiyacımız yok. Biz sadece

logger.debug("expensive representation, eg: " + 
    godObject.expensiveMethod()) 

Biz bir ileti ve bağımsız değişkenlerini geçemiyor yazabilir, doğrudan iletiye değerlendirilir kod parçası geçmektedir. Ancak, sadece logger bunu yapmaya karar verirse. Hata ayıklama düzeyi açık değilse, logger.debug(...) içinde hiç bir şey değerlendirilmez, tüm şey atlanır. Ne expensiveMethod ne de herhangi bir toString çağrılır veya dizi birleştirme gerçekleşir. Yani bu yaklaşım en genel ve en esnek. Ne kadar karmaşık olursa olsun, String ile debug arasında değerlendirilen tüm ifadeleri iletebilirsiniz.

+1

Crystal clear, çok teşekkürler. Galiba tam bir açıklamanın, umduğum ve ummadığım büyüyü oluşturduğunu sanıyorum. :) – teo

İlgili konular