SLF4J 日志级别作为参数

发布于 2024-09-25 21:58:28 字数 584 浏览 4 评论 0原文

我们正在寻找使用 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 来实现这一点?

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

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

还如梦归 2024-10-02 21:58:28

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

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

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.

void myLog(Level level, String message)
{
  switch (level)
  {
  case FATAL:
    log.fatal(message);
    break;
  case ERROR:
    log.error(message);
    break;
  ....
  }
}
别挽留 2024-10-02 21:58:28

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

The answer is No. Refer to this discussion.

七色彩虹 2024-10-02 21:58:28

您的用例迫切需要委托模式。基本上,您可以在代码和 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可以使用该接口来获取消息附录。

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

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 MyLogger class SomeObj should either use Object.toString() or it should implement an interface which MyLogger can use to get the message addendum.

终止放荡 2024-10-02 21:58:28

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

使用下面的代码片段,您可以获取 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 作为主要日志记录接口来实现。

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

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:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文