skywalking源码--agent配置加载
本源码来自于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配置加载相关推荐
- Mybatis3源码分析(05)-加载Configuration-加载MappedStatement
2019独角兽企业重金招聘Python工程师标准>>> Mybatis3源码分析(05)-加载Configuration-加载MappedStatement 博客分类: java m ...
- springboot集成mybatis源码分析-启动加载mybatis过程(二)
springboot集成mybatis源码分析-启动加载mybatis过程(二) 1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplicati ...
- 【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- Spring源码分析4---IOC加载过程补充总结
原文出自:http://cmsblogs.com IOC 之 获取验证模型 DTD 与 XSD 的区别 DTD(Document Type Definition),即文档类型定义,为 XML 文件的验 ...
- Spring源码——bean的加载
前言 内容主要参考自<Spring源码深度解析>一书,算是读书笔记或是原书的补充.进入正文后可能会引来各种不适,毕竟阅读源码是件极其痛苦的事情. 本文主要涉及书中第五章的部分,依照书中内容 ...
- Glide 4.9源码解析-图片加载流程
本文Glide源码基于4.9,版本下载地址如下:Glide 4.9 前言 由于Glide源码真的很复杂,因此本文只分析和贴出与图片加载流程相关的功能以及代码.另外本文Glide源码基于4.9,与3.x ...
- 【转载保存】修改IK分词器源码实现动态加载词典
链接:http://www.gongstring.com/portal/article/index/id/59.html 当前IKAnalyzer从发布最后一个版本后就一直没有再更新,使用过程中,经常 ...
- 从 RequireJs 源码剖析脚本加载原理
引言 俗话说的好,不喜欢研究原理的程序员不是好的程序员,不喜欢读源码的程序员不是好的 jser.这两天看到了有关前端模块化的问题,才发现 JavaScript 社区为了前端工程化真是煞费苦心.今天研究 ...
- 分时图均价线计算公式源码,可以加载到K线图
一.分时图均价线简介 分时图其实就是1分钟图,但是和1分钟K线图有区别.分时图是以收盘价连成的线,但是1分钟K线图是以开高低收的K线形成的图形.如果把主图切换成收盘价,那么图形和分时图就一样了. 分时 ...
最新文章
- Java内存模型(Java Memory Model,JMM)
- live555 学习笔记
- 压缩,解压文件|*.tar.gz/.tar.bz2 文件
- java 怎么向串口发送指令_idea ssm项目java程序使用十六进制rxtx包向串口发送指令的方法...
- Shell常用命令总结
- 分割法和填补法_“聚合”法与“分割”法
- Dubbo to Mesh 云原生架构改造方案解析
- android 好看的输入法,Android 手机上最好的输入法是哪种
- 温伯格《技术领导之路》——如何弯腰更省力,怎样伸手更合理
- C/C++ Bug记录
- Atitit.增强系统稳定性----虚拟内存的设置
- 三相短路电流计算机算法的原理什么,第三章电力系统三相短路电流及实用计算.ppt...
- DS1302的电子万年历_51单片机,年月日、星期、时分秒、农历和温度,带闹钟,全套资料
- 为什么精英这样用脑不会累
- C# 模拟PrintScreen 和 Alt+PrintScreen截取屏幕图片
- 被取代的ERP?EBC正在用业务数字化让管理出效益
- Burp Suite测试小程序,设置代理之后手机一直连不上网
- HDU5266 LCA 树链剖分LCA 线段树
- QSS 自定义QMessageBox
- python实现类似于visio_5款替代微软Visio的开源免费软件
热门文章
- 爬虫实例之爬取北京地铁站点
- 激光雷达稀疏投影图插值
- 嵌入式系统----原理与应用技术考点
- latex遇到重复的作者有波折号省略问题
- linux禁用小企鹅输入法,小企鹅(fcitx)输入法停止开发
- 笔记本一开机就跳出来计算机,电脑开机就自动进入BIOS界面,该怎么解决?
- cacti安装记录 第四阶段cacti的基本使用(3)setting and thresholds (邮件和阀值报警)
- numpy.random.rand(),numpy.random.randn(),numpy.random.normal()函数介绍和示例
- 卡通小人的眼睛跟着鼠标动
- 温度 数值模拟 matlab,西安交通大学——温度场数值模拟matlab