Log4j2:动态创建多个日志的日志文件

我目前正在创建一个可以拥有模块的系统(将它们视为插件),其中每个模块都可以拥有自己的专用日志。

我想使用log4j2项目进行日志记录,但我似乎在使用文件appender时遇到了一些问题。

主项目(模块加载器和整个事物的“核心”)应该有自己的日志文件,而模块应该有自己的(如mod_XXXXXXXX.log )。

通过阅读有关appender的文档,我发现了FileAppender类,我打算使用它。 直到我发现我不能简单地将appender添加到LogManager.getLog()创建的默认记录器中。

LogManager返回的记录器是与Logger接口不同的记录Logger

即使搜索没有给我任何近乎解决方案,我发现只是xml配置中的预定义文件日志 – 这不是我想要的。

谢谢你的阅读; 即使是最轻微的线索也欢迎:)

如果您确实需要动态确定日志文件,请查看Log4J2 RoutingAppender 。 一个较长的例子是在FAQ中 ,这些stackoverflow问题可能是有意义的: Log4j2的RoutingAppender的Wildcard模式和如何用log4j2(MDC in xml)在不同的文件中写入不同的日志?

请注意,您需要在ThreadContext映射中设置RoutingAppender用于决定将日志事件路由到哪个appender的值。 这意味着每次代码进入不同的插件时,您需要在ThreadContext映射中放置一些值。

但是,你真的需要这种动态吗? 如果你事先知道你有什么插件,你可以为每个插件声明一个记录器(使用插件的包名是执行此操作的常用方法),并将每个这样的记录器映射到单独的appender。

      %d %p %c{1.} [%t] %m%n     %d %p %c{1.} [%t] %m%n     %d %p %c{1.} [%t] %m%n                

我假设您希望模块管理代码定义记录器配置,对吧? 如果是这样,您可能需要查看本手册中有关扩展LoggerConfig的部分,该部分基于您的询问是我认为您正在寻找的内容。

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

为了它的价值,我之前(使用OSGi)参与了大型基于插件的系统,我们老实说没有走这条路。 从单个日志文件中grep您感兴趣的类或包通常更容易。

尽管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 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(); // 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