自定义Exporter开发--实现自己应用的监控--国产数据库通用模块开发

概述

Exporter是Prometheus监控系统中一个重要组件,可以理解为收集监控对象各种数据的agent。Prometheus为我们提供了较多的官方及第三方export,如果想要实现用户自己应用的监控,则需自己开发exporter,常用的监控对象大致可分为数据库对象,中间件对象,主机及操作系统,以及用户应用等。其中本文主要介绍了国产数据库gbase-8a的通用模块

(1)添加依赖

首先在国产数据库项目(例如exporter-gbase-8a)下的pom.xml中添加exporter-select-sql的依赖,用于让国产数据库项目与exporter-select-sql的jar包相关联

  <dependency><groupId>com.apusic.amp.exporter</groupId><artifactId>exporter-select-sql</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

(2)注册

在国产数据库项目(例如exporter-gbase-8a)下的application注册文件下(例如Gbase8aExporterApplication)注册selectSqlExporter和gbase8aExporter采集器,注册方式为

@SpringBootApplication
@EnablePrometheusEndpoint
@ComponentScan("com.apusic.amp.exporter")
public class Gbase8aExporterApplication extends WebMvcConfigurerAdapter implements CommandLineRunner {@Autowiredprivate SelectSqlExporter selectSqlExporter;@Autowiredprivate Gbase8aExporter gbase8aExporter;public static void main(String[] args) {SpringApplication.run(Gbase8aExporterApplication.class, args);}@Overridepublic void run(String... args) throws Exception {DefaultExports.initialize();selectSqlExporter.register();gbase8aExporter.register();}
}

(3)根据不同国产数据库的需求配置metrics.yml

找到国产数据库项目下的metrics.yml配置文件(例如exporter-gbase-8a项目下的metrics_select_sql.yml)
因为exporter后的metrics内容格式是由context+name+fieldForValue+help+type+fieldForLabels组成,所以通过metrics_select_sql.yml配置文件依次获取到各项指标的值,然后根据Prometheus所需的格式排列起来,例如

# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0

其中metrics_select_sql.yml的内容

selectmetrics:dbVersion: 8.6                            //gbase_8a的版本为8.6dbName: gbase_8a                          //所采集的数据库名称(第一个拼接值,可以自己设置)metricFamilies:                           //一条sql语句对应的metric集合- context: info_schema                  //标签名(第二个拼接值,可以自己设置)sql: SELECT TABLE_SCHEMA as tableschema,TABLE_NAME as tablename,TABLE_TYPE as type,ifnull(ENGINE, 'NONE') as engine,ifnull(VERSION, '0') as version,ifnull(ROW_FORMAT, 'NONE') as row_format,ifnull(TABLE_ROWS, '0') as TABLE_ROWS,ifnull(DATA_LENGTH, '0') as DATA_LENGTH,ifnull(INDEX_LENGTH, '0') as INDEX_LENGTH,ifnull(DATA_FREE, '0') as DATA_FREE,ifnull(CREATE_OPTIONS, '') as create_options FROM information_schema.tables             //select语句metrics:                              //sql语句查询到的结果集合- name: table_version               //字段名(第三个拼接值,通常为字段名,也可以自己设置容易理解的内容)fieldForValue: version            //字段值(第五个拼接值,所需要的指标的值,固定写法,通常为字段名)help: "The version number of the table's .frm file"   //解释type: gauge                       //指标类型fieldForLabels:                   //标签(第四个拼接值,在{}中,每个标签用逗号隔开,通常设置一些固定的内容,比如名字,id等信息)- tableschema- tablename- type- engine- row_format- create_options

(4)在exporter-select-sql配置项目下的SelectSqlMetricsYmlLoader中读取配置文件

SelectSqlMetricsYmlLoader的内容

@Component
@PropertySource(value = {"${metrics.selectsql.config}"}, factory = SelectSqlMetricsYmlPropertyFactory.class)
public class SelectSqlMetricsYmlLoader {
}

