5

私は現在、モジュール (プラグインと考えてください) を持つことができるシステムを作成しています。このシステムでは、それぞれが専用のログを持つことができます。

ロギングに log4j2 プロジェクトを使用したいのですが、ファイル アペンダーに問題があるようです。

メイン プロジェクト (モジュール ローダーと全体の「コア」) には独自のログ ファイルが必要ですが、モジュールには独自のログ ファイル ( などmod_XXXXXXXX.log) が必要です。

アペンダーに関するドキュメントを読んでFileAppenderクラスを発見し、それを使用するつもりでした。によって作成されたデフォルトのロガーにアペンダーを単純に追加することはできないことがわかるまでLogManager.getLog()

LogManager によって返されるロガーは、インターフェイスとは異なるロガーですLogger

検索しても、近い解決策は得られませんでした。見つかったのは、xml 構成で定義済みのファイル ログだけでした。これは、私が望んでいるものではありません。

読んでくれてありがとう; わずかな手がかりでも大歓迎です:)

4

3 に答える 3

9

ログ ファイルを動的に決定する必要がある場合は、 Log4J2 RoutingAppenderを参照してください。より長い例はFAQにあり、これらのスタックオーバーフローの質問は興味深いかもしれません: Log4j2 の RoutingAppender のワイルドカード パターンlog4j2 (xml の MDC) を使用して異なるファイルに異なるログを書き込む方法は?

ThreadContextログイベントをルーティングするアペンダーを決定するために RoutingAppender が使用するマップに値を設定する必要があることに注意してください。これは、コードが別のプラグインに入るたびに、ThreadContext マップに何らかの値を設定する必要があることを意味します。

しかし、これほどダイナミックであることが本当に必要なのでしょうか? 使用しているプラ​​グインが事前にわかっている場合は、プラグインごとにロガーを宣言し (プラグインのパッケージ名を使用するのが一般的な方法です)、そのような各ロガーを個別のアペンダーにマップするだけです。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
    <File name="plugin1" fileName="logs/plugin1.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
    <File name="plugin2" fileName="logs/plugin2.log">
      <PatternLayout>
        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
      </PatternLayout>
    </File>
  </Appenders>
  <Loggers>
    <Logger name="com.mycomp.project.plugin1" level="debug">
      <AppenderRef ref="plugin1" level="debug" />
    </Logger>
    <Logger name="com.mycomp.project.plugin2" level="debug">
      <AppenderRef ref="plugin2" level="debug" />
    </Logger>
    <Root level="trace">
      <AppenderRef ref="MyFile" level="trace" />
    </Root>
  </Loggers>
</Configuration>
于 2013-09-28T22:11:38.800 に答える
0

モジュール管理コードでロガー構成を定義する必要があると思いますよね?もしそうなら、あなたが求めているものに基づいてLoggerConfigを拡張することについて説明しているマニュアルのこの部分を見てみたいと思うかもしれませ

http://logging.apache.org/log4j/2.x/manual/extending.html

価値のあることとして、私は以前に (OSGi を使用して) 大規模なプラグイン ベースのシステムに関与したことがありますが、正直なところ、このルートを選択したことはありません。通常は、関心のあるクラスまたはパッケージを 1 つのログ ファイルから grep する方が簡単です。

于 2013-09-27T14:30:19.403 に答える
0

Remko Popma の回答がログを記録する最も効率的な方法かもしれませんが、独自にログ ファイルを作成できる小さなクラスを作成しました。

私は受け入れられた回答の解決策を使用すると思うので、XMLファイルを回避するために私が書いたコードは次のとおりです。

import gnu.trove.map.hash.THashMap;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.async.AsyncLoggerContext;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.message.FormattedMessageFactory;
import org.apache.logging.log4j.message.MessageFactory;

import java.io.File;
import java.io.IOException;
import java.util.Map;

/**
 * Represents a manager for custom log files stored inside a log folder.
 */
public class LoggingManager {
    /** The default log file extension */
    public static final String FILE_EXTENSION = "log";

    /** The global context used for all loggers */
    private final LoggerContext context;

    /** The global message factory used for all loggers */
    private final MessageFactory msgFactory;

    /** A map of all created logs */
    private final Map<String, Logger> logCache;

    /** The folder containing the log files */
    private final File logFolder;


    public LoggingManager(String name, File logFolder) throws IOException {
        this.logFolder = logFolder;

        if(!logFolder.exists()) {
            if(!logFolder.mkdirs()) {
                throw new IOException("Could not create log folder");
            }
        }

        this.logCache = new THashMap<String, Logger>();

        // Create logger context
        this.context = new AsyncLoggerContext(name);

        // Create formatted message factory
        this.msgFactory = new FormattedMessageFactory();
    }

    public Logger getLogger(String name) {
        Logger logger = logCache.get(name);

        // Create a new one
        if(logger == null) {
            logger = new SimpleLogger(name);

            FileAppender appender = FileAppender.createAppender(
                    new File(logFolder, name + "." + FILE_EXTENSION).getAbsolutePath(),
                    "true",
                    "false",
                    "file_appender-" + name,
                    "true",
                    "false",
                    "true",
                    PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, null, null, "UTF-8", "true"),
                    null,
                    "false",
                    null,
                    null
            );

            appender.start();
            logger.getContext().getConfiguration().getLoggerConfig("root").addAppender(appender, Level.ALL, null);

            // Add to log cache
            logCache.put(name, logger);
        }

        // Return the logger
        return logger;
    }

    private class SimpleLogger extends Logger {

        public SimpleLogger(String name) {
            super(context, name, msgFactory);

            // Set to all levels
            this.setLevel(Level.ALL);
        }

    }

}

使用しない場合は、必要に応じtroveて通常の Java に置き換えることができHashMapます。

于 2013-09-30T09:55:46.347 に答える