2013-06-04 16 views
42

logback.xmlにlogback.xmlが定義されています。これはDBアペンダですが、Beanとして定義された独自の接続プールを使用してJavaでappenderを設定する方法があるかどうか不思議です。LogBack appenderをプログラムで設定します

私は似たようなことをしますが、実際の答えは決してありません。

答えて

87

私の作品の簡単な例(私はこの例ではFileAppenderを使用することに注意してください)

import org.slf4j.LoggerFactory; 

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.LoggerContext; 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; 
import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.FileAppender; 

public class Loggerutils { 

    public static void main(String[] args) { 
      Logger foo = createLoggerFor("foo", "foo.log"); 
      Logger bar = createLoggerFor("bar", "bar.log"); 
      foo.info("test"); 
      bar.info("bar"); 
    } 

    private static Logger createLoggerFor(String string, String file) { 
      LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
      PatternLayoutEncoder ple = new PatternLayoutEncoder(); 

      ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n"); 
      ple.setContext(lc); 
      ple.start(); 
      FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>(); 
      fileAppender.setFile(file); 
      fileAppender.setEncoder(ple); 
      fileAppender.setContext(lc); 
      fileAppender.start(); 

      Logger logger = (Logger) LoggerFactory.getLogger(string); 
      logger.addAppender(fileAppender); 
      logger.setLevel(Level.DEBUG); 
      logger.setAdditive(false); /* set to true if root should log too */ 

      return logger; 
    } 

} 
+0

@Andrew Swan:あなたは現在のバージョンで変更したいことをコメントに書き留めてください。私はそれに応じてそれを更新しようとします。 – reto

+0

@reto私の変更は主に(1)クラス宣言を追加してそのままコンパイルし、(2)欠落した "g"を "Loger"に追加します。 –

+1

入力いただきありがとうございます。私はこれらの事を更新しました。 – reto

14

プログラムでアペンダーを構成できます。ほぼすべてのアペンダーは、プログラムによる設定を使用してテストされます。ログバックプロジェクトのソースコードには、プログラム上のアペンダー設定の例がたくさんあります。ログバックコアのアペンダの場合はlogback-core/src/test/java、ログバックの場合はlogback-classic/src/test/javaの古典的なアペンダです。ここで

2

だけで、誰かがプログラム的な構成の具体的な例を探しているならば。ここで

IセットアップConsoleAppenderの文字セット:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
ConsoleAppender<ILoggingEvent> appender = 
    (ConsoleAppender) lc.getLogger("appconsole").getAppender("STDOUT"); 
LayoutWrappingEncoder<ILoggingEvent> enc = 
    (LayoutWrappingEncoder<ILoggingEvent>) appender.getEncoder(); 
enc.setCharset(Charset.forName("utf-8")); 

そして、私のlogback.xml:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder> 
     <charset>866</charset> 
     <pattern>[%level] %msg%n</pattern> 
    </encoder> 
</appender> 

<logger name="appconsole"> 
    <appender-ref ref="STDOUT" /> 
</logger> 

私はロガーを設定programmaticaly必要なぜ?なぜなら、私は自分のアプリケーション(Spring Boot)をjarファイルにパッケージ化しているからです。その結果、Logback.xmlファイルはjar内で非表示に見えます。しかし、それを解凍して変更すると便利ではありません。そして私は私のapp.jarの横に任意のlogback.xmlファイルは必要ありません。 appのすべての設定プロパティを含むapp.yamlファイルのみがあります。

3

参考までに、ロガーの作成を担当するコードを変更しようとすると、ロガーが機能するために必要な一連のルールがあります。

これらのルールは偉大で親切記事Programmatic configuration of slf4j/logbackで説明された。今、私はSLF4J/logbackのプログラム構成での経験を持って

タスク

プログラムは、各処理された入力ファイルの個別のログファイルを開く必要があります。代わりにXMLを介しlogback設定のタスク

ため

ソリューション、一つは「手動」そして、それらを一緒に設定し、リンク、エンコーダ、アペンダとロガーをインスタンス化する必要があります。

警告1

Logbackはアペンダ間エンコーダ(すなわちPatternLayoutEncoder)を共有しようとする試みに狂っ進みます。警告1

ため

解決策は、各アペンダのための別個のエンコーダを作成します。エンコーダとアペンダは、ロギングコンテキストに関連付けられていない場合

警告2

Logbackは、何をログに記録することを拒否します。パラメータとしてLoggerFactory を通過各エンコーダとアペンダーに警告2

コールsetContext用

ソリューション。エンコーダとアペンダが開始されていない場合

警告3

Logbackは、何をログに記録することを拒否します。警告3

