1. 思路

使用 spring-jmx、jolokia 将 JMX 封装并暴露 restful 接口,便于操作。

2. logback 实现

2.1. JMXConfiguratorMBean

接口 ch.qos.logback.classic.jmx.JMXConfiguratorMBean 提供了如下操作入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void reloadDefaultConfiguration() throws JoranException;
void reloadByFileName(String fileName) throws JoranException, FileNotFoundException;
void reloadByURL(URL url) throws JoranException;
void setLoggerLevel(String loggerName, String levelStr);
String getLoggerLevel(String loggerName);
String getLoggerEffectiveLevel(String loggerName);
List<String> getLoggerList();
List<String> getStatuses();

2.2. JMXConfigurator

ch.qos.logback.classic.jmx.JMXConfigurator 实现了 JMXConfiguratorMBean

实例化 JMXConfigurator 并使用 spring-jmx 暴露。

该类构造方法中的 ch.qos.logback.classic.LoggerContext 对象,可通过 (LoggerContext) LoggerFactory.getILoggerFactory() 获取。

3. log4j2 实现

log4j2 中未提供 JMX 操作接口,不过通过查看源码可知:

  1. org.apache.logging.slf4j.Log4jLogger,是 slf4jlog4j2 桥接实现
  2. Log4jLogger 是代理的 org.apache.logging.log4j.spi.ExtendedLogger 具体日志输出功能
  3. 被代理的 ExtendedLogger 是通过 org.apache.logging.log4j.spi.LoggerContext#getLogger(java.lang.String) 实例化的
  4. getLogger 是通过在 org.apache.logging.log4j.core.LoggerContext#newInstance new 一个 org.apache.logging.log4j.core.Logger 的实例
  5. org.apache.logging.log4j.core.Logger 提供了 org.apache.logging.log4j.core.Logger#setLevel 方法设置日志级别

因此,只需要使用 spring-jmx 封装一个对象,提供 setLevel 方法,在该方法中,通过 org.apache.logging.log4j.LogManager#getLogger(java.lang.String) 获取到 logger,再调用该 logger 的 setLevel 方法即可;

由于 org.apache.logging.log4j.core.LoggerContext#loggerRegistry 缓存了同名的的 logger,可以保证设置的其他使用的是同一个 logger 实例。