本源码来自于skywalking-agent 8.9.0版本
本节主要讲解skywalking-agent的配置文件加载流程,该实现在 apm-sniffer模块的apm-agent-core 模块里面。但是入口依然是在 apm-agent 模块的 SkyWalkingAgent 的premain方法里面。

注:本篇文章主要是作为自己看书后的总结,内容有可能会存在一些个人理解上的偏差,如果有网友找出问题欢迎提出,感谢!!!如果我理解上的错误误导了您,在此表示抱歉!!!

文章目录

  • 相关源码
    • org.apache.skywalking.apm.agent.SkyWalkingAgent 类
      • 疑问
    • org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer 类
  • 主要流程
    • 加载配置文件
    • 通过系统变量重新设置相关配置
    • 初始化配置
    • 重新设置日志类型
    • 配置信息的检查及容错
      • 解答

相关源码

org.apache.skywalking.apm.agent.SkyWalkingAgent 类


try {SnifferConfigInitializer.initializeCoreConfig(agentArgs);} catch (Exception e) {// try to resolve a new logger, and use the new logger to write the error log hereLogManager.getLogger(SkyWalkingAgent.class).error(e, "SkyWalking agent initialized failure. Shutting down.");return;} finally {// refresh logger again after initialization finishesLOGGER = LogManager.getLogger(SkyWalkingAgent.class);}

这里 SnifferConfigInitializer.initializeCoreConfig(agentArgs) 就是加载配置的入口。

疑问

这里来个小问题,为什么加载配置的时候再catch的里面打印日志时需要通过 LogManager.getLogger 重新获取日志类型,而不是直接打印日志?这个等文章结尾再讲解

org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer 类

public static void initializeCoreConfig(String agentOptions) {AGENT_SETTINGS = new Properties();try (final InputStreamReader configFileStream = loadConfig()) {AGENT_SETTINGS.load(configFileStream);for (String key : AGENT_SETTINGS.stringPropertyNames()) {String value = (String) AGENT_SETTINGS.get(key);AGENT_SETTINGS.put(key, PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(value, AGENT_SETTINGS));}} 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.");}agentOptions = StringUtil.trim(agentOptions, ',');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);}}initializeConfig(Config.class);// reconfigure logger after config initializationconfigureLogger();LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {throw new ExceptionInInitializerError("`agent.service_name` is missing.");} else {if (StringUtil.isNotEmpty(Config.Agent.NAMESPACE) || StringUtil.isNotEmpty(Config.Agent.CLUSTER)) {Config.Agent.SERVICE_NAME = StringUtil.join(SERVICE_NAME_PART_CONNECTOR,Config.Agent.SERVICE_NAME,Config.Agent.NAMESPACE,Config.Agent.CLUSTER);}}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;}

主要流程

1、加载配置文件
2、通过系统变量重新设置相关配置
3、通过启动参数重新设置相关配置
4、初始化配置
5、重新设置日志类型
6、做一些配置信息的检查及容错

加载配置文件

private static InputStreamReader loadConfig() throws AgentPackageNotFoundException, ConfigNotFoundException {// 获取是否存在 SPECIFIED_CONFIG_PATH 系统变量,这个变量用于设置配置文件路径,
// 如果存在查看这个变量的值是否为空,非空加载该路径下的文件;空的话加载默认路径(/config/agent.config)下的文件
// 所以可能存在有些场景下需要将配置文件放在指定位置,那么可以通过这种方式设置String specifiedConfigPath = System.getProperty(SPECIFIED_CONFIG_PATH);File configFile = StringUtil.isEmpty(specifiedConfigPath) ? new File(AgentPackagePath.getPath(), DEFAULT_CONFIG_FILE_NAME) : new File(specifiedConfigPath);
// 如果存在这个路径,且是该路径下的是文件,那么读取该文件if (configFile.exists() && configFile.isFile()) {try {LOGGER.info("Config file found in {}.", configFile);return new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8);} catch (FileNotFoundException e) {throw new ConfigNotFoundException("Failed to load agent.config", e);}}throw new ConfigNotFoundException("Failed to load agent.config.");}

其中 AgentPackagePath.getPath() 的作用是用于定位出 skywalking-agent.jar包的路径,因为知道了它的路径,那么其他的一些包的路径也就知道了,因为在默认情况下打包后的目录结构是固定的。

通过系统变量重新设置相关配置


private static void overrideConfigBySystemProp() {Properties systemProperties = System.getProperties();for (final Map.Entry<Object, Object> prop : systemProperties.entrySet()) {String key = prop.getKey().toString();if (key.startsWith(ENV_KEY_PREFIX)) {String realKey = key.substring(ENV_KEY_PREFIX.length());AGENT_SETTINGS.put(realKey, prop.getValue());}}}

如果系统中设置了相关的gaent配置,那么就进行替换。

初始化配置


public static void initializeConfig(Class configClass) {if (AGENT_SETTINGS == null) {LOGGER.error("Plugin configs have to be initialized after core config initialization.");return;}try {// 将 Properties 内的值赋值给 Config ,这里 Config 内的属性是以模块+配置的形式设计的,同样 配置文件中也是以模块+配置的形式设计的,不同的是配置文件内的属性都是小写的。只要将大小写相互转化就可以找到相互的映射关系ConfigInitializer.initialize(AGENT_SETTINGS, configClass);} catch (IllegalAccessException e) {LOGGER.error(e,"Failed to set the agent settings {}"+ " to Config={} ",AGENT_SETTINGS, configClass);}}

重新设置日志类型

static void configureLogger() {switch (Config.Logging.RESOLVER) {case JSON:LogManager.setLogResolver(new JsonLogResolver());break;case PATTERN:default:LogManager.setLogResolver(new PatternLogResolver());}}

这里会根据配置中设置的日志格式进行设置

配置信息的检查及容错

// 服务名是必须的,因为这涉及到服务注册
if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {throw new ExceptionInInitializerError("`agent.service_name` is missing.");} else {// 命名空间也是必须的,这也涉及到服务注册if (StringUtil.isNotEmpty(Config.Agent.NAMESPACE) || StringUtil.isNotEmpty(Config.Agent.CLUSTER)) {Config.Agent.SERVICE_NAME = StringUtil.join(SERVICE_NAME_PART_CONNECTOR,Config.Agent.SERVICE_NAME,Config.Agent.NAMESPACE,Config.Agent.CLUSTER);}}// 后端地址也是必须的,这涉及到服务注册和心跳,因为数据上报可以通过kafka,所以数据上报可以不受他的影响if (StringUtil.isEmpty(Config.Collector.BACKEND_SERVICE)) {throw new ExceptionInInitializerError("`collector.backend_service` is missing.");}// 因为peer地址一般都大于3,所以如果设置的太小会强制改为200if (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;}
解答

大家应该看到了,在加载配置的代码里面加载完配置后会重新设置日志类型,这个时候新的日志类型可能和原先刚开始的日志类型不一致,所以需要在最外面重新获取一次日志类型,不然日志类型还是原先skywalking默认的日志类型。

skywalking源码--agent配置加载相关推荐

  1. Mybatis3源码分析(05)-加载Configuration-加载MappedStatement

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis3源码分析(05)-加载Configuration-加载MappedStatement 博客分类: java m ...

  2. springboot集成mybatis源码分析-启动加载mybatis过程(二)

    springboot集成mybatis源码分析-启动加载mybatis过程(二) 1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplicati ...

  3. 【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  4. Spring源码分析4---IOC加载过程补充总结

    原文出自:http://cmsblogs.com IOC 之 获取验证模型 DTD 与 XSD 的区别 DTD(Document Type Definition),即文档类型定义,为 XML 文件的验 ...

  5. Spring源码——bean的加载

    前言 内容主要参考自<Spring源码深度解析>一书,算是读书笔记或是原书的补充.进入正文后可能会引来各种不适,毕竟阅读源码是件极其痛苦的事情. 本文主要涉及书中第五章的部分,依照书中内容 ...

  6. Glide 4.9源码解析-图片加载流程

    本文Glide源码基于4.9,版本下载地址如下:Glide 4.9 前言 由于Glide源码真的很复杂,因此本文只分析和贴出与图片加载流程相关的功能以及代码.另外本文Glide源码基于4.9,与3.x ...

  7. 【转载保存】修改IK分词器源码实现动态加载词典

    链接:http://www.gongstring.com/portal/article/index/id/59.html 当前IKAnalyzer从发布最后一个版本后就一直没有再更新,使用过程中,经常 ...

  8. 从 RequireJs 源码剖析脚本加载原理

    引言 俗话说的好,不喜欢研究原理的程序员不是好的程序员,不喜欢读源码的程序员不是好的 jser.这两天看到了有关前端模块化的问题,才发现 JavaScript 社区为了前端工程化真是煞费苦心.今天研究 ...

  9. 分时图均价线计算公式源码,可以加载到K线图

    一.分时图均价线简介 分时图其实就是1分钟图,但是和1分钟K线图有区别.分时图是以收盘价连成的线,但是1分钟K线图是以开高低收的K线形成的图形.如果把主图切换成收盘价,那么图形和分时图就一样了. 分时 ...

最新文章

  1. Java内存模型(Java Memory Model,JMM)
  2. live555 学习笔记
  3. 压缩,解压文件|*.tar.gz/.tar.bz2 文件
  4. java 怎么向串口发送指令_idea ssm项目java程序使用十六进制rxtx包向串口发送指令的方法...
  5. Shell常用命令总结
  6. 分割法和填补法_“聚合”法与“分割”法
  7. Dubbo to Mesh 云原生架构改造方案解析
  8. android 好看的输入法,Android 手机上最好的输入法是哪种
  9. 温伯格《技术领导之路》——如何弯腰更省力,怎样伸手更合理
  10. C/C++ Bug记录
  11. Atitit.增强系统稳定性----虚拟内存的设置
  12. 三相短路电流计算机算法的原理什么,第三章电力系统三相短路电流及实用计算.ppt...
  13. DS1302的电子万年历_51单片机,年月日、星期、时分秒、农历和温度,带闹钟,全套资料
  14. 为什么精英这样用脑不会累
  15. C# 模拟PrintScreen 和 Alt+PrintScreen截取屏幕图片
  16. 被取代的ERP?EBC正在用业务数字化让管理出效益
  17. Burp Suite测试小程序,设置代理之后手机一直连不上网
  18. HDU5266 LCA 树链剖分LCA 线段树
  19. QSS 自定义QMessageBox
  20. python实现类似于visio_5款替代微软Visio的开源免费软件

热门文章

  1. 爬虫实例之爬取北京地铁站点
  2. 激光雷达稀疏投影图插值
  3. 嵌入式系统----原理与应用技术考点
  4. latex遇到重复的作者有波折号省略问题
  5. linux禁用小企鹅输入法,小企鹅(fcitx)输入法停止开发
  6. 笔记本一开机就跳出来计算机,电脑开机就自动进入BIOS界面,该怎么解决?
  7. cacti安装记录 第四阶段cacti的基本使用(3)setting and thresholds (邮件和阀值报警)
  8. numpy.random.rand(),numpy.random.randn(),numpy.random.normal()函数介绍和示例
  9. 卡通小人的眼睛跟着鼠标动
  10. 温度 数值模拟 matlab,西安交通大学——温度场数值模拟matlab