From 88fe2eae5aab2fce3528354fb13b170cb90ead21 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 4 Apr 2019 17:41:55 +0800 Subject: [PATCH] support rescan plugins. #558 --- .../com/taobao/arthas/agent/ArthasAgent.java | 7 +- .../command/basic1000/PluginsCommand.java | 15 +++- .../alibaba/arthas/plugin/ArthasPlugin.java | 22 ++++-- .../alibaba/arthas/plugin/PluginManager.java | 76 +++++++++++-------- .../alibaba/arthas/plugin/PluginState.java | 2 +- 5 files changed, 79 insertions(+), 43 deletions(-) diff --git a/agent/src/main/java/com/taobao/arthas/agent/ArthasAgent.java b/agent/src/main/java/com/taobao/arthas/agent/ArthasAgent.java index f7f8715a0..839e6e333 100644 --- a/agent/src/main/java/com/taobao/arthas/agent/ArthasAgent.java +++ b/agent/src/main/java/com/taobao/arthas/agent/ArthasAgent.java @@ -9,7 +9,6 @@ import java.util.Properties; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; -import com.alibaba.arthas.plugin.PluginException; import com.alibaba.arthas.plugin.PluginManager; import com.taobao.arthas.common.FeatureCodec; @@ -92,10 +91,10 @@ public class ArthasAgent { properties.putAll(map); logger.debug("PluginManager properties: {}", properties); - pluginManager = new PluginManager(inst, properties); try { + pluginManager = new PluginManager(inst, properties, new File(arthasHome, "plugins").toURI().toURL()); - pluginManager.scanPlugins(new File(arthasHome, "plugins")); + pluginManager.scanPlugins(); pluginManager.enablePlugins(); @@ -103,7 +102,7 @@ public class ArthasAgent { pluginManager.startPlugins(); - } catch (PluginException e) { + } catch (Exception e) { logger.error("PluginManager error", e); e.printStackTrace(); } diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/PluginsCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/PluginsCommand.java index 6c553539a..029e9d688 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/PluginsCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/PluginsCommand.java @@ -30,6 +30,8 @@ public class PluginsCommand extends AnnotatedCommand { private String uninstallPlugin; + private boolean reScanPlugins; + @Option(shortName = "l", longName = "list") @Description("List plugins") public void setListPlugins(boolean listPlugins) { @@ -54,6 +56,12 @@ public class PluginsCommand extends AnnotatedCommand { this.uninstallPlugin = plugin; } + @Option(longName = "rescan") + @Description("Rescan plugin") + public void setReScan(boolean reScanPlugins) { + this.reScanPlugins = reScanPlugins; + } + @Override public void process(CommandProcess process) { int exitCode = 0; @@ -83,7 +91,11 @@ public class PluginsCommand extends AnnotatedCommand { } else { process.write("Can not find plugin " + uninstallPlugin + "\n"); } - } else { + } else if( this.reScanPlugins) { + pluginMaanger.scanPlugins(); + process.write("Rescan plugins success.\n"); + } + else { TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1); table.row(true, label("Order").style(Decoration.bold.bold()), label("Name").style(Decoration.bold.bold()), @@ -96,6 +108,7 @@ public class PluginsCommand extends AnnotatedCommand { process.write(RenderUtil.render(table, process.width())); } } catch (Throwable e) { + process.write("Error: " + e.getMessage() + "\n"); logger.error(null, null, e); } process.end(exitCode); diff --git a/plugin/src/main/java/com/alibaba/arthas/plugin/ArthasPlugin.java b/plugin/src/main/java/com/alibaba/arthas/plugin/ArthasPlugin.java index b55cf3cb6..7d4e80066 100644 --- a/plugin/src/main/java/com/alibaba/arthas/plugin/ArthasPlugin.java +++ b/plugin/src/main/java/com/alibaba/arthas/plugin/ArthasPlugin.java @@ -11,6 +11,8 @@ import java.util.List; import java.util.Properties; import java.util.Set; +import com.alibaba.arthas.deps.org.slf4j.Logger; +import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.common.IOUtils; import com.taobao.arthas.common.properties.PropertiesInjectUtil; @@ -20,6 +22,7 @@ import com.taobao.arthas.common.properties.PropertiesInjectUtil; * */ public class ArthasPlugin implements Plugin { + private static final Logger logger = LoggerFactory.getLogger(PluginManager.class); public static final int DEFAULT_ORDER = 1000; @@ -79,10 +82,15 @@ public class ArthasPlugin implements Plugin { Class activatorClass = classLoader.loadClass(pluginConfig.getPluginActivator()); pluginActivator = (PluginActivator) activatorClass.newInstance(); enabled = pluginActivator.enabled(pluginContext); - if (!enabled) { + if (enabled) { + this.state = PluginState.ENABLED; + } else { this.state = PluginState.DISABLED; + logger.info("plugin {} disabled.", this.pluginConfig.getName()); } - } catch (Exception e) { + + } catch (Throwable e) { + this.state = PluginState.ERROR; throw new PluginException("check enabled plugin error, plugin name: " + pluginConfig.getName(), e); } return enabled; @@ -92,7 +100,8 @@ public class ArthasPlugin implements Plugin { public void init() throws PluginException { try { pluginActivator.init(pluginContext); - } catch (Exception e) { + } catch (Throwable e) { + this.state = PluginState.ERROR; throw new PluginException("init plugin error, plugin name: " + pluginConfig.getName(), e); } } @@ -101,7 +110,8 @@ public class ArthasPlugin implements Plugin { public void start() throws PluginException { try { pluginActivator.start(pluginContext); - } catch (Exception e) { + } catch (Throwable e) { + this.state = PluginState.ERROR; throw new PluginException("start plugin error, plugin name: " + pluginConfig.getName(), e); } } @@ -110,7 +120,8 @@ public class ArthasPlugin implements Plugin { public void stop() throws PluginException { try { pluginActivator.stop(pluginContext); - } catch (Exception e) { + } catch (Throwable e) { + this.state = PluginState.ERROR; throw new PluginException("stop plugin error, plugin name: " + pluginConfig.getName(), e); } } @@ -171,5 +182,4 @@ public class ArthasPlugin implements Plugin { return urls; } - } diff --git a/plugin/src/main/java/com/alibaba/arthas/plugin/PluginManager.java b/plugin/src/main/java/com/alibaba/arthas/plugin/PluginManager.java index 941cf4b84..c663f43c7 100644 --- a/plugin/src/main/java/com/alibaba/arthas/plugin/PluginManager.java +++ b/plugin/src/main/java/com/alibaba/arthas/plugin/PluginManager.java @@ -2,6 +2,7 @@ package com.alibaba.arthas.plugin; import java.io.File; import java.lang.instrument.Instrumentation; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -17,6 +18,8 @@ import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; * */ public class PluginManager { + private static final Logger logger = LoggerFactory.getLogger(PluginManager.class); + private ClassLoader parentClassLoader = PluginManager.class.getClassLoader(); private List plugins = new ArrayList(); @@ -24,33 +27,37 @@ public class PluginManager { private Properties properties; - private static final Logger logger = LoggerFactory.getLogger(PluginManager.class); + private List scanPluginlLoacations = new ArrayList(); - public PluginManager(Instrumentation instrumentation, Properties properties) { + public PluginManager(Instrumentation instrumentation, Properties properties, URL scanPluginLocation) { this.instrumentation = instrumentation; this.properties = properties; + this.scanPluginlLoacations.add(scanPluginLocation); } // 可能会执行多次 - synchronized public void scanPlugins(File dir) throws PluginException { - try { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - if (!file.isHidden() && file.isDirectory()) { - ArthasPlugin plugin = new ArthasPlugin(file.toURI().toURL(), instrumentation, parentClassLoader, properties); - if (!containsPlugin(plugin.name())) { - plugins.add(plugin); + synchronized public void scanPlugins() throws PluginException { + for (URL scanLocation : scanPluginlLoacations) { + File dir = new File(scanLocation.getFile()); + try { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (!file.isHidden() && file.isDirectory()) { + ArthasPlugin plugin = new ArthasPlugin(file.toURI().toURL(), instrumentation, + parentClassLoader, properties); + if (!containsPlugin(plugin.name())) { + plugins.add(plugin); + } } } } + } catch (Exception e) { + throw new PluginException("scan plugins error.", e); } - } catch (Exception e) { - throw new PluginException("scan plugins error.", e); } Collections.sort(plugins, new PluginComparator()); - } synchronized public boolean containsPlugin(String name) { @@ -73,19 +80,25 @@ public class PluginManager { public void startPlugin(String name) throws PluginException { Plugin plugin = findPlugin(name); - if (plugin != null && (plugin.state() == PluginState.NONE || plugin.state() == PluginState.STOPED)) { - updateState(plugin, PluginState.INITING); - logger.info("Init plugin, name: {}", plugin.name()); - plugin.init(); - logger.info("Init plugin success, name: {}", plugin.name()); - updateState(plugin, PluginState.INITED); - } - if (plugin != null && plugin.state() == PluginState.INITED) { - updateState(plugin, PluginState.STARTING); - logger.info("Start plugin, name: {}", plugin.name()); - plugin.start(); - logger.info("Start plugin success, name: {}", plugin.name()); - updateState(plugin, PluginState.STARTED); + if (plugin != null) { + if (plugin.state() == PluginState.NONE || plugin.state() == PluginState.STOPED) { + plugin.enabled(); + } + if (plugin.state() == PluginState.ENABLED) { + updateState(plugin, PluginState.INITING); + logger.info("Init plugin, name: {}", plugin.name()); + plugin.init(); + logger.info("Init plugin success, name: {}", plugin.name()); + updateState(plugin, PluginState.INITED); + } + + if (plugin.state() == PluginState.INITED) { + updateState(plugin, PluginState.STARTING); + logger.info("Start plugin, name: {}", plugin.name()); + plugin.start(); + logger.info("Start plugin success, name: {}", plugin.name()); + updateState(plugin, PluginState.STARTED); + } } } @@ -112,8 +125,9 @@ public class PluginManager { public void enablePlugin(String name) { Plugin plugin = findPlugin(name); - if (plugin != null && plugin.state() == PluginState.DISABLED) { - updateState(plugin, PluginState.NONE); + if (plugin != null && (plugin.state() == PluginState.DISABLED || plugin.state() == PluginState.NONE + || plugin.state() == PluginState.STOPED)) { + updateState(plugin, PluginState.ENABLED); } } @@ -125,7 +139,7 @@ public class PluginManager { synchronized public List allPlugins() { ArrayList result = new ArrayList(plugins.size()); - Collections.copy(result, plugins); + result.addAll(plugins); return result; } @@ -142,7 +156,7 @@ public class PluginManager { synchronized public void initPlugins() throws PluginException { logger.info("Init available plugins"); for (Plugin plugin : plugins) { - if (plugin.state() == PluginState.NONE) { + if (plugin.state() == PluginState.ENABLED) { updateState(plugin, PluginState.INITING); logger.info("Init plugin, name: {}", plugin.name()); plugin.init(); diff --git a/plugin/src/main/java/com/alibaba/arthas/plugin/PluginState.java b/plugin/src/main/java/com/alibaba/arthas/plugin/PluginState.java index edc99c387..17c430537 100644 --- a/plugin/src/main/java/com/alibaba/arthas/plugin/PluginState.java +++ b/plugin/src/main/java/com/alibaba/arthas/plugin/PluginState.java @@ -8,6 +8,6 @@ package com.alibaba.arthas.plugin; */ public enum PluginState { - NONE, DISABLED, INITING, INITED, STARTING, STARTED, STOPPING, STOPED + NONE, ENABLED, DISABLED, INITING, INITED, STARTING, STARTED, STOPPING, STOPED, ERROR }