15

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 を使用してこれを達成する方法はありますか?

4

4 に答える 4

11

slf4j 呼び出しのラッパーを作成し、6 つのログ レベル用に独自の列挙型を作成します。次に、ラッパーで、スイッチを使用して正しい slf4j 呼び出しを呼び出します。

void myLog(Level level, String message)
{
  switch (level)
  {
  case FATAL:
    log.fatal(message);
    break;
  case ERROR:
    log.error(message);
    break;
  ....
  }
}
于 2010-09-30T15:08:57.900 に答える
6

答えはノーです。この議論を参照してください。

于 2010-09-30T15:07:31.043 に答える
3

あなたのユースケースは委任パターンを求めています。基本的に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
}

これは、次のようなビジネス コードで使用されます。

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

于 2012-07-24T09:32:26.117 に答える
1

技術的には、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を使用して実行することは可能です。

于 2012-07-20T18:24:30.717 に答える