diff --git a/core/pom.xml b/core/pom.xml
index 00dd043f0..6c1b497ee 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -120,6 +120,15 @@
log4j
log4j
1.2.17
+ provided
+ true
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.12.1
+ provided
+ true
com.alibaba
diff --git a/core/src/main/java/com/taobao/arthas/core/command/logger/Log4j2Helper.java b/core/src/main/java/com/taobao/arthas/core/command/logger/Log4j2Helper.java
new file mode 100644
index 000000000..b089daeff
--- /dev/null
+++ b/core/src/main/java/com/taobao/arthas/core/command/logger/Log4j2Helper.java
@@ -0,0 +1,187 @@
+package com.taobao.arthas.core.command.logger;
+
+import java.lang.reflect.Field;
+import java.security.CodeSource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.logging.log4j.Level;
+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;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.appender.FileAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+
+/**
+ *
+ * @author hengyunabc 2019-09-20
+ *
+ */
+public class Log4j2Helper {
+ private static boolean Log4j2 = false;
+ private static Field configField = null;
+
+ static {
+ try {
+ Class> loggerClass = Class.forName("org.apache.logging.log4j.Logger");
+ // 这里可能会加载到其它上游ClassLoader的log4j2,因此需要判断是否当前classloader
+ if (loggerClass.getClassLoader().equals(Log4j2Helper.class.getClassLoader())) {
+ Log4j2 = true;
+ }
+
+ try {
+ configField = LoggerConfig.class.getDeclaredField("config");
+ configField.setAccessible(true);
+ } catch (Throwable e) {
+ // ignore
+ }
+ } catch (Throwable t) {
+ }
+ }
+
+ public static boolean hasLength(String str) {
+ return (str != null && !str.isEmpty());
+ }
+
+ private static LoggerConfig getLoggerConfig(String name) {
+ if (!hasLength(name) || LoggerConfig.ROOT.equalsIgnoreCase(name)) {
+ name = LogManager.ROOT_LOGGER_NAME;
+ }
+ return getLoggerContext().getConfiguration().getLoggers().get(name);
+ }
+
+ private static LoggerContext getLoggerContext() {
+ return (LoggerContext) LogManager.getContext(false);
+ }
+
+ public static Boolean updateLevel(String loggerName, String logLevel) {
+ if (Log4j2) {
+ Level level = Level.getLevel(logLevel.toUpperCase());
+ if (level == null) {
+ return null;
+ }
+ LoggerConfig loggerConfig = getLoggerConfig(loggerName);
+ if (loggerConfig == null) {
+ loggerConfig = new LoggerConfig(loggerName, level, true);
+ getLoggerContext().getConfiguration().addLogger(loggerName, loggerConfig);
+ } else {
+ loggerConfig.setLevel(level);
+ }
+ getLoggerContext().updateLoggers();
+ return Boolean.TRUE;
+ }
+ return null;
+ }
+
+ public static Map> getLoggers(String name, boolean includeNoAppender) {
+ Map> loggerInfoMap = new HashMap>();
+ if (!Log4j2) {
+ return loggerInfoMap;
+ }
+
+ Configuration configuration = getLoggerContext().getConfiguration();
+
+ if (name != null && !name.trim().isEmpty()) {
+ LoggerConfig loggerConfig = configuration.getLoggerConfig(name);
+ if (loggerConfig == null) {
+ return loggerInfoMap;
+ }
+ loggerInfoMap.put(name, doGetLoggerInfo(loggerConfig));
+ } else {
+ // 获取所有logger时,如果没有appender则忽略
+ Map loggers = configuration.getLoggers();
+ if (loggers != null) {
+ for (Entry entry : loggers.entrySet()) {
+ LoggerConfig loggerConfig = entry.getValue();
+ if (!includeNoAppender) {
+ if (!loggerConfig.getAppenders().isEmpty()) {
+ loggerInfoMap.put(entry.getKey(), doGetLoggerInfo(entry.getValue()));
+ }
+ } else {
+ loggerInfoMap.put(entry.getKey(), doGetLoggerInfo(entry.getValue()));
+ }
+ }
+ }
+ }
+
+ return loggerInfoMap;
+ }
+
+ private static Object getConfigField(LoggerConfig loggerConfig) {
+ try {
+ if(configField != null) {
+ return configField.get(loggerConfig);
+ }
+ } catch (Throwable e) {
+ // ignore
+ }
+ return null;
+ }
+
+ private static Map doGetLoggerInfo(LoggerConfig loggerConfig) {
+ Map info = new HashMap();
+
+ String name = loggerConfig.getName();
+ if (name == null || name.trim().isEmpty()) {
+ name = LoggerConfig.ROOT;
+ }
+
+ info.put(LoggerHelper.name, name);
+ info.put(LoggerHelper.clazz, loggerConfig.getClass());
+ CodeSource codeSource = loggerConfig.getClass().getProtectionDomain().getCodeSource();
+ if (codeSource != null) {
+ info.put(LoggerHelper.codeSource, codeSource.getLocation());
+ }
+ Object config = getConfigField(loggerConfig);
+ if (config != null) {
+ info.put(LoggerHelper.config, config);
+ }
+
+ info.put(LoggerHelper.additivity, loggerConfig.isAdditive());
+
+ Level level = loggerConfig.getLevel();
+ if (level != null) {
+ info.put(LoggerHelper.level, level.toString());
+ }
+
+ List