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作为主要日志记录接口来实现。