ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Log4j – 在运行时重新加载日志记录级别 > 原文: [https://howtodoinjava.com/log4j/how-to-reload-log4j-levels-on-runtime/](https://howtodoinjava.com/log4j/how-to-reload-log4j-levels-on-runtime/) 过多的日志记录是导致应用性能下降的常见原因。 它是[**最佳实践**](//howtodoinjava.com/category/best-practices/ "java best practices")之一,可确保 Java EE 应用实现中的正确日志记录。 但是,请注意在生产环境中启用的日志记录级别。 过多的日志记录将触发服务器上的高 IO,并增加 CPU 使用率。 对于使用较旧硬件的较旧环境或处理大量并发卷的环境而言,这尤其可能成为问题。 ```java A balanced approach is to implement a "reloadable logging level" facility to turn extra logging ON / OFF when required in your day to day production support. ``` 让我们看看如何使用 Java 7 提供的[**`WatchService`**](https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html "WatchService")完成此操作。 ## 步骤 1)实现一个`WatchService`,它将监听给定 log4j 文件中的更改 下面的给定代码初始化了一个线程,该线程连续监视给定 log4j 文件(`StandardWatchEventKinds.ENTRY_MODIFY`)中的修改。 一旦观察到文件更改,就会调用`configurationChanged()`方法,并使用 `DOMConfigurator.configure()`方法再次重新加载 log4j 配置。 **`Log4jChangeWatcherService.java`** ```java package com.howtodoinjava.demo; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import org.apache.log4j.xml.DOMConfigurator; public class Log4jChangeWatcherService implements Runnable { private String configFileName = null; private String fullFilePath = null; public Log4jChangeWatcherService(final String filePath) { this.fullFilePath = filePath; } //This method will be called each time the log4j configuration is changed public void configurationChanged(final String file) { System.out.println("Log4j configuration file changed. Reloading logging levels !!"); DOMConfigurator.configure(file); } public void run() { try { register(this.fullFilePath); } catch (IOException e) { e.printStackTrace(); } } private void register(final String file) throws IOException { final int lastIndex = file.lastIndexOf("/"); String dirPath = file.substring(0, lastIndex + 1); String fileName = file.substring(lastIndex + 1, file.length()); this.configFileName = fileName; configurationChanged(file); startWatcher(dirPath, fileName); } private void startWatcher(String dirPath, String file) throws IOException { final WatchService watchService = FileSystems.getDefault().newWatchService(); //Define the file and type of events which the watch service should handle Path path = Paths.get(dirPath); path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { watchService.close(); } catch (IOException e) { e.printStackTrace(); } } }); WatchKey key = null; while (true) { try { key = watchService.take(); for (WatchEvent< ?> event : key.pollEvents()) { if (event.context().toString().equals(configFileName)) { //From here the configuration change callback is triggered configurationChanged(dirPath + file); } } boolean reset = key.reset(); if (!reset) { System.out.println("Could not reset the watch key."); break; } } catch (Exception e) { System.out.println("InterruptedException: " + e.getMessage()); } } } } ``` ## 2)添加`Log4jConfigurator`,这是您的应用与 log4j 协作的接口 此类是一个工具类,它将 log4j 初始化代码和重载策略与应用代码分开。 **`Log4jConfigurator.java`** ```java package com.howtodoinjava.demo; public class Log4jConfigurator { //This ensures singleton instance of configurator private final static Log4jConfigurator INSTANCE = new Log4jConfigurator(); public static Log4jConfigurator getInstance() { return INSTANCE; } //This method will start the watcher service of log4j.xml file and also configure the loggers public void initilize(final String file) { try { //Create the watch service thread and start it. //I will suggest to use some logic here which will check if this thread is still alive; //If thread is killed then restart the thread Log4jChangeWatcherService listner = new Log4jChangeWatcherService(file); //Start the thread new Thread(listner).start(); } catch (Exception e) { e.printStackTrace(); } } } ``` ## 3)测试 log4j 重载事件 为了测试代码,我记录了两个两个语句:一个调试级别和一个信息级别。 两个语句在循环 2 秒后都被记录。 我将在一些日志语句之后更改日志记录级别,并且应该重新加载 log4j。 **`log4j-config.xml`** ```java <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%t] %-5p %c %x - %m%n"/> </layout> </appender> <root> <priority value ="info" /> <appender-ref ref="console" /> </root> </log4j:configuration> ``` **`Log4jConfigReloadExample.java`** ```java package com.howtodoinjava.demo; import org.apache.log4j.Logger; public class Log4jConfigReloadExample { private static final String LOG_FILE_PATH = "C:/Lokesh/Setup/workspace/Log4jReloadExample/log4j-config.xml"; public static void main(String[] args) throws InterruptedException { //Configure logger service Log4jConfigurator.getInstance().initilize(LOG_FILE_PATH); //Get logger instance Logger LOGGER = Logger.getLogger(Log4jConfigReloadExample.class); //Print the log messages and wait for log4j changes while(true) { //Debug level log message LOGGER.debug("A debug message !!"); //Info level log message LOGGER.info("A info message !!"); //Wait between log messages Thread.sleep(2000); } } } Output: [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! Log4j configuration file changed. Reloading logging levels !! [main] DEBUG com.howtodoinjava.demo.Log4jConfigReloadExample - A debug message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! [main] DEBUG com.howtodoinjava.demo.Log4jConfigReloadExample - A debug message !! [main] INFO com.howtodoinjava.demo.Log4jConfigReloadExample - A info message !! ``` **祝您学习愉快!**