Author: rpopma
Date: Sun Jan 5 11:06:48 2014
New Revision: 1555481
URL: http://svn.apache.org/r1555481
Log:
LOG4J2-443 Fixed issue where log4j2 LoggerContext did not show up in JMX GUI or
JConsole
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
logging/log4j/log4j2/trunk/src/changes/changes.xml
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java?rev=1555481&r1=1555480&r2=1555481&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
Sun Jan 5 11:06:48 2014
@@ -37,6 +37,7 @@ import org.apache.logging.log4j.core.con
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.core.helpers.Assert;
import org.apache.logging.log4j.core.helpers.NetUtils;
+import org.apache.logging.log4j.core.jmx.Server;
import org.apache.logging.log4j.message.MessageFactory;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.status.StatusLogger;
@@ -380,6 +381,13 @@ public class LoggerContext implements or
* instance.start(); Configuration old = setConfiguration(instance);
* updateLoggers(); if (old != null) { old.stop(); }
*/
+
+ try {
+ Server.reregisterMBeansAfterReconfigure();
+ } catch (final Exception ex) {
+ LOGGER.error("Could not reconfigure JMX", ex);
+ }
+
LOGGER.debug("Reconfiguration completed");
}
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java?rev=1555481&r1=1555480&r2=1555481&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
Sun Jan 5 11:06:48 2014
@@ -21,7 +21,6 @@ import java.net.URI;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.helpers.Constants;
import org.apache.logging.log4j.core.helpers.Loader;
-import org.apache.logging.log4j.core.jmx.Server;
import org.apache.logging.log4j.core.selector.ClassLoaderContextSelector;
import org.apache.logging.log4j.core.selector.ContextSelector;
import org.apache.logging.log4j.spi.LoggerContextFactory;
@@ -55,11 +54,6 @@ public class Log4jContextFactory impleme
if (selector == null) {
selector = new ClassLoaderContextSelector();
}
- try {
- Server.registerMBeans(selector);
- } catch (final Exception ex) {
- LOGGER.error("Could not start JMX", ex);
- }
}
/**
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java?rev=1555481&r1=1555480&r2=1555481&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
Sun Jan 5 11:06:48 2014
@@ -16,8 +16,6 @@
*/
package org.apache.logging.log4j.core.jmx;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Map;
@@ -32,6 +30,7 @@ import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
+import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.AsyncAppender;
@@ -39,7 +38,9 @@ import org.apache.logging.log4j.core.asy
import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
import org.apache.logging.log4j.core.async.AsyncLoggerContext;
import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.impl.Log4jContextFactory;
import org.apache.logging.log4j.core.selector.ContextSelector;
+import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.apache.logging.log4j.status.StatusLogger;
/**
@@ -51,6 +52,8 @@ import org.apache.logging.log4j.status.S
public final class Server {
private static final String PROPERTY_DISABLE_JMX = "log4j2.disable.jmx";
+ private static final StatusLogger LOGGER = StatusLogger.getLogger();
+ static final Executor executor = Executors.newFixedThreadPool(1);
private Server() {
}
@@ -104,8 +107,7 @@ public final class Server {
// avoid creating Platform MBean Server if JMX disabled
if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
- StatusLogger.getLogger().debug(
- "JMX disabled for log4j2. Not registering MBeans.");
+ LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
return;
}
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -128,45 +130,75 @@ public final class Server {
final MBeanServer mbs) throws JMException {
if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
- StatusLogger.getLogger().debug(
- "JMX disabled for log4j2. Not registering MBeans.");
+ LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
return;
}
- final Executor executor = Executors.newFixedThreadPool(1);
registerStatusLogger(mbs, executor);
registerContextSelector(selector, mbs, executor);
final List<LoggerContext> contexts = selector.getLoggerContexts();
registerContexts(contexts, mbs, executor);
+ }
+
+ public static void reregisterMBeansAfterReconfigure() {
+ // avoid creating Platform MBean Server if JMX disabled
+ if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
+ LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
+ return;
+ }
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ reregisterMBeansAfterReconfigure(mbs);
+ }
+
+ public static void reregisterMBeansAfterReconfigure(MBeanServer mbs) {
+ if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
+ LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
+ return;
+ }
+
+ try {
+ unregisterStatusLogger(mbs);
+ registerStatusLogger(mbs, executor);
+ } catch (Exception ex) {
+ LOGGER.error("Could not register MBeans", ex);
+ }
+
+ final ContextSelector selector = getContextSelector();
+ if (selector == null) {
+ LOGGER.debug("Could not register MBeans: no ContextSelector
found.");
+ return;
+ }
- for (final LoggerContext context : contexts) {
- context.addPropertyChangeListener(new PropertyChangeListener() {
+ // first unregister the old MBeans
+ unregisterContextSelector(mbs);
+ unregisterContexts(mbs);
+ unregisterLoggerConfigs("*", mbs);
+ unregisterAsyncLoggerConfigRingBufferAdmins("*", mbs);
+ unregisterAppenders("*", mbs);
+ unregisterAsyncAppenders("*", mbs);
- @Override
- public void propertyChange(final PropertyChangeEvent evt) {
- if (!LoggerContext.PROPERTY_CONFIG.equals(evt
- .getPropertyName())) {
- return;
- }
- // first unregister the MBeans that instrument the
- // previous instrumented LoggerConfigs and Appenders
- unregisterLoggerConfigs(context.getName(), mbs);
-
unregisterAsyncLoggerConfigRingBufferAdmins(context.getName(), mbs);
- unregisterAppenders(context.getName(), mbs);
- unregisterAsyncAppenders(context.getName(), mbs);
-
- // now provide instrumentation for the newly configured
- // LoggerConfigs and Appenders
- try {
- registerLoggerConfigs(context, mbs, executor);
- registerAppenders(context, mbs, executor);
- } catch (final Exception ex) {
- StatusLogger.getLogger().error(
- "Could not register mbeans", ex);
- }
- }
- });
+ // now provide instrumentation for the newly configured
+ // LoggerConfigs and Appenders
+ try {
+ registerContextSelector(selector, mbs, executor);
+ final List<LoggerContext> contexts = selector.getLoggerContexts();
+ registerContexts(contexts, mbs, executor);
+ for (LoggerContext context : contexts) {
+ registerLoggerConfigs(context, mbs, executor);
+ registerAppenders(context, mbs, executor);
+ }
+ } catch (final Exception ex) {
+ LOGGER.error("Could not register mbeans", ex);
+ }
+ }
+
+ private static ContextSelector getContextSelector() {
+ ContextSelector selector = null;
+ final LoggerContextFactory factory = LogManager.getFactory();
+ if (factory instanceof Log4jContextFactory) {
+ selector = ((Log4jContextFactory) factory).getSelector();
}
+ return selector;
}
/**
@@ -207,7 +239,7 @@ public final class Server {
throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
final StatusLoggerAdmin mbean = new StatusLoggerAdmin(executor);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
}
private static void registerContextSelector(final ContextSelector
selector, final MBeanServer mbs,
@@ -215,7 +247,7 @@ public final class Server {
NotCompliantMBeanException {
final ContextSelectorAdmin mbean = new ContextSelectorAdmin(selector);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
}
/**
@@ -232,15 +264,23 @@ public final class Server {
unregisterContext(ctx.getName());
final LoggerContextAdmin mbean = new LoggerContextAdmin(ctx,
executor);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
if (ctx instanceof AsyncLoggerContext) {
RingBufferAdmin rbmbean =
AsyncLogger.createRingBufferAdmin(ctx.getName());
- mbs.registerMBean(rbmbean, rbmbean.getObjectName());
+ register(mbs, rbmbean, rbmbean.getObjectName());
}
}
}
+ private static void unregisterStatusLogger(final MBeanServer mbs) {
+ unregisterAllMatching(StatusLoggerAdminMBean.NAME, mbs);
+ }
+
+ private static void unregisterContextSelector(final MBeanServer mbs) {
+ unregisterAllMatching(ContextSelectorAdminMBean.NAME, mbs);
+ }
+
private static void unregisterLoggerConfigs(final String contextName,
final MBeanServer mbs) {
final String pattern = LoggerConfigAdminMBean.PATTERN;
@@ -248,6 +288,12 @@ public final class Server {
unregisterAllMatching(search, mbs);
}
+ private static void unregisterContexts(final MBeanServer mbs) {
+ final String pattern = LoggerContextAdminMBean.PATTERN;
+ final String search = String.format(pattern, "*");
+ unregisterAllMatching(search, mbs);
+ }
+
private static void unregisterAppenders(final String contextName,
final MBeanServer mbs) {
final String pattern = AppenderAdminMBean.PATTERN;
@@ -281,11 +327,11 @@ public final class Server {
final ObjectName pattern = new ObjectName(search);
final Set<ObjectName> found = mbs.queryNames(pattern, null);
for (final ObjectName objectName : found) {
+ LOGGER.debug("Unregistering MBean {}", objectName);
mbs.unregisterMBean(objectName);
}
} catch (final Exception ex) {
- StatusLogger.getLogger()
- .error("Could not unregister " + search, ex);
+ LOGGER.error("Could not unregister MBeans for " + search, ex);
}
}
@@ -296,12 +342,12 @@ public final class Server {
for (final String name : map.keySet()) {
final LoggerConfig cfg = map.get(name);
final LoggerConfigAdmin mbean = new
LoggerConfigAdmin(ctx.getName(), cfg);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
if (cfg instanceof AsyncLoggerConfig) {
AsyncLoggerConfig async = (AsyncLoggerConfig) cfg;
RingBufferAdmin rbmbean =
async.createRingBufferAdmin(ctx.getName());
- mbs.registerMBean(rbmbean, rbmbean.getObjectName());
+ register(mbs, rbmbean, rbmbean.getObjectName());
}
}
}
@@ -316,11 +362,17 @@ public final class Server {
if (appender instanceof AsyncAppender) {
AsyncAppender async = ((AsyncAppender) appender);
final AsyncAppenderAdmin mbean = new
AsyncAppenderAdmin(ctx.getName(), async);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
} else {
final AppenderAdmin mbean = new AppenderAdmin(ctx.getName(),
appender);
- mbs.registerMBean(mbean, mbean.getObjectName());
+ register(mbs, mbean, mbean.getObjectName());
}
}
}
+
+ private static void register(MBeanServer mbs, Object mbean, ObjectName
objectName)
+ throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
+ LOGGER.debug("Registering MBean {}", objectName);
+ mbs.registerMBean(mbean, objectName);
+ }
}
Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1555481&r1=1555480&r2=1555481&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Sun Jan 5 11:06:48 2014
@@ -21,6 +21,9 @@
</properties>
<body>
<release version="2.0-RC1" date="2013-MM-DD" description="Bug fixes and
enhancements">
+ <action issue="LOG4J2-443" dev="rpopma" type="fix">
+ Fixed issue where log4j2 LoggerContext did not show up in JMX GUI or
JConsole.
+ </action>
<action issue="LOG4J2-485" dev="rpopma" type="fix">
Fixed issue where toString methods that perform logging could deadlock
AsyncAppender.
</action>