`

JMX实现Log4J级别的运行时动态更改

    博客分类:
  • java
阅读更多

    首先来介绍一下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();


    下面的是它的实现类,实现了NotificationPublisherAware接口,在运行的时候会注入一个NotificationPublisher对象,实现Notification的发送。

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();
	}


}


下面定义的是Notification的类型

public enum NotificationType {
     CHANGE_LOG_LEVEL, RESET_CONFIGURATION
}


其实最主要的就是下面的配置文件,借助sping的JMX Support,就可以避免了MBean的注册等一些细节。

<!-- Service to set the log level of a class. -->
    <bean id="loggingMBean" class="de.stefanheintz.log.jmxservice.LoggingConfigImpl"/>
	<bean id="exporterLogConfig" class="org.springframework.jmx.export.MBeanExporter">
		<property name="beans">
			<map>
				<entry key="de.stefanheintz.log:jmxservice=loggingConfiguration" value-ref="loggingMBean" />
			</map>
		</property>
		<property name="assembler">
	      <bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
	        <property name="managedInterfaces">
	          <value>de.stefanheintz.log.jmxservice.LoggingConfig</value>
	        </property>
	      </bean>
	    </property>
	</bean>



    首先我们先介绍一下运行该程序的系统属性的设置:

-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


下面我们介绍一下测试,我们构造一个客户端程序,然后使用jconsole调用刚才我们暴露的接口来更改log级别,然后客户端程序的log信息会有相应的调整,然后再jconsole里面可以看到客户端发出的Notification。

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");
		}
	}

}


用jconsole连接后,可以找到我们的mbean,然后我们调用mbean暴露的函数,可以看到客户端的日志信息会实时的变化。






  • 大小: 13.7 KB
  • 大小: 21.8 KB
分享到:
评论
7 楼 spyker 2010-03-28  
log对外暴露jmx服务 如果我没有记错的话 应该只是一个设置的问题
你仔细看一看log4j的文档
它的配置文件支持jmx的
6 楼 spyker 2010-03-28  
logger的filter可以根据包来进行设置
还可以根据logger的内容进行 过滤 
这些是log的设置

jmx控制log可以通过spring很简单的完成
5 楼 spyker 2010-03-28  
calorie520 写道
曾开发过这样的系统,通过日志控制台,下发日志策略到日志系统中,这些日志策略有:日志记本地,日记写远程文件,日志写数据库,同时可控制只记录某个时间段的日志。这样的项目如果控制台和日志系统都是Java开发的话,很适合使用JMX来控制,当然通过其他协议下发策略也是可以的,当初我们项目就是通过UDP承载syslog协议来做的

去年 自己弄了一个用jmx控制日志  流量监测 系统启动和关闭的东西

日志采用的是sl4j
spring2.0
4 楼 nickycheng 2010-03-28  
对不起,问下。 log4j在web容器下不是可以自己监控配置文件的更改并做对应的修改吗?
3 楼 sw1982 2010-03-27  
确实遇到过。。一直没认真研究。
2 楼 calorie520 2010-03-27  
曾开发过这样的系统,通过日志控制台,下发日志策略到日志系统中,这些日志策略有:日志记本地,日记写远程文件,日志写数据库,同时可控制只记录某个时间段的日志。这样的项目如果控制台和日志系统都是Java开发的话,很适合使用JMX来控制,当然通过其他协议下发策略也是可以的,当初我们项目就是通过UDP承载syslog协议来做的
1 楼 asialee 2010-03-27  
大家没有遇到要动态更改级别的问题吗?

相关推荐

    动态设置log4j的日志级别

    总结来说,动态设置Log4j的日志级别是提高应用灵活性的重要手段,可以根据运行时的需求调整日志输出的详细程度,同时避免不必要的重启操作。通过配置文件、API、JMX以及Web界面等多种方式,开发者可以方便地实现这一...

    运行时改变log4j日志级别

    本文将详细讲解如何在运行时改变Log4j的日志级别,这对于调试和性能优化至关重要。我们将从以下几个方面进行探讨: 1. **日志级别介绍** 日志级别是Log4j中控制日志输出的关键,它定义了不同严重程度的消息应该被...

    log4j使用教程(详解)

    - 日志级别动态调整:在运行时可以通过JMX(Java Management Extensions)或者修改配置文件动态改变日志级别。 - 异步日志记录:通过使用AsyncAppender,可以实现日志记录的异步化,提高系统性能。 - 日志归档:...

    apache-log4j-2.15.0-bin.tar.gz

    3. **动态日志配置**:通过JMX(Java Management Extensions)或API,可以在运行时动态更改日志级别和配置,无需重启应用。 4. **插件架构**:Log4j 2支持插件,用户可以自定义Appenders(输出目的地)、Layouts...

    log4j-users-guide-2.5

    Log4j2 提供了对 JMX 的支持,可以通过 JMX 来管理和监控 Log4j2 的配置和运行时状态: - **动态配置更改**:能够在不重启应用的情况下改变日志配置。 - **性能监控**:可以实时监控 Log4j2 的性能指标,如日志事件...

    Log4j.rar

    Log4j的JMX(Java Management Extensions)支持允许我们在运行时动态调整日志配置,这对调试和性能监控非常有用。 此外,Log4j还支持插件系统,这意味着开发者可以自定义Appender和Layout,以满足特定场景的需求。...

    Common-log 和log4j2 配合使用

    为了实现动态日志级别调整,可以利用`log4j2`的API或者JMX管理工具。例如,如果你想在运行时将日志级别改为DEBUG,可以这样做: ```java import org.apache.logging.log4j.LogManager; import org.apache.logging....

    apache-log4j-2.0-beta9-bin.zip

    8. **JMX(Java Management Extensions)控制台**:Log4j 2.0可以通过JMX控制台动态修改配置,监控和管理日志系统,提供了更便捷的操作界面。 9. **日志事件的生命周期**:Log4j 2.0中的日志事件经历了创建、过滤、...

    apache-log4j-2.16.0-bin.tar.gz

    2. **动态配置**:Log4j 2支持动态配置,允许在运行时更改日志级别和配置,无需重启应用。通过JMX(Java Management Extensions)或API可以实现这一功能。 3. **插件体系结构**:Log4j 2允许开发自定义的Appenders...

    log4j2-log4j-2.15.0-rc2.zip

    2. 动态配置:Log4j2支持动态日志级别调整和配置更改,无需重启应用即可生效。这对于开发和运维团队来说,大大提高了工作效率。 3. 安全性增强:Log4j2团队时刻关注安全问题,2.15.0-rc2可能包含对已知安全漏洞的...

    log4j2在SpringMVC工程中的运用

    为了实现日志级别动态调整,可以利用Log4j2的JMX控制台或者通过配置文件的参数来改变日志级别。例如,如果希望在生产环境中降低日志输出,可以将`level="info"`改为`level="error"`。 最后,如果需要将日志数据输出...

    Log4j的使用

    在运行时,我们可以通过JMX(Java Management Extensions)或者修改配置文件来动态调整日志级别,无需重启应用。 **5. 源码分析** Log4j的源码提供了一个学习Java设计模式和日志系统实现的好机会。它利用了工厂...

    Log4j2手册阅读随笔(Log4j2新特性)

    Log4j2手册详细介绍了该库的各个方面,包括架构、迁移、API、配置、Web应用程序集成、插件、查找、Appenders、布局、过滤器、异步记录器、无垃圾日志记录、JMX、日志分离以及如何扩展Log4j。 Log4j2是E.U.SEMPER...

    log4j技术参考文档

    - **日志级别动态调整**: 在运行时,可以通过JMX(Java Management Extensions)或者重新加载配置文件来改变日志级别。 - **异步日志记录**: 通过使用AsyncAppender,可以提高日志记录的性能,避免阻塞主线程。 - ...

    log4j2 2.15日志例子

    1. **动态日志级别**:Log4j2支持动态调整日志级别,可以在运行时通过JMX或API更改。 2. **异步日志记录**:提供异步日志记录器,显著提高日志性能。 3. **插件体系**:拥有丰富的插件库,如SMTP Appender、MongoDB ...

    log4j2.0教程(英文版)

    Log4j 2.0集成了JMX(Java Management Extensions),允许通过JMX代理管理和监控日志记录行为。借助JMX,可以动态地更改日志配置、查看日志统计信息等。这对于生产环境中的日志管理非常有用,可以在不影响应用程序...

    DymLog4jTest

    本文将深入探讨"Log4j热部署"这一主题,解释如何在服务器运行时动态调整Log4j的输出级别,而无需重启服务器,以实现"DymLog4jTest"的功能。 首先,理解Log4j的基本概念至关重要。Log4j是一个开源的Java日志API,它...

    lo4j2数据开发必备帮你规避不必要的线上bug

    8. **动态配置**:Log4j2支持运行时动态调整配置,可以通过JMX(Java Management Extensions)或者API来实现,无需重启应用即可更改日志设置。 9. **性能优化**:合理配置Log4j2可以帮助优化性能,例如,减少不必要...

    Log4j2Tutorial

    5. **JMX集成**:JMX(Java Management Extensions)是一个用于管理和监控Java应用程序的工具,Log4j2可以通过JMX动态调整日志配置,如改变日志级别。 6. **插件系统**:Log4j2的插件系统允许扩展其功能,如自定义...

    slf4j+logback的jar和配置文件

    SLF4J是一个日志门面,它提供了一个统一的接口,允许开发人员在运行时插入所需的日志框架,如Logback、Log4j或Java内置的日志系统。Logback则是SLF4J的一个实现,它高效且功能强大,被许多开发者视为替代Log4j的首选...

Global site tag (gtag.js) - Google Analytics