2010-09-30 13 views
11

हम SLF4J का उपयोग करने के लिए देख रहे हैं, लेकिन एक बात हमने पाया था कि आप एक तर्क के रूप स्तर निर्दिष्ट नहीं कर सकते, यानीSLF4J लॉग स्तर एक तर्क के रूप

Logger.log(Level.INFO, "messsage"); 

आप इस

क्या करना है
logger.info("message"); 

यह किसी विधि के माध्यम से सब कुछ पारित करने में सक्षम होने से रोकता है, ताकि आप कक्षा में सभी लॉग संदेशों के लिए अन्य गुणों का सामना कर सकें।

public class Test 
{ 
    public Test(SomeObj obj) 
    { 
     log(Level.INFO, "message"); 
    } 

    public void anotherMethod() 
    { 
     log(Level.DEBUG, "another message"); 
    } 
    private void log(Level level, String message) 
    { 
     logger.log(level, message + obj.someString()); 
    } 
} 

क्या SLF4j का उपयोग करके इसे प्राप्त करने का कोई तरीका है?

+1

पास स्ट्रिंग "INFO" और "DEBUG" पास करें, और सही विधि का आह्वान करने के लिए प्रतिबिंब का उपयोग करें - बस मजाक कर रहे हैं! – irreputable

+0

वास्तव में यह बहुत शॉर्ट्स और अफसोसपूर्ण है कि अधिकांश (शायद सभी) समकालीन लॉगर्स अभी भी उस पुरातन प्रतिमान का पालन करते हैं – matanster

उत्तर

6

उत्तर संख्या this discussion का संदर्भ लें।

+0

ऐसा करने का एक तरीका है, लेकिन इसमें देशी लॉगजर को एक हैंडल प्राप्त करना शामिल है जो slf4j पाया गया। - नीचे मेरा जवाब देखें। – PaulG

8

slf4j कॉल के चारों ओर एक रैपर लिखें और छः लॉग स्तरों के लिए अपना स्वयं का enum बनाएँ। फिर अपने रैपर में, सही slf4j कॉल को कॉल करने के लिए एक स्विच का उपयोग करें।

void myLog(Level level, String message) 
{ 
    switch (level) 
    { 
    case FATAL: 
    log.fatal(message); 
    break; 
    case ERROR: 
    log.error(message); 
    break; 
    .... 
    } 
} 
1

अच्छा, तकनीकी रूप से SLF4J आपको एक logger.log (स्तर, संदेश) विधि प्रदान नहीं करता है। लेकिन मुझे इसके चारों ओर एक रास्ता मिला। [संपादित करें: आत्मनिरीक्षण का उपयोग करता है]

नीचे दिए गए कोड स्निपेट का उपयोग करके आप देशी लॉगर प्राप्त कर सकते हैं जो slf4j आपके लिए रनटाइम पर पाया और लपेटा गया है। यदि आपको याद आएगा, तो slf4j किसी अन्य प्रदाता (या तो, jdkLogging, Log4J, JCL, आदि ...) से एक slf4j कार्यान्वयन के आसपास बस एक रैपर है। तो यहाँ:

public Object getNativeLogger(org.slf4j.Logger logger) { 
    Object result = null; 
    if (logger.getClass().getName().equals("org.slf4j.impl.Log4jLoggerAdapter")) { 
     try { 
     Field f = Log4jLoggerAdapter.class.getDeclaredField("logger"); 
     f.setAccessible(true); 
     result = (org.apache.log4j.Logger)f.get(logger); 
     } 
     catch(Exception e) { 
     System.out.println("Unable to access native log4j logger"); 
     } 
    } 
    else if (logger.getClass().getName().equals("org.slf4j.impl.JDK14LoggerAdapter")) { 
     try { 
     Field f = Jdk14Logger.class.getDeclaredField("logger"); 
     f.setAccessible(true); 
     result = (Jdk14Logger)f.get(logger); 
     } 
     catch(Exception e) { 
     System.out.println("Unable to access native log4j logger"); 
     } 
    } 
    else if (..... other native loggers slf4j supports).... 
    } 
    return result; 
} 

तो फिर तुम इसे इस तरह उपयोग कर सकते हैं: तो

Object l = getNativeLogger(mySlf4jLogger); 
    if (l instanceof org.apache.log4j.Logger) { 
     org.apache.log4j.Logger logger = (org.apache.log4j.Logger) l; 
     logger.log(CUSTOMLog4JLevel, message); 
    } 
    else if(.... other implementations that you care about ...)... 

जबकि यह तकनीकी रूप से slf4j भीतर नहीं है, यह आपके प्राथमिक प्रवेश इंटरफेस के रूप में slf4j का उपयोग कर यह करने के लिए संभव है।

2

आपका उपयोगकेस प्रतिनिधिमंडल पैटर्न के लिए चिल्लाता है। मूल रूप से आप अपने कोड और SLF4J और के बीच Logger का अपना स्वयं का कार्यान्वयन कील "विस्तार" प्रासंगिक तरीके: के इष्टतम पुनर्प्रयोग के लिए

public class Test 
{ 
    Logger log; 

    public Test(SomeObj obj) 
    { 
     log = new MyLogger(Test.class, obj); 
     log.logInfo("message"); 
    } 

    public void anotherMethod() 
    { 
     logDebug("another message"); 
    } 
} 

:

class MyLogger implements Logger { 

    Logger realLogger; 
    Object userData; 


    MyLogger(Class clazz, Object userData){ 
     this.realLogger = LoggerFactory.getLogger(clazz); 
    } 

    public void debug(String msg) { 
     realLogger.debug(msg + userData.someString()); 
    } 

    // many more methods, perhaps per java.lang.reflect.Proxy 
} 

यह इस तरह व्यापार कोड में इस्तेमाल होता है MyLogger कक्षा SomeObj या तो Object.toString() का उपयोग करना चाहिए या इसे एक इंटरफ़ेस लागू करना चाहिए जो संदेश परिशिष्ट प्राप्त करने के लिए MyLogger उपयोग कर सकता है।

संबंधित मुद्दे