From 3da99d5ba5081bcc743bbca2077bb1da3135a4d5 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Fri, 14 Feb 2020 03:34:17 +0800 Subject: [PATCH] support arthas.properties. #986 --- .../arthas/core/config/BinderUtils.java | 9 +- .../taobao/arthas/core/config/TestConfig.java | 9 -- .../arthas/core/server/ArthasBootstrap.java | 119 ++++++++++++++---- .../taobao/arthas/core/util/FileUtils.java | 14 +++ 4 files changed, 115 insertions(+), 36 deletions(-) delete mode 100644 core/src/main/java/com/taobao/arthas/core/config/TestConfig.java diff --git a/core/src/main/java/com/taobao/arthas/core/config/BinderUtils.java b/core/src/main/java/com/taobao/arthas/core/config/BinderUtils.java index fe52eb441..8af4e2cd5 100644 --- a/core/src/main/java/com/taobao/arthas/core/config/BinderUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/config/BinderUtils.java @@ -51,9 +51,12 @@ public class BinderUtils { && methodName.length() > "set".length()) { String field = getFieldNameFromSetterMethod(methodName); - Object reslovedValue = environment.getProperty(prefix + '.' + field, parameterTypes[0]); - if (reslovedValue != null) { - method.invoke(instance, new Object[] { reslovedValue }); + String configKey = prefix + '.' + field; + if (environment.containsProperty(configKey)) { + Object reslovedValue = environment.getProperty(prefix + '.' + field, parameterTypes[0]); + if (reslovedValue != null) { + method.invoke(instance, new Object[] { reslovedValue }); + } } } } diff --git a/core/src/main/java/com/taobao/arthas/core/config/TestConfig.java b/core/src/main/java/com/taobao/arthas/core/config/TestConfig.java deleted file mode 100644 index 2145f47ca..000000000 --- a/core/src/main/java/com/taobao/arthas/core/config/TestConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.taobao.arthas.core.config; - - -@Config -public class TestConfig { - - @NestedConfig - SecondConfig secondConfig; -} diff --git a/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java b/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java index b19fa7084..3bf10784d 100644 --- a/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java +++ b/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java @@ -1,13 +1,35 @@ package com.taobao.arthas.core.server; -import com.taobao.arthas.core.config.Configure; -import com.taobao.arthas.core.config.FeatureCodec; -import com.taobao.arthas.core.env.ArthasEnvironment; -import com.taobao.arthas.core.env.MapPropertySource; +import java.arthas.Spy; +import java.io.File; +import java.io.IOException; +import java.lang.instrument.Instrumentation; +import java.lang.reflect.Method; +import java.net.URI; +import java.security.CodeSource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import com.alibaba.arthas.tunnel.client.TunnelClient; import com.taobao.arthas.common.PidUtils; import com.taobao.arthas.core.advisor.AdviceWeaver; import com.taobao.arthas.core.command.BuiltinCommandPack; +import com.taobao.arthas.core.config.BinderUtils; +import com.taobao.arthas.core.config.Configure; +import com.taobao.arthas.core.config.FeatureCodec; +import com.taobao.arthas.core.env.ArthasEnvironment; +import com.taobao.arthas.core.env.MapPropertySource; +import com.taobao.arthas.core.env.PropertiesPropertySource; +import com.taobao.arthas.core.env.PropertySource; import com.taobao.arthas.core.shell.ShellServer; import com.taobao.arthas.core.shell.ShellServerOptions; import com.taobao.arthas.core.shell.command.CommandResolver; @@ -17,35 +39,23 @@ import com.taobao.arthas.core.shell.term.impl.HttpTermServer; import com.taobao.arthas.core.shell.term.impl.httptelnet.HttpTelnetTermServer; import com.taobao.arthas.core.util.ArthasBanner; import com.taobao.arthas.core.util.Constants; +import com.taobao.arthas.core.util.FileUtils; import com.taobao.arthas.core.util.LogUtil; import com.taobao.arthas.core.util.UserStatUtil; import com.taobao.middleware.logger.Logger; import io.netty.channel.ChannelFuture; -import java.arthas.Spy; -import java.io.File; -import java.io.IOException; -import java.lang.instrument.Instrumentation; -import java.lang.reflect.Method; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - /** * @author vlinux on 15/5/2. */ public class ArthasBootstrap { + public static final String CONFIG_NAME_PROPERTY = "arthas.config.name"; + public static final String CONFIG_LOCATION_PROPERTY = "arthas.config.location"; + public static final String CONFIG_OVERRIDE_ALL= "arthas.config.overrideAll"; + private static Logger logger = LogUtil.getArthasLogger(); private static ArthasBootstrap arthasBootstrap; @@ -102,23 +112,84 @@ public class ArthasBootstrap { public void bind(String args) throws Throwable { initSpy(); - if( arthasEnvironment == null) { + if (arthasEnvironment == null) { arthasEnvironment = new ArthasEnvironment(); } - Configure configure = Configure.toConfigure(args); + + /** + *
+         * 脚本里传过来的配置项,即命令行参数 > System Env > System Properties > arthas.properties
+         * arthas.properties 指供一个配置项,可以反转优先级。 arthas.config.overrideAll=true
+         * https://github.com/alibaba/arthas/issues/986
+         * 
+ */ Map argsMap = FeatureCodec.DEFAULT_COMMANDLINE_CODEC.toMap(args); // 给配置全加上前缀 Map mapWithPrefix = new HashMap(argsMap.size()); - for(Entry entry : argsMap.entrySet()) { + for (Entry entry : argsMap.entrySet()) { mapWithPrefix.put("arthas." + entry.getKey(), entry.getValue()); } MapPropertySource mapPropertySource = new MapPropertySource("args", mapWithPrefix); arthasEnvironment.addFirst(mapPropertySource); + tryToLoadArthasProperties(); + + Configure configure = new Configure(); + BinderUtils.inject(arthasEnvironment, configure); + bind(configure); } + // try to load arthas.properties + private void tryToLoadArthasProperties() throws IOException { + this.arthasEnvironment.resolvePlaceholders(CONFIG_LOCATION_PROPERTY); + + String location = null; + + if (arthasEnvironment.containsProperty(CONFIG_LOCATION_PROPERTY)) { + location = arthasEnvironment.resolvePlaceholders(CONFIG_LOCATION_PROPERTY); + } + + if (location == null) { + CodeSource codeSource = ArthasBootstrap.class.getProtectionDomain().getCodeSource(); + if (codeSource != null) { + try { + location = new File(codeSource.getLocation().toURI().getSchemeSpecificPart()).getAbsolutePath(); + } catch (Throwable e) { + logger.error("arthas", "can not find libasyncProfiler so", e); + } + } + } + + String configName = "arthas"; + if (arthasEnvironment.containsProperty(CONFIG_NAME_PROPERTY)) { + configName = arthasEnvironment.resolvePlaceholders(CONFIG_NAME_PROPERTY); + } + + if (location != null) { + if (!location.endsWith(".properties")) { + location = new File(location, configName + ".properties").getAbsolutePath(); + } + } + + if (new File(location).exists()) { + Properties properties = FileUtils.readProperties(location); + + boolean overrideAll = false; + if (arthasEnvironment.containsProperty(CONFIG_OVERRIDE_ALL)) { + overrideAll = arthasEnvironment.getRequiredProperty(CONFIG_OVERRIDE_ALL, boolean.class); + } + + PropertySource propertySource = new PropertiesPropertySource(location, properties); + if (overrideAll) { + arthasEnvironment.addFirst(propertySource); + } else { + arthasEnvironment.addLast(propertySource); + } + } + } + /** * Bootstrap arthas server * diff --git a/core/src/main/java/com/taobao/arthas/core/util/FileUtils.java b/core/src/main/java/com/taobao/arthas/core/util/FileUtils.java index 99cfcea38..973acc23e 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/FileUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/FileUtils.java @@ -10,6 +10,7 @@ import java.io.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import java.util.Properties; public class FileUtils { @@ -163,5 +164,18 @@ public class FileUtils { } } + public static Properties readProperties(String file) throws IOException { + Properties properties = new Properties(); + + FileInputStream in = null; + try { + in = new FileInputStream(file); + properties.load(in); + return properties; + } finally { + com.taobao.arthas.common.IOUtils.close(in); + } + + } }