(5)在exporter-select-sql配置项目下的SelectSqlMetricsService

其中SelectSqlMetricsService的步骤分别为
1.首先在metrics第一次初始化的时候,会执行一次监控的国产数据库的版本判定,版本判断通过后执行下一步
2.接下来从metrics集合中获取sql语句所查询到的指标内容,并判断指标是否有固定名称,然后对指标的各项内容进行拼接,拼接成Prometheus所需的格式并用-排列起来,排列方式为context-name-fieldForValue-help-type-fieldForLabels,最后可以添加文件名缓存,如果文件前面的名称相同,可以直接读取缓存的名称。
SelectSqlMetricsService源码如下

@Service
public class SelectSqlMetricsService {@Autowiredprivate SelectSqlMetricYmlProperty dataBaseMetricProperty;@Autowiredprivate SelectSqlMetricsDao dmActivityMetricsDao;private boolean isCheckEnable;static final Gauge inprogressRequests = Gauge.build().name("db_up").help("Whether the database server is up.").register();private static final Logger logger = LoggerFactory.getLogger(SelectSqlMetricsService.class);public void collect(List<Collector.MetricFamilySamples> metricsList) {Double status = dmActivityMetricsDao.status();inprogressRequests.set(status);if (status < 1) {return;}if (!isCheckEnable) {checkMetricFamilyEnable();}for (SelectSqlMetricFamily metricFamily : dataBaseMetricProperty.getMetricFamilies()) {if (!metricFamily.isEnable()) {continue;}List<Map<String, String>> resultMapList = null;try {resultMapList = dmActivityMetricsDao.query(metricFamily.getSql());} catch (Exception e) {logger.error("Get Metrics ResultMap Error! Metrics: " + metricFamily.getContext()  + ", Detail: " + e.getMessage());continue;}if(resultMapList == null || resultMapList.size() == 0) {continue;}//初始化一个map来放 MetricFamilySamplesMap<String, Collector.MetricFamilySamples> metricFamilySamplesMap = new HashMap<>();for (SelectSqlMetric metric : metricFamily.getMetrics()) {for (Map<String, String> resultMap : resultMapList) {//当指标值指定的列的值不能解析成Double时,跳过Double value = null;try {value = Double.parseDouble(resultMap.get(metric.getFieldForValue()));} catch (Exception e) {continue;}//获取labelList<String> labelKeys = new ArrayList<>();List<String> labelValues = new ArrayList<>();if (metric.getFieldForLabels() != null) {for (String label : metric.getFieldForLabels()) {labelKeys.add(label);labelValues.add(resultMap.get(label).trim());}}if (metric.getConstantLabels() != null) {for (Map.Entry<String, String> entry : metric.getConstantLabels().entrySet()) {labelKeys.add(entry.getKey());labelValues.add(entry.getValue());}}//获取nameString metricName = metric.getName() != null ? metric.getName() : "";if (StringUtils.isEmpty(metric.getFieldForName())) {metricName = buildMetricName(dataBaseMetricProperty.getDbName(), metricFamily.getContext(), metricName);} else {metricName = buildMetricName(dataBaseMetricProperty.getDbName(), metricFamily.getContext(), cleanName(resultMap.get(metric.getFieldForName())));}//创建指标MetricFamilyFactory.createMetricFamilyUseingCache(metricFamilySamplesMap, metricName, metric.getHelp(), metric.getType(), labelKeys, labelValues, value);}}metricsList.addAll(metricFamilySamplesMap.values());}}private String buildMetricName(String namespace, String context, String metricName) {if (StringUtils.isEmpty(metricName)) {return "";}if (!StringUtils.isEmpty(namespace) && !StringUtils.isEmpty(context)) {return namespace + "_" + context + "_" + metricName;} else if (!StringUtils.isEmpty(namespace)) {return namespace + "_" + metricName;} else if (!StringUtils.isEmpty(context)) {return context + "_" + metricName;} else {return metricName;}}//清除指标名称中的空格,/private String cleanName(String s) {s = s.trim();s = s.replaceAll(" ", "_");s = s.replaceAll("/", "");return s;}private MetricsType getMetricType(String metricType) {MetricsType type = null;try {type = MetricsType.valueOf(metricType.toUpperCase());} catch (Exception e) {throw new RuntimeException("No metrics found while parsing: " + metricType);}return type;}/*** 根据版本判断指标族是否可用*/private void checkMetricFamilyEnable() {for (SelectSqlMetricFamily metricFamily : dataBaseMetricProperty.getMetricFamilies()) {//未申明任何版本号,默认开启该指标族if (dataBaseMetricProperty.getDbVersion() >= metricFamily.getLowVersion() && (metricFamily.getUpVersion() <= 0 || dataBaseMetricProperty.getDbVersion() <= metricFamily.getUpVersion())) {metricFamily.setEnable(true);} else {metricFamily.setEnable(false);}}isCheckEnable = true;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/680340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ClickHouse--03--数据类型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 数据类型1. Int2.FloattoFloat32(...) 用来将字符串转换成 Float32 类型的函数toFloat64(...) 用来将字符串转换成 Float64 类型的函数 3.DecimaltoDecimal32(value…

Linux常用make命令

一、简介 make 是一个常用的命令行工具&#xff0c;用于自动化构建和管理软件项目。它通常用于编译源代码、生成可执行文件或库&#xff0c;并处理项目中的依赖关系。 make 命令使用一个名为 “Makefile” 的文件来定义构建规则和目标。Makefile 中包含了一系列规则&#xff0…

视觉开发板—K210自学笔记(五)

本期我们来遵循其他单片机的学习路线开始去用板子上的按键控制点亮LED。那么第一步还是先知道K210里面的硬件电路是怎么连接的&#xff0c;需要查看第二节的文档&#xff0c;看看开发板原理图到底是按键是跟哪个IO连在一起。然后再建立输入按键和GPIO的映射就可以开始变成了。 …

Redis中缓存问题

缓存预热 Redis缓存预热是一项关键任务&#xff0c;可帮助提升应用程序的性能和响应速度。在高流量的应用程序中&#xff0c;Redis缓存预热可以加速数据查询和读取&#xff0c;从而改善用户体验。本文将介绍一种快速、稳定的Redis缓存预热方案&#xff0c;并提供相应代码实现。…

Linux第48步_编译正点原子的出厂Linux内核源码

编译正点原子的出厂 Linux 内核源码&#xff0c;为后面移植linux做准备。研究对象如下&#xff1a; 1)、linux内核镜像文件“uImage” 路径为“arch/arm/boot”&#xff1b; 2)、设备树文件“stm32mp157d-atk.dtb” 路径为“arch/arm/boot/dts” 3)、默认配置文件“stm32m…

django中实现数据库操作

在Django中&#xff0c;数据库操作通常通过Django的ORM&#xff08;Object-Relational Mapping&#xff09;来实现。ORM允许你使用Python类来表示数据库表&#xff0c;并可以使用Python语法来查询和操作数据库。 以下是在Django中实现数据库操作的基本步骤&#xff1a; 一&am…

2.11 假期作业

1、若有以下说明语句&#xff1a;int a[12]{1,2,3,4,5,6,7,8,9,10,11,12};char c’a’,d,g;则数值为4的表达式是&#xff08;D&#xff09;。 A&#xff09;a[g-c] B&#xff09;a[4] C&#xff09;a[‘d’-‘c’] D&#xff09;a[‘d’-c] 2、假…

C++入门篇——类与对象重点解析(中篇)

1. 类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 class Date {}; 默认成员函数&#xff1a;用户没有显式实现&a…

WordPress修改所有用户名并发送邮件通知的插件Easy Username Updater

前面跟大家介绍了『如何修改WordPress后台管理员用户名&#xff1f;推荐2种简单方法』一文&#xff0c;但是对于有很多用户的站长来说&#xff0c;操作有点复杂&#xff0c;而且无法发邮件通知对方&#xff0c;所以今天boke112百科向大家推荐一款可以直接在WordPress后台修改所…

Rust语言之哈希表

文章目录 哈希表&#xff08;Hash map)一、新建哈希表二、访问某个元素索引访问GET方法 二、插入新元素三、遍历哈希表四、检查某个元素是否存在contains_key方法entry方法 五、元素更新使用contains_keyinsert 的方法使用entry方法 六、删除元素 Rus设计语言官方教程 哈希表&…

全面详细对比@Resource和@Autowired

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Resource和Autowired概述 在Java的Spring框架中&#xff0c;Resource和Autowired都是用于实现依赖注入&#xff08;Dependency Injection, DI&#xff09;的重要注解。依赖…

洛谷UVA题目Unknown Error

UnexpectedResponseStatus: expect status code: 301 Moved Permanently on https://onlinejudge.org/index.php?optioncom_comprofiler&tasklogin, got: 200 OK 如果你绑定了账号&#xff0c;去原站Online Judge - Home 登录一下&#xff0c;好久没登陆&#xff0c;需要激…

[2-远程开发-01]idea远程连接开发

背景 因为本次的项目使用到一些网络相关的库只在linux可使用&#xff0c;项目本身也会在linux运行&#xff0c;而且如果在mac上进行开发的话&#xff0c;也涉及到部署的问题&#xff0c;而且也不能调试。 所以直接在本专栏第一篇的centos主机上进行开发&#xff0c;以远程连接…

Junit常用断言

0.断言简介 断言:assert Q:断言的作用 更方便的对结果进行判定 "有针对性"的if判断 针对两个变量值是否相同 使用assertEquals针对两个对象是否相同 使用assertSame针对返回值是否为True 使用assertTrue 1.断言的参数 assertXXX(”断言失败时提升的信息“&#x…

MD5 哈希

md5DigestAsHex 是 Spring Framework 中 DigestUtils 类的一个方法&#xff0c;用于计算 MD5 哈希并返回十六进制表示的字符串。这个方法的主要作用是将输入的字节数组进行 MD5 哈希处理&#xff0c;并返回结果的十六进制表示形式。 MD5&#xff08;Message Digest Algorithm …

【开源】SpringBoot框架开发校园疫情防控管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生2.2 老师2.3 学校管理部门 三、系统展示四、核心代码4.1 新增健康情况上报4.2 查询健康咨询4.3 新增离返校申请4.4 查询防疫物资4.5 查询防控宣传数据 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBoot…

C# Thread的使用

在C#中&#xff0c;线程用于实现程序的并发执行。通过创建和管理多个线程&#xff0c;可以同时处理不同的任务或操作&#xff0c;从而提高程序性能和响应性。以下是如何在C#中使用线程的基本步骤&#xff1a; 创建新线程 // 使用System.Threading命名空间 using System.Threa…

【Java程序设计】【C00253】基于Springboot的在线考试管理系统(有论文)

基于Springboot的在线考试管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的在线考试系统 本系统分为系统功能模块、管理员功能模块以及用户功能模块。 系统功能模块&#xff1a;系统登录&#xff0c;管理…

WordPress后台编辑个人资料页面直接修改用户名插件Change Username

前面跟大家介绍了『如何修改WordPress后台管理员用户名&#xff1f;推荐2种简单方法』一文&#xff0c;但是对于新站长或者有很多用户的站长来说&#xff0c;操作有点复杂&#xff0c;所以今天向大家推荐一款可以直接在WordPress后台编辑个人&#xff08;用户&#xff09;资料页…