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实现这一目标?
在slf4j调用周围编写一个包装器,并为六个日志级别创建自己的枚举。 然后在你的包装器中,使用一个开关来调用正确的slf4j调用。
void myLog(Level level, String message) { switch (level) { case FATAL: log.fatal(message); break; case ERROR: log.error(message); break; .... } }
答案是否定的。请参阅此讨论 。
你的用例为代表模式尖叫。 基本上你在你的代码和SLF4J之间楔入你自己的Logger
实现并“扩展”相关的方法:
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 }
这在商业代码中使用,如下所示:
public class Test { Logger log; public Test(SomeObj obj) { log = new MyLogger(Test.class, obj); log.logInfo("message"); } public void anotherMethod() { logDebug("another message"); } }
为了MyLogger
类的最佳可重用性, SomeObj
应该使用Object.toString()
或者它应该实现一个MyLogger
可以用来获取消息附录的接口。
好吧,从技术上讲,SLF4J不提供logger.log(级别,消息)方法。 但我找到了解决方法。 [编辑:使用内省]
使用下面的代码片段,您可以获得slf4j在运行时找到并包装的本机记录器。 如果你还记得,slf4j只是来自另一个提供者的slf4j实现的包装器(jdkLogging,Log4J,JCL等……)。 所以在这里:
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作为主要日志记录接口来实现。