Index: src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdmin.java
===================================================================
--- src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdmin.java	(revision 0)
+++ src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdmin.java	(revision 0)
@@ -0,0 +1,137 @@
+package org.apache.logging.log4j.core.jmx;
+
+import java.util.*;
+
+import javax.management.ObjectName;
+
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.*;
+import org.apache.logging.log4j.core.config.*;
+
+
+
+
+/**
+ * Expose log4j2 configuration so can redefine levels
+ * for arbitrary loggers at runtime via jmx.
+ * Requires >log4j2-rc2 
+ * @author Phil Wray
+ */
+public class LoggerLevelAdmin implements LoggerLevelAdminMBean {
+	
+	private static final org.apache.logging.log4j.Logger LOG = LogManager.getLogger(LoggerLevelAdmin.class.getName());
+	private final ObjectName objectName;
+	
+	public LoggerLevelAdmin(){
+		try {
+			final String name = Server.DOMAIN + ":component=Loggers,name=LoggerLevelAdmin";
+			objectName = new ObjectName(name);
+        } catch (final Exception e) {
+            throw new IllegalStateException(e);
+        }
+	}
+	
+	@Override
+	public String changeLoggerLevel(String loggerName, String level){
+		Level newLevel = Level.toLevel(level);
+		LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+		Configuration config = ctx.getConfiguration();
+		LoggerConfig loggerConfig = config.getLoggerConfig(loggerName);
+		String msg;
+		
+		if (loggerName.equals(loggerConfig.getName())){
+			Level oldLevel = loggerConfig.getLevel();
+			loggerConfig.setLevel(newLevel);
+			msg = String.format("Modified existing logger %s level from %s to %s", loggerName, oldLevel, newLevel); 
+		} else {
+			createCopyFrom(loggerConfig, loggerName, newLevel, config);
+			msg = String.format("Added new logger %s with level %s previously used logger %s with level %s", loggerName, newLevel, loggerConfig.getName(), loggerConfig.getLevel());
+		}
+		ctx.updateLoggers();
+		LOG.info(msg);
+		return msg;
+	}
+	
+	@Override
+	public String changeRootLoggerLevel(String level){
+		return changeLoggerLevel(LogManager.ROOT_LOGGER_NAME, level);
+	}
+	
+	private void createCopyFrom(LoggerConfig original, String name, Level level, Configuration config){
+		AppenderRef[] refs = original.getAppenderRefs().toArray(new AppenderRef[]{});
+		Filter filter = original.getFilter();
+		
+		LoggerConfig copy = LoggerConfig.createLogger(
+				"false", 
+				level, 
+				name, 
+				Boolean.toString(original.isIncludeLocation()), 
+				refs, (Property[])null, config, filter);
+		
+		for (Appender appender : original.getAppenders().values()){
+			copy.addAppender(appender, null, null);
+		}
+		config.addLogger(name, copy);
+	}
+	
+
+	
+	@Override
+	public String listLoggers(){
+		StringBuilder builder = new StringBuilder();
+		builder.append("logger,level,additive,appenders");
+		LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+		Configuration config = ctx.getConfiguration();
+		for (Map.Entry<String, LoggerConfig> logger : config.getLoggers().entrySet()){
+			LoggerConfig lconfig = logger.getValue();
+			StringBuilder appenders = new StringBuilder();
+			for (Iterator<String> appenderNames = lconfig.getAppenders().keySet().iterator(); appenderNames.hasNext();){
+					appenders.append(appenderNames.next());
+					if (appenderNames.hasNext()){
+						appenders.append(",");
+					}
+			}
+
+			builder.append(logger.getKey()).append(",")
+			.append(lconfig.getLevel()).append(",")
+			.append(lconfig.isAdditive()).append(",")
+			.append(appenders.toString());
+		}
+		return builder.toString();
+	}
+	
+	
+
+	@Override
+	public String logMessageAtLevel(String message, String level){
+		Level logLevel = Level.toLevel(level);
+		// what is wrong with people - where's the Log.log(Level, String) method in slf4j?
+		if (Level.TRACE == logLevel){
+			LOG.trace(message);
+		} else if (Level.DEBUG == logLevel){
+			LOG.debug(message);
+		} else if (Level.INFO == logLevel){
+			LOG.info(message);
+		} else if (Level.WARN== logLevel){
+			LOG.warn(message);
+		} else if (Level.ERROR == logLevel){
+			LOG.error(message);
+		} else {
+			return "Cannot handle level " + level;
+		}
+		return String.format("Logged %s at %s", message, level);
+	}
+	
+    /**
+     * Returns the {@code ObjectName} of this mbean.
+     *
+     * @return the {@code ObjectName}
+     * @see LoggerConfigAdminMBean#PATTERN
+     */
+    public ObjectName getObjectName() {
+        return objectName;
+    }
+	
+}
Index: src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdminMBean.java
===================================================================
--- src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdminMBean.java	(revision 0)
+++ src/main/java/org/apache/logging/log4j/core/jmx/LoggerLevelAdminMBean.java	(revision 0)
@@ -0,0 +1,14 @@
+package org.apache.logging.log4j.core.jmx;
+
+
+public interface LoggerLevelAdminMBean {
+
+	public abstract String changeLoggerLevel(String loggerName, String level);
+
+	public abstract String changeRootLoggerLevel(String level);
+
+	public abstract String listLoggers();
+
+	public abstract String logMessageAtLevel(String message, String level);
+
+}
\ No newline at end of file
Index: src/main/java/org/apache/logging/log4j/core/jmx/Server.java
===================================================================
--- src/main/java/org/apache/logging/log4j/core/jmx/Server.java	(revision 1617435)
+++ src/main/java/org/apache/logging/log4j/core/jmx/Server.java	(working copy)
@@ -58,6 +58,7 @@
     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 static final LoggerLevelAdmin loggerLevelAdmin = new LoggerLevelAdmin();
 
     private Server() {
     }
@@ -158,6 +159,7 @@
                 registerLoggerConfigs(ctx, mbs, executor);
                 registerAppenders(ctx, mbs, executor);
             }
+            registerLoggerLevelAdmin(mbs);
         } catch (final Exception ex) {
             LOGGER.error("Could not register mbeans", ex);
         }
@@ -185,6 +187,7 @@
         unregisterAsyncLoggerConfigRingBufferAdmins("*", mbs);
         unregisterAppenders("*", mbs);
         unregisterAsyncAppenders("*", mbs);
+        unregisterLoggerLevelAdmin(mbs);
     }
 
     /**
@@ -237,6 +240,15 @@
         unregisterAsyncLoggerRingBufferAdmins(contextName, mbs);
         unregisterAsyncLoggerConfigRingBufferAdmins(contextName, mbs);
     }
+    
+    private static void unregisterLoggerLevelAdmin(final MBeanServer mbs){
+        try {
+            mbs.unregisterMBean(loggerLevelAdmin.getObjectName());
+        } catch (final Exception ex) {
+            LOGGER.error("Could not unregister MBean " + loggerLevelAdmin.getObjectName());
+        }
+    }
+    
 
     private static void registerStatusLogger(final String contextName, final MBeanServer mbs, final Executor executor)
             throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
@@ -348,6 +360,10 @@
             }
         }
     }
+    
+    private static void registerLoggerLevelAdmin(final MBeanServer mbs) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
+        register(mbs, loggerLevelAdmin, loggerLevelAdmin.getObjectName());
+    }
 
     private static void register(final MBeanServer mbs, final Object mbean, final ObjectName objectName)
             throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
