プログラムによるLog4jロガーの構成


189

SLF4J(log4jバインディング付き)を初めて使用しようとしています。

さまざまなレベルをログに記録し、メッセージをさまざまなアペンダーにプッシュするLoggerFactoryによって返される3つの異なる名前付きロガーを構成したいと思います。

  • ロガー1 "FileLogger"はデバッグをログに記録し、 DailyRollingFileAppender
  • ロガー2 "TracingLogger"はTRACE +をログに記録し、 JmsAppender
  • ロガー3「ErrorLogger」はERROR +をログに記録し、別の JmsAppender

さらに、それらをプログラムで構成したい(XMLまたはlog4j.propertiesファイルではなく、Javaで)。

通常、メソッドのLoggerように、これらのsをブートストラップコードのどこかに定義すると思いますinit()。ただし、を使用したいのでslf4j-log4j、ロガーを定義してクラスパスで使用できるようにする場所に戸惑っています。

これはSLF4Jの根本的な目的(ファサードとして)に違反しいるとは思いません。SLF4JAPIを使用する私のコードは、これらのロガーが存在することを知らないためです。私のコードは、SLF4J APIへの通常の呼び出しを行うだけで、クラスパスで見つけたlog4jロガーに転送します。

しかし、Javaでクラスパスにこれらのlog4jロガーを設定するにはどうすればよいですか。



3
log4jは2.xの参照のために、以下の受け入れ答え使用1.Xについてlogging.apache.org/log4j/2.x/manual/customconfig.html
earcamを

回答:


277

プログラムでLog4jにAppenderを追加/削除できます。

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

これがどこかで確実に実行されるinit()のどこかに置くことをお勧めします。次に、ルートロガー上のすべての既存のアペンダーを削除できます

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

独自のものを追加することから始めます。もちろん、これを機能させるには、クラスパスにlog4jが必要です。

備考:
あなたはどの取ることができLogger.getLogger(...)、あなたがアペンダを追加したいです。ルートロガーはすべての最下部にあり、他のカテゴリの他のアペンダーを介して渡されるすべてを処理するので、ルートロガーを取得しました(追加フラグを設定して構成されていない限り)。

ロギングの仕組みと、ログの書き込み場所がどのように決定されているかを知る必要がある場合は、このマニュアルで詳細を確認してください。
要するに:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

カテゴリ「com.fizz」のロガーを提供します。
上記の例の場合、これは、ログに記録されたすべてのものがコンソールとルートロガーのファイルアペンダーに参照されることを意味します。
Logger.getLogger( "com.fizz")。addAppender(newAppender)にアペンダーを追加した場合、ロギングfizzはルートロガーとのすべてのアペンダーによって処理されnewAppenderます。
ロガーを構成で作成するのではなく、システムで可能なすべてのカテゴリのハンドラーを提供するだけです。


2
ありがとうoers!簡単な質問-ルートロガーにアペンダーを追加していることに気付きました。これには理由がありますか?
IAmYourFaja 2012年

さらに重要なことに、SLF4JのLoggerFactoryから取得するLoggerを指定する必要があります。SLF4Jにlog4jのルートロガーを要求することは可能ですか?
IAmYourFaja 2012年

3
@AdamTannon好きなLogger.getLogger(...)を取ることができます。ルートロガーはすべての最下部にあり、他のカテゴリの他のアペンダーを介して渡されるすべてのものを処理するため、ルートロガーを取得しました(特に構成されていない場合)。ロガー階層を参照
12

@AdamTannon sl4jファクトリを使用してlog4jルートロガーを取得することはできません。SL4jはロギングファサードです。それから特定のlog4jを取得しません。
2012年

2
oers-あなたの素晴らしいフィードバックに感謝しますが、ここですべての点を結び付けているわけではありません。例を変更して、システムに追加された後、それを要求する他のクラスで使用できる新しいロガー(ルートロガーではない)の追加を表示できますか?たとえば、通常は「Logger fizz = LoggerFactory.getLogger("com.fizz");Thanks!」などでアクセスされるロガー。
IAmYourFaja 2012年

47

「両端」(コンシューマー側と構成側)からlog4jを使用しようとしているようです。

slf4j apiに対してコード化したいが、クラスパスが返すlog4jロガーの構成を事前に(そしてプログラムで)決定する場合は、遅延構築を利用するある種のロギング適応が絶対に必要です。

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.apache.log4j.Logger debugLogger = org.apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

このアプローチを使用すると、log4jロガーがどこで/いつ設定されるかについて心配する必要はありません。クラスパスが初めてそれらを要求するとき、それらは遅延構築され、渡され、slf4jを介して利用可能になります。これが役に立てば幸い!


2
ばっちり成功!役立つ例をありがとうございました!@Oers-私を正しい方向に向けてくれてありがとう-私はあなたの献身に対してグリーンなチェックをしますが、それがまさに私が探していたものだったのでzharveyに賞金を与えなければなりません。みんなありがとう!
IAmYourFaja 2012年

4

log4jプロパティでアペンダーを定義していて、それをプログラムで更新したい場合は、log4jプロパティで名前を設定し、名前で取得します。

次に、log4j.propertiesエントリの例を示します。

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

更新するには、次の手順を実行します。

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);

1

誰かがJavaでプログラムでlog4j2を構成することを探している場合、このリンクが役立ちます:(https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class

コンソールアペンダーを構成するための基本的なコードは次のとおりです。

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

builder.setStatusLevel(Level.DEBUG);
// naming the logger configuration
builder.setConfigurationName("DefaultLogger");

// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
// add a layout like pattern, json etc
appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d %p %c [%t] %m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG);
rootLogger.add(builder.newAppenderRef("Console"));

builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());

これにより、デフォルトのrootLoggerが再構成され、新しいアペンダー作成されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.