java SLF4J 日志级别作为参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3831785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:34:47  来源:igfitidea点击:

SLF4J Log Level as an argument

javaloggingslf4j

提问by marchaos

We are looking to use SLF4J, but one thing we found was that you can't specify the level as an argument, i.e

我们正在寻找使用 SLF4J,但我们发现的一件事是您不能将级别指定为参数,即

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

You have to do this

你必须这样做

logger.info("message");

this prevents being able to pass everything through a method, so you can tack other properties to all log messages in a class.

这阻止了能够通过方法传递所有内容,因此您可以将其他属性附加到类中的所有日志消息。

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());
    }
}

Is there a way to achieve this using SLF4j ?

有没有办法使用 SLF4j 实现这一目标?

回答by Starkey

Write a wrapper around the slf4j call and create your own enum for the six log levels. Then in your wrapper, use a switch to call the correct slf4j call.

围绕 slf4j 调用编写一个包装器,并为六个日志级别创建自己的枚举。然后在您的包装器中,使用开关来调用正确的 slf4j 调用。

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

回答by Raghuram

The answer is No. Refer to this discussion.

答案是否定的。请参阅此讨论

回答by A.H.

Your usecase screams for the delegation pattern. Basically you wedge your own implementation of Loggerbetween your code and SLF4J and "extend" the relevant methods:

您的用例为委托模式尖叫。基本上你Logger在你的代码和 SLF4J 之间楔入你自己的实现并“扩展”相关方法:

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
}

This is use in the business code like this:

这是在业务代码中使用的,如下所示:

public class Test
{
    Logger log;

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

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

For optimal reusability of the MyLoggerclass SomeObjshould either use Object.toString()or it should implement an interface which MyLoggercan use to get the message addendum.

为了实现MyLogger类的最佳可重用性,SomeObj应该使用Object.toString()或实现一个MyLogger可用于获取消息附录的接口。

回答by PaulG

Well, technically SLF4J doesn't offer you a logger.log(Level, message) method. But I found a way around that. [edit: uses introspection]

好吧,从技术上讲,SLF4J 没有为您提供 logger.log(Level, message) 方法。但我找到了解决办法。[编辑:使用内省]

Using the below code snippet you can get the native logger that slf4j found and wrapped for you at runtime. If you'll recall, slf4j is simply a wrapper around an slf4j implementation from another provider (either, jdkLogging, Log4J, JCL, etc...). So here:

使用下面的代码片段,您可以获得 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;
}

Then you can use it like this:

然后你可以像这样使用它:

   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 ...)...

So while it's not technically within slf4j, it is possible to do it using slf4j as your primary logging interface.

因此,虽然它在技术上不在 slf4j 中,但可以使用 slf4j 作为主要日志记录界面来实现。