【问题标题】:Dynamically/Programmatically configuring your own asynclogger in Log4j2在 Log4j2 中动态/编程配置您自己的异步记录器
【发布时间】:2014-04-11 04:14:33
【问题描述】:

我的项目中已经实现了一个旧的 log4j1.x,我们通过扩展类 org.apach.log4j.logger 创建了自己的记录器。但是现在我们想迁移到 Log4j2因为它有 asynLogger。下面的代码是否实现了异步日志记录的所有功能,以编程方式创建时支持我的 log4j2

        import java.util.HashMap;

        import org.apache.logging.log4j.Level;
        import org.apache.logging.log4j.core.LoggerContext;
        import org.apache.logging.log4j.core.appender.ConsoleAppender;
        import org.apache.logging.log4j.core.appender.RandomAccessFileAppender;
        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;

        public final class MyLog4j2Logger extends
                org.apache.logging.log4j.core.async.AsyncLogger {

            private static HashMap<String, MyLog4j2Logger> logCache = new HashMap<String, MyLog4j2Logger>(4);

            private MyLog4j2Logger(LoggerContext context, String name,MessageFactory msgFactory) {
                super(context, name, msgFactory);
                System.out.println("Using AsyncLogger");

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

            /*
            * Factory Method that returns an instance of Logger. returns if the
            * instance is already present in the Hash Table else creates now and
            * returns it.
            */
            public final static MyLog4j2Logger getCustomLogger(String sCategory) {
                try {
                    System.setProperty("Log4jContextSelector",
                            "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
                    // Check if Instance is already present for the Category
                    if (logCache.containsKey(sCategory)) {
                        MyLog4j2Logger logger = logCache.get(sCategory);
                        logger.info("Getting already created logger for " + sCategory);
                        return logger;
                    } else {

                        // Create a new custom logger for this category
                        MyLog4j2Logger customLogger = configureCategoryLogger(sCategory);

                        // Add the custom logger to Table.
                        logCache.put(sCategory, customLogger);

                        customLogger.info("Created a New Logger for " + sCategory);

                        return (MyLog4j2Logger) customLogger;
                    }
                } catch (Exception exp) {
                    System.out
                            .println("Exception thrown while fetching Logger instance");
                    exp.printStackTrace();
                }

                return null;

            }

            private static MyLog4j2Logger configureCategoryLogger(String sCategory) {

                // Create logger context
                LoggerContext context = new AsyncLoggerContext(sCategory);

                // Create formatted message factory
                MessageFactory msgFactory = new FormattedMessageFactory();

                MyLog4j2Logger logger = new MyLog4j2Logger(context, sCategory,
                        msgFactory);

                RandomAccessFileAppender appender = RandomAccessFileAppender
                        .createAppender(
                                "C:\\temp\\App.log",// filename
                                "true",// append
                                "file_appender-" + sCategory,// name
                                "true",// immediateFlush
                                "",// bufferSize
                                "true",// ignoreExceptions
                                PatternLayout.createLayout(
                                        "%-5p - [%d] - [%t] - [%l]  : %m%n", null,
                                        null, "UTF-8", "true", sCategory), null,// filter
                                "false",// advertise
                                null,// advertiseURI
                                null// config
                        );

                ConsoleAppender consoleAppender = ConsoleAppender.createAppender(
                        PatternLayout.createLayout("%-5p - [%d] - [%t] - [%l]  : %m%n",
                                null, null, "UTF-8", null, null), null, null,
                        "Console", null, null);

                appender.start();
                consoleAppender.stop();
                logger.getContext().getConfiguration().getLoggerConfig(sCategory)
                        .addAppender(appender, Level.TRACE, null);
                logger.getContext().getConfiguration().getLoggerConfig(sCategory)
                        .addAppender(consoleAppender, Level.OFF, null);
                System.out.println(logger.getContext().getConfiguration()
                        .getAppenders());

                return logger;

            }

            public static void main(String[] args) {

                MyLog4j2Logger logger = MyLog4j2Logger.getCustomLogger("TESTING");
                logger.debug("Debug MSG");
                logger.error("Error MSG");
                logger.info("INFO msg");

            }

        }

【问题讨论】:

  • Log4j 初始化相当复杂。我确信可以创建仅执行 log4j 的一些初始化并且仍然有效的自定义代码,但我不明白您为什么要这样做。基于标准配置的 log4j-2.0 初始化有问题吗? (在那种情况下,我想了解这个问题,以便我们可以解决它而不是试图解决它......)
  • 谢谢。我们扩展 Asynlogger 类的主要目的是减少/限制 MyLog4j2Logger 中 log4j 模块的依赖关系。如果我们想在不影响我们的应用程序代码的情况下切换到任何其他记录器框架,这将很有帮助。
  • 为了保持与 log4j-core 的前向兼容性(可能没有像 log4j-api 这样的稳定​​ API),我建议与 log4j-core 开发保持同步。看起来这对于编程配置来说效果很好,但在未来,我们将使 API 更易于用于编程配置。在这种情况下,使用配置文件并将 log4j 实例包装在您自己的上下文中会更容易,如果您愿意的话。
  • Sats,我现在更了解您的想法了。我认为子类化 log4j2 实现类不是一个好主意。这是很多工作,但回报很少。如果您想潜在地切换到不同的日志记录框架,请考虑使用 slf4j。这是一个广泛使用的日志外观,它具有 log4j、logback 和 log4j2 的实现(“绑定”)。如果您真的想自己开发一些东西,我建议您编写一个简单的包装器。

标签: logging asynchronous log4j log4j2


【解决方案1】:

Log4j2 中的 AsyncLogger 可以完成您的代码 sn-p 所做的一切(以及更多)。我会检查并为您的应用程序配置它以降低代码的复杂性。

【讨论】:

  • 感谢 Matt。我们扩展 Asynlogger 类的主要目的是减少/限制 MyLog4j2Logger 中 log4j 模块的依赖关系。如果我们想切换到任何其他记录器框架而不影响我们的应用程序代码,这将很有帮助。请确认上述方法是否是扩展异步记录器的正确步骤。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多