本文主要研究一下SkyWalkingAgent
skywalking-6.6.0/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java
public class SkyWalkingAgent { private static final ILog logger = LogManager.getLogger(SkyWalkingAgent.class); /** * Main entrance. Use byte-buddy transform to enhance all classes, which define in plugins. * * @param agentArgs * @param instrumentation * @throws PluginException */ public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException, IOException { final PluginFinder pluginFinder; try { SnifferConfigInitializer.initialize(agentArgs); pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins()); } catch (ConfigNotFoundException ce) { logger.error(ce, "SkyWalking agent could not find config. Shutting down."); return; } catch (AgentPackageNotFoundException ape) { logger.error(ape, "Locate agent.jar failure. Shutting down."); return; } catch (Exception e) { logger.error(e, "SkyWalking agent initialized failure. Shutting down."); return; } final ByteBuddy byteBuddy = new ByteBuddy() .with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS)); AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy) .ignore( nameStartsWith("net.bytebuddy.") .or(nameStartsWith("org.slf4j.")) .or(nameStartsWith("org.groovy.")) .or(nameContains("javassist")) .or(nameContains(".asm.")) .or(nameContains(".reflectasm.")) .or(nameStartsWith("sun.reflect")) .or(allSkyWalkingAgentExcludeToolkit()) .or(ElementMatchers.<TypeDescription>isSynthetic())); JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses(); try { agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses); } catch (Exception e) { logger.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down."); return; } try { agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses); } catch (Exception e) { logger.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down."); return; } agentBuilder .type(pluginFinder.buildMatch()) .transform(new Transformer(pluginFinder)) .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) .with(new Listener()) .installOn(instrumentation); try { ServiceManager.INSTANCE.boot(); } catch (Exception e) { logger.error(e, "Skywalking agent boot failure."); } Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { ServiceManager.INSTANCE.shutdown(); } }, "skywalking service shutdown thread")); } //...... } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializer.java
public class SnifferConfigInitializer { private static final ILog logger = LogManager.getLogger(SnifferConfigInitializer.class); private static String SPECIFIED_CONFIG_PATH = "skywalking_config"; private static String DEFAULT_CONFIG_FILE_NAME = "/config/agent.config"; private static String ENV_KEY_PREFIX = "skywalking."; private static boolean IS_INIT_COMPLETED = false; /** * If the specified agent config path is set, the agent will try to locate the specified agent config. If the * specified agent config path is not set , the agent will try to locate `agent.config`, which should be in the * /config directory of agent package. * <p> * Also try to override the config by system.properties. All the keys in this place should * start with {@link #ENV_KEY_PREFIX}. e.g. in env `skywalking.agent.service_name=yourAppName` to override * `agent.service_name` in config file. * <p> * At the end, `agent.service_name` and `collector.servers` must not be blank. */ public static void initialize(String agentOptions) throws ConfigNotFoundException, AgentPackageNotFoundException { InputStreamReader configFileStream; try { configFileStream = loadConfig(); Properties properties = new Properties(); properties.load(configFileStream); for (String key : properties.stringPropertyNames()) { String value = (String)properties.get(key); //replace the key's value. properties.replace(key,value) in jdk8+ properties.put(key, PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(value, properties)); } ConfigInitializer.initialize(properties, Config.class); } catch (Exception e) { logger.error(e, "Failed to read the config file, skywalking is going to run in default config."); } try { overrideConfigBySystemProp(); } catch (Exception e) { logger.error(e, "Failed to read the system properties."); } if (!StringUtil.isEmpty(agentOptions)) { try { agentOptions = agentOptions.trim(); logger.info("Agent options is {}.", agentOptions); overrideConfigByAgentOptions(agentOptions); } catch (Exception e) { logger.error(e, "Failed to parse the agent options, val is {}.", agentOptions); } } if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) { throw new ExceptionInInitializerError("`agent.service_name` is missing."); } if (StringUtil.isEmpty(Config.Collector.BACKEND_SERVICE)) { throw new ExceptionInInitializerError("`collector.backend_service` is missing."); } if (Config.Plugin.PEER_MAX_LENGTH <= 3) { logger.warn("PEER_MAX_LENGTH configuration:{} error, the default value of 200 will be used.", Config.Plugin.PEER_MAX_LENGTH); Config.Plugin.PEER_MAX_LENGTH = 200; } IS_INIT_COMPLETED = true; } //...... } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java
public class PluginBootstrap { private static final ILog logger = LogManager.getLogger(PluginBootstrap.class); /** * load all plugins. * * @return plugin definition list. */ public List<AbstractClassEnhancePluginDefine> loadPlugins() throws AgentPackageNotFoundException { AgentClassLoader.initDefaultLoader(); PluginResourcesResolver resolver = new PluginResourcesResolver(); List<URL> resources = resolver.getResources(); if (resources == null || resources.size() == 0) { logger.info("no plugin files (skywalking-plugin.def) found, continue to start application."); return new ArrayList<AbstractClassEnhancePluginDefine>(); } for (URL pluginUrl : resources) { try { PluginCfg.INSTANCE.load(pluginUrl.openStream()); } catch (Throwable t) { logger.error(t, "plugin file [{}] init failure.", pluginUrl); } } List<PluginDefine> pluginClassList = PluginCfg.INSTANCE.getPluginClassList(); List<AbstractClassEnhancePluginDefine> plugins = new ArrayList<AbstractClassEnhancePluginDefine>(); for (PluginDefine pluginDefine : pluginClassList) { try { logger.debug("loading plugin class {}.", pluginDefine.getDefineClass()); AbstractClassEnhancePluginDefine plugin = (AbstractClassEnhancePluginDefine)Class.forName(pluginDefine.getDefineClass(), true, AgentClassLoader.getDefault()) .newInstance(); plugins.add(plugin); } catch (Throwable t) { logger.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass()); } } plugins.addAll(DynamicPluginLoader.INSTANCE.load(AgentClassLoader.getDefault())); return plugins; } } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginFinder.java
public class PluginFinder { private final Map<String, LinkedList<AbstractClassEnhancePluginDefine>> nameMatchDefine = new HashMap<String, LinkedList<AbstractClassEnhancePluginDefine>>(); private final List<AbstractClassEnhancePluginDefine> signatureMatchDefine = new ArrayList<AbstractClassEnhancePluginDefine>(); private final List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefine = new ArrayList<AbstractClassEnhancePluginDefine>(); public PluginFinder(List<AbstractClassEnhancePluginDefine> plugins) { for (AbstractClassEnhancePluginDefine plugin : plugins) { ClassMatch match = plugin.enhanceClass(); if (match == null) { continue; } if (match instanceof NameMatch) { NameMatch nameMatch = (NameMatch)match; LinkedList<AbstractClassEnhancePluginDefine> pluginDefines = nameMatchDefine.get(nameMatch.getClassName()); if (pluginDefines == null) { pluginDefines = new LinkedList<AbstractClassEnhancePluginDefine>(); nameMatchDefine.put(nameMatch.getClassName(), pluginDefines); } pluginDefines.add(plugin); } else { signatureMatchDefine.add(plugin); } if (plugin.isBootstrapInstrumentation()) { bootstrapClassMatchDefine.add(plugin); } } } public List<AbstractClassEnhancePluginDefine> find(TypeDescription typeDescription) { List<AbstractClassEnhancePluginDefine> matchedPlugins = new LinkedList<AbstractClassEnhancePluginDefine>(); String typeName = typeDescription.getTypeName(); if (nameMatchDefine.containsKey(typeName)) { matchedPlugins.addAll(nameMatchDefine.get(typeName)); } for (AbstractClassEnhancePluginDefine pluginDefine : signatureMatchDefine) { IndirectMatch match = (IndirectMatch)pluginDefine.enhanceClass(); if (match.isMatch(typeDescription)) { matchedPlugins.add(pluginDefine); } } return matchedPlugins; } public ElementMatcher<? super TypeDescription> buildMatch() { ElementMatcher.Junction judge = new AbstractJunction<NamedElement>() { @Override public boolean matches(NamedElement target) { return nameMatchDefine.containsKey(target.getActualName()); } }; judge = judge.and(not(isInterface())); for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) { ClassMatch match = define.enhanceClass(); if (match instanceof IndirectMatch) { judge = judge.or(((IndirectMatch)match).buildJunction()); } } return new ProtectiveShieldMatcher(judge); } public List<AbstractClassEnhancePluginDefine> getBootstrapClassMatchDefine() { return bootstrapClassMatchDefine; } } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java
private static class Transformer implements AgentBuilder.Transformer { private PluginFinder pluginFinder; Transformer(PluginFinder pluginFinder) { this.pluginFinder = pluginFinder; } @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) { List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription); if (pluginDefines.size() > 0) { DynamicType.Builder<?> newBuilder = builder; EnhanceContext context = new EnhanceContext(); for (AbstractClassEnhancePluginDefine define : pluginDefines) { DynamicType.Builder<?> possibleNewBuilder = define.define(typeDescription, newBuilder, classLoader, context); if (possibleNewBuilder != null) { newBuilder = possibleNewBuilder; } } if (context.isEnhanced()) { logger.debug("Finish the prepare stage for {}.", typeDescription.getName()); } return newBuilder; } logger.debug("Matched class {}, but ignore by finding mechanism.", typeDescription.getTypeName()); return builder; } } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java
private static class Listener implements AgentBuilder.Listener { @Override public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) { } @Override public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) { if (logger.isDebugEnable()) { logger.debug("On Transformation class {}.", typeDescription.getName()); } InstrumentDebuggingClass.INSTANCE.log(dynamicType); } @Override public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded) { } @Override public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) { logger.error("Enhance class " + typeName + " error.", throwable); } @Override public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) { } } 复制代码
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java
public enum ServiceManager { INSTANCE; private static final ILog logger = LogManager.getLogger(ServiceManager.class); private Map<Class, BootService> bootedServices = Collections.emptyMap(); public void boot() { bootedServices = loadAllServices(); prepare(); startup(); onComplete(); } public void shutdown() { for (BootService service : bootedServices.values()) { try { service.shutdown(); } catch (Throwable e) { logger.error(e, "ServiceManager try to shutdown [{}] fail.", service.getClass().getName()); } } } private Map<Class, BootService> loadAllServices() { Map<Class, BootService> bootedServices = new LinkedHashMap<Class, BootService>(); List<BootService> allServices = new LinkedList<BootService>(); load(allServices); Iterator<BootService> serviceIterator = allServices.iterator(); while (serviceIterator.hasNext()) { BootService bootService = serviceIterator.next(); Class<? extends BootService> bootServiceClass = bootService.getClass(); boolean isDefaultImplementor = bootServiceClass.isAnnotationPresent(DefaultImplementor.class); if (isDefaultImplementor) { if (!bootedServices.containsKey(bootServiceClass)) { bootedServices.put(bootServiceClass, bootService); } else { //ignore the default service } } else { OverrideImplementor overrideImplementor = bootServiceClass.getAnnotation(OverrideImplementor.class); if (overrideImplementor == null) { if (!bootedServices.containsKey(bootServiceClass)) { bootedServices.put(bootServiceClass, bootService); } else { throw new ServiceConflictException("Duplicate service define for :" + bootServiceClass); } } else { Class<? extends BootService> targetService = overrideImplementor.value(); if (bootedServices.containsKey(targetService)) { boolean presentDefault = bootedServices.get(targetService).getClass().isAnnotationPresent(DefaultImplementor.class); if (presentDefault) { bootedServices.put(targetService, bootService); } else { throw new ServiceConflictException("Service " + bootServiceClass + " overrides conflict, " + "exist more than one service want to override :" + targetService); } } else { bootedServices.put(targetService, bootService); } } } } return bootedServices; } private void prepare() { for (BootService service : bootedServices.values()) { try { service.prepare(); } catch (Throwable e) { logger.error(e, "ServiceManager try to pre-start [{}] fail.", service.getClass().getName()); } } } private void startup() { for (BootService service : bootedServices.values()) { try { service.boot(); } catch (Throwable e) { logger.error(e, "ServiceManager try to start [{}] fail.", service.getClass().getName()); } } } private void onComplete() { for (BootService service : bootedServices.values()) { try { service.onComplete(); } catch (Throwable e) { logger.error(e, "Service [{}] AfterBoot process fails.", service.getClass().getName()); } } } /** * Find a {@link BootService} implementation, which is already started. * * @param serviceClass class name. * @param <T> {@link BootService} implementation class. * @return {@link BootService} instance */ public <T extends BootService> T findService(Class<T> serviceClass) { return (T)bootedServices.get(serviceClass); } void load(List<BootService> allServices) { Iterator<BootService> iterator = ServiceLoader.load(BootService.class, AgentClassLoader.getDefault()).iterator(); while (iterator.hasNext()) { allServices.add(iterator.next()); } } } 复制代码
SkyWalkingAgent的premain方法首先通过SnifferConfigInitializer.initialize(agentArgs)进行初始化,然后执行new PluginFinder(new PluginBootstrap().loadPlugins()),之后创建AgentBuilder,设置ignore、type、transform、listener然后install;最后执行ServiceManager.INSTANCE.boot()并注册shutdownHook执行ServiceManager.INSTANCE.shutdown()