エンコーダとアペンダため

ソリューションが正しい順序で起動する必要がある、即ち、第1のエンコーダは、アペンダ。

警告4

RollingPolicyオブジェクト(すなわちTimeBasedRollingPolicy)それらはアペンダと同じコンテキストに取り付けられていない場合、「認識されない日付形式」のような奇妙なエラーメッセージを生成します。エンコーダとアペンダのようRollingPolicy同様の注意点4

コールsetContextため

ソリューション。ここで

は「手動」logback構成の実施例である:コメント(?まだ)は許可されていません

package testpackage 

import ch.qos.logback.classic.Level 
import ch.qos.logback.classic.Logger 
import ch.qos.logback.classic.LoggerContext 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder 
import ch.qos.logback.core.ConsoleAppender 
import ch.qos.logback.core.rolling.RollingFileAppender 
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy 

import org.slf4j.LoggerFactory 

class TestLogConfig { 

    public static void main(String[] args) { 
    LoggerContext logCtx = LoggerFactory.getILoggerFactory() 

    PatternLayoutEncoder logEncoder = new PatternLayoutEncoder() 
    logEncoder.setContext(logCtx) 
    logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level - %msg%n') 
    logEncoder.start() 

    ConsoleAppender logConsoleAppender = new ConsoleAppender() 
    logConsoleAppender.setContext(logCtx) 
    logConsoleAppender.setName('console') 
    logConsoleAppender.setEncoder(logEncoder) 
    logConsoleAppender.start() 

    logEncoder = new PatternLayoutEncoder() 
    logEncoder.setContext(logCtx) 
    logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level - %msg%n') 
    logEncoder.start() 

    RollingFileAppender logFileAppender = new RollingFileAppender() 
    logFileAppender.setContext(logCtx) 
    logFileAppender.setName('logFile') 
    logFileAppender.setEncoder(logEncoder) 
    logFileAppender.setAppend(true) 
    logFileAppender.setFile('logs/logfile.log') 

    TimeBasedRollingPolicy logFilePolicy = new TimeBasedRollingPolicy() 
    logFilePolicy.setContext(logCtx) 
    logFilePolicy.setParent(logFileAppender) 
    logFilePolicy.setFileNamePattern('logs/logfile-%d{yyyy-MM-dd_HH}.log') 
    logFilePolicy.setMaxHistory(7) 
    logFilePolicy.start() 

    logFileAppender.setRollingPolicy(logFilePolicy) 
    logFileAppender.start() 

    Logger log = logCtx.getLogger("Main") 
    log.additive = false 
    log.level = Level.INFO 
    log.addAppender(logConsoleAppender) 
    log.addAppender(logFileAppender) 
    } 
} 
0

、私は3つのヒントを追加したいと思います。

  • 上記の注意事項に関する問題が発生した場合は、すべてがあなたの がroot /「メイン」のアペンダを追加した後、つまり、設定された後、ちょうど

    StatusPrinter.print(context); 
    

    に呼び出しを追加アペンダー:それはあなたに何が間違っているか教えてください。

  • 私は非常に多くのファイルのログレベルを分離するのが好きです。エラーを探しているとき、私は彼らが

    private static class ThresholdLoggerFilter extends Filter<ILoggingEvent> { 
    
         private final Level level; 
    
         private ThresholdLoggerFilter(Level level){ 
          this.level = level; 
         } 
    
         @Override 
         public FilterReply decide(ILoggingEvent event) { 
          if (event.getLevel().isGreaterOrEqual(level)) { 
           return FilterReply.NEUTRAL; 
          } else { 
           return FilterReply.DENY; 
          } 
         } 
        } 
    
    ようなシンプルなプライベートフィルタクラスによって

tot_[app name].log : Level.INFO 
deb_[app name].log : Level.DEBUG 
err_[app name].log : Level.ERROR 

ルーティングのように設定したので、上のエラーファイルに見て、で始まります

とし、myFilter.start()myAppender.addFilter(myFilter);を呼び出してください。

  • 最後に、それを一緒に入れて、私は通常

    いくつかのプロパティのルートログレベルを維持
    public interface LoggingService { 
        void setRootLogLevel(Level level); 
    } 
    

のようないくつかの簡単なインターフェイスを実装し、動的に設定したログレベルを変更することができるようにしたいです-fileこれは、有効な入力があるたびに、このサービスを次のように実装するように監視されます。

@Override 
    public void setRootLogLevel(Level level) { 
     if (context != null && context.isStarted()) { 
     ((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(level); 
     } 
    } 

に私の新しいルートロガーレベルがあります。

関連する問題