JMX实现Log4J级别的运行时动态更改
首先来介绍一下MBean暴露的接口,主要是根据filter得到logger,设置logger的对象,动态的得到当前log4j的配置等,这个比较简单。
import org.apache.log4j.Level;public interface LoggingConfig {/** * * @param filter returns only loggers, which contain the filter string * @return all available loggers */public String[] getLoggers(String filter);/** * assigns the {@link Level#INFO} to the given class * @param target the FQCN of the class */public void assignInfoLevel(String target);/** * assigns the {@link Level#WARN} to the given class * @param target the FQCN of the class */public void assignWarnLevel(String target);/** * assigns the {@link Level#ERROR} to the given class * @param target the FQCN of the class */public void assignErrorLevel(String target);/** * assigns the {@link Level#DEBUG} to the given class * @param target the FQCN of the class */public void assignDebug(String target);/** * assigns the {@link Level#FATAL} to the given class * @param target the FQCN of the class */public void assignFatalLevel(String target);/** * assigns the {@link Level#TRACE} to the given class * @param target the FQCN of the class */public void assignTraceLevel(String target);/** * deactivates the logging of the given class * @param target the FQCN of the class */public void deactivateLogging(String target);/** * reloads the log4j configuration from the <code>log4j.properties</code> file in the classpath */public void resetConfiguration();/** * * @return the log4j configuration from the <code>log4j.properties</code> file in the classpath */public String printLog4jConfig();
import java.io.PrintWriter;import java.io.StringWriter;import java.net.URL;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.management.Notification;import org.apache.log4j.Level;import org.apache.log4j.LogManager;import org.apache.log4j.Logger;import org.apache.log4j.PropertyConfigurator;import org.apache.log4j.config.PropertyPrinter;import org.apache.log4j.spi.LoggerRepository;import org.springframework.jmx.export.notification.NotificationPublisher;import org.springframework.jmx.export.notification.NotificationPublisherAware;public class LoggingConfigImpl implements LoggingConfig, NotificationPublisherAware {private Map<NotificationType, Long> notificationTypeMap = new HashMap<NotificationType, Long>();private NotificationPublisher publisher;public void setNotificationPublisher(NotificationPublisher notificationPublisher) { this.publisher = notificationPublisher; }public String[] getLoggers(String filter) {LoggerRepository r = LogManager.getLoggerRepository();Enumeration<Logger> enumList = r.getCurrentLoggers();Logger logger = null;List<String> resultList = new ArrayList<String>();while (enumList.hasMoreElements()) {logger = (Logger) enumList.nextElement();if (filter == null|| (filter != null && logger.getName().contains(filter))) {resultList.add(logger.getName());}}return (String[]) resultList.toArray(new String[] {});}public void assignInfoLevel(String target) {assignLogLevel(target, Level.INFO);}public void assignWarnLevel(String target) {assignLogLevel(target, Level.WARN);}public void assignErrorLevel(String target) {assignLogLevel(target, Level.ERROR);}public void assignDebug(String target) {assignLogLevel(target, Level.DEBUG);}public void assignFatalLevel(String target) {assignLogLevel(target, Level.FATAL);}public void deactivateLogging(String target) {assignLogLevel(target, Level.OFF);}public void assignTraceLevel(String target) {assignLogLevel(target, Level.TRACE);}private void assignLogLevel(String target, Level level) {String message = level.toString() + " for '" + target + "'";Logger existingLogger = LogManager.exists(target);if(existingLogger != null) {Level currentLevel = existingLogger.getLevel();if(currentLevel == null) {message = "initial to " + message;} else {message = "from " + currentLevel.toString() + " to " + message;}} LogManager.getLogger(target).setLevel(level);sendNotification(NotificationType.CHANGE_LOG_LEVEL, message);}private synchronized void sendNotification(NotificationType notificationType, String message) {Long counter = 0L;if(!notificationTypeMap.containsKey(notificationType))notificationTypeMap.put(notificationType, counter);counter = notificationTypeMap.get(notificationType);notificationTypeMap.put(notificationType, Long.valueOf(counter + 1));Notification notification = new Notification(notificationType.toString(), this, counter);notification.setUserData(message);publisher.sendNotification(notification);}public void resetConfiguration() {ClassLoader cl = getClass().getClassLoader();LogManager.resetConfiguration();URL log4jprops = cl.getResource("log4j.properties");if (log4jprops != null) {PropertyConfigurator.configure(log4jprops);}sendNotification(NotificationType.RESET_CONFIGURATION , "used file: " + log4jprops.getFile());}public String printLog4jConfig() {StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);PropertyPrinter pp = new PropertyPrinter(pw);pp.print(pw);// System.out.println(sw.toString());return sw.toString();}}
public enum NotificationType { CHANGE_LOG_LEVEL, RESET_CONFIGURATION}
<!-- Service to set the log level of a class. --> <bean id="loggingMBean" value-ref="loggingMBean" /></map></property><property name="assembler"> <bean name="code">-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=8004-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=8004-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=true-Dcom.sun.management.jmxremote.access.file=D:/temp/jmxremote.access-Dcom.sun.management.jmxremote.password.file=D:/temp/jmxremote.password
public class LetsGo {/** * @param args */public static void main(String[] args) {Test test = new TestImpl(); }}public interface Test {void logAllLogLevels();}import org.apache.log4j.Logger;public class TestImpl implements Test {private static final Logger logger = Logger.getLogger(TestImpl.class);public void logAllLogLevels() {while (true) {try {Thread.currentThread().sleep(500L);} catch (InterruptedException e) {e.printStackTrace();}logger.trace("This is the TRACE logging");logger.debug("This is the DEBUG logging");logger.warn("This is the WARN logging");logger.info("This is the INFO logging");logger.error("This is the ERROR logging");logger.fatal("This is the FATAL logging");}}}