go语言开发Prometheus Exporter(DM数据库)

news2024/11/15 15:59:00

一、介绍

  • 源码步骤基于dameng_exporter源码讲解,看完本篇文章可以直接进行二次开发。

  • dameng exporter的开源地址:https://github.com/gy297879328/dameng_exporter(可直接对接prometheus+grafana 提供表盘)

  • 开发一个exporter 其实就是写一个 Metric格式的接口页面,等待prometheus访问就可以了。

  • Metric(指标)是用于描述和记录系统、应用程序或服务状态的量化数据。Metric提供了对系统运行状态和性能的可量化度量,帮助监控系统的健康状况、性能表现和行为模式。

1. Metric 的主要特征包括

  1. 名称(Name): 指标的唯一标识符,用于在监控系统中识别和区分不同的指标。
  2. 标签(Labels): 用于附加到指标的键值对元数据,可以提供更详细的上下文信息。标签使得指标能够根据不同维度进行分组和过滤。
  3. 值(Value): 指标的具体数值或测量结果,反映了被度量对象的某种状态、计数或度量。
  4. 时间戳(Timestamp): 记录指标值的时间点或时间范围,用于分析指标变化的趋势和时间相关性。

2. Metric 的分类

Metrics 可以按照不同的维度进行分类,主要包括以下几类:

  1. 计数器(Counter): 计数器用于累计某个事件发生的次数或增量。它通常只能递增,不能减少。例如,HTTP请求数、任务完成数等。
  2. 计量器(Gauge): 计量器表示一个可变的数值,它可以增加或减少。通常用于表示系统状态或资源利用率,如内存使用量、CPU利用率等。
  3. 直方图(Histogram): 直方图用于统计和分析观察值的分布情况。它将观察值按照预定义的桶(Bucket)范围进行分组统计,并记录每个桶中的观察值数量。
  4. 摘要(Summary): 摘要类似于直方图,但是它除了统计桶中的观察值数量外,还会记录观察值的总和、计数和其他分位数(如中位数、95th百分位数等)。
    在这里插入图片描述

二、简化版的Metric

  • 最简易版的Counter类型指标方式,只有这么几行代码。
  • 主要是三个函数也就是三步骤

1) prometheus.NewCounter()声明一个自己的指标
2) prometheus.MustRegister() 将自定义的指标注册到prometheus
3) http.Handle(“/metrics”, promhttp.Handler()) 把prometheus的handler交给接口即可

var (
    requestsTotal = prometheus.NewCounter(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests processed",
        },
    )
)

func main() {
    // 注册指标
    prometheus.MustRegister(requestsTotal)

    // 模拟请求处理
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        requestsTotal.Inc() // 每次请求增加计数器
        fmt.Fprintf(w, "Hello, World!")
    })

    // 启动 HTTP 服务,暴露指标
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(":8080", nil))
}

三、标准版的Metric

1. 目录结构

collector
    //注册类
    collector.go
    db_sessions_collector.go
//启动类
dameng_exporter.go

2. main函数(dameng_exporter.go)

注:这里使用的是自己的Registry,特别重要。并且注册指标方式不同

func main() {

	// 创建一个新的注册器,如果使用系统自带的Registry,会多余出很多默认的go指标
	reg := prometheus.NewRegistry()
    //注册指标,这里的collector是我的项目目录
	collector.RegisterCollectors(reg)
    //设置metric路径
	http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))

}

3. 注册指标(collector.go)

  • 这里为什么声明MetricCollector接口,附录章节写原因
// MetricCollector 接口
type MetricCollector interface {
	Describe(ch chan<- *prometheus.Desc)
	Collect(ch chan<- prometheus.Metric)
}

var (
	collectors  []prometheus.Collector
	registerMux sync.Mutex
)

//注册指标
func RegisterCollectors(reg *prometheus.Registry) {
    //加锁
	registerMux.Lock()
	defer registerMux.Unlock()
    
    //连接DM数据库
    db, err := sql.Open("dm", "dm://SYSDBA:SYSDBA@localhost:5236?autoCommit=true")
    
    //将指标存放到collectors数组中
    collectors = append(collectors, NewDBSessionsCollector(db))
    
    //把collectors数组中指标注册
    for _, collector := range collectors {
		reg.MustRegister(collector)
	}
    
}

4.指标采集器(db_sessions_collector.go)

  • 实现MetricCollector的两个接口 Describe 和 Collect, Describe传的channel,Collect是采集逻辑
  • Collect函数我是直接连接DM数据库执行SQL采集指标
  • NewDBSessionsCollector中的返回值 就是我们的metric指标的格式。四个参数已经在代码中标明了,这里只是声明lable的标签并不赋值
  • Collect函数的prometheus.MustNewConstMetric()函数,这步是给事先定义的标签赋值,需要一一对应才行。
  • Collect函数的prometheus.MustNewConstMetric()函数的prometheus.GaugeValue这个参数指定就是Metric的分类
package collector

import (
	"context"
	"dameng_exporter/config"
	"dameng_exporter/logger"
	"database/sql"
	"github.com/prometheus/client_golang/prometheus"
)

type DBSessionsCollector struct {
	db         *sql.DB
	metricDesc *prometheus.Desc
}

func NewDBSessionsCollector(db *sql.DB) MetricCollector {
	return &DBSessionsCollector{
		db: db,
		metricDesc: prometheus.NewDesc(
			"db_sessions", //key便签值
			"Number of database sessions",//辅助信息
			[]string{"host_name"}, // 添加标签
			nil,
		),
	}
}

func (c *DBSessionsCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- c.metricDesc
}

func (c *DBSessionsCollector) Collect(ch chan<- prometheus.Metric) {
	// ping 一下判断连接是否有问题
	if err := checkDBConnection(c.db); err != nil {
		return
	}
	//设置超时时间的ctx对象
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	var value float64
	err := c.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM v$sessions").Scan(&value)
	if err != nil {
		handleDbQueryError(err)
		return
	}

	logger.Logger.Debugf("DBSessionsCollector: %v", value)
	ch <- prometheus.MustNewConstMetric(c.metricDesc, prometheus.GaugeValue, value, config.GetHostName())
}

四、附录

为什么声明MetricCollector接口?

  • prometheus注册需要reg.MustRegister函数需要传Collector类型
  • Collector有两个接口Describe(chan<- *Desc)以及Collect(chan<- Metric)
  • 因为要传这个所以先定义同接口的MetricCollector类型
  • 写的每一个指标都需要实现这两个接口

在这里插入图片描述

如何连接DM数据库

大概如下,具体的参考DM官网:https://eco.dameng.com/document/dm/zh-cn/app-dev/go_dm.html

// 引用Go标准库sql和dm驱动包,后面的示例不再赘述
import (
"database/sql"
_ "dm"
)
db, err := sql.Open("dm", "dm://SYSDBA:SYSDBA@localhost:5236?autoCommit=true")

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

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

相关文章

智谱OpenDay“大有可玩”:30秒将任意文字生成视频

Sora毫无疑问带来AI大模型的全新玩法&#xff0c;大模型可基于任意文字生成视频&#xff0c;这也是这个“大家庭”若干努力&#xff08;包括Runway的Gen系列、微软的Nuwa、Meta的Emu、谷歌的Phenaki/VideoPoet、CogVideo等&#xff09;的一个全新高度。 7月26日&#xff0c;这…

数据结构(5.3_4)——线索二叉树的概念

普通二叉树找某结点前驱和后继的方法 中序线索二叉树 n个结点的二叉树&#xff0c;有n1个空链域!可用来记录前驱&#xff0c;后继的信息 中序线索二叉树的存储结构 //线索二叉树结点 typedef struct ThreadNode {ElemType data;struct BiTNode* lchild, * rchild;int ltag,…

Git、Gitlab以及分支管理

分布式版本控制系统 一、Git概述 Git是一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更。它由Linus torvalds创建的&#xff0c;最初被设计用于Linux内核的开发。Git 允许开发人员跟踪和管理代码的版本&#xff0c;并且可以在不同的开发人员之间进行协作。 Githu…

【学习笔记】解决Serial Communication Library编译问题

【学习笔记】解决编译 Serial Communication Library 时的 Catkin 依赖问题 Serial Communication Library 是一个用 C 编写的用于连接类似 rs-232 串口的跨平台库。它提供了一个现代的 C 接口&#xff0c;它的工作流程设计在外观和感觉上与 PySerial 相似&#xff0c;但串口速…

操盘手分享:葆奕康平台获上市公司投资3300万,大健康新零售模式!

文丨微三云胡佳东&#xff0c;点击上方“关注”&#xff0c;为你分享市场商业模式电商干货。 - 2024年的项目越来越难做&#xff0c;不是随便开个盘在线上零撸、嘘投、空转&#xff08;无实业&#xff09;&#xff0c;这种没实力、没资本、没实业、没生态的项目90%的都活不过…

linux如何卸载python3.5

卸载&#xff1a; 1、卸载python3.5 sudo apt-get remove python3.5 2、卸载python3.5及其依赖 sudo apt-get remove --auto-remove python3.5 3、清除python3.5 sudo apt-get purge python3.5 或者 sudo apt-get purge --auto-remove python3.5

LeetCode 2844.生成特殊数字的最少操作(哈希表 + 贪心)

给你一个下标从 0 开始的字符串 num &#xff0c;表示一个非负整数。 在一次操作中&#xff0c;您可以选择 num 的任意一位数字并将其删除。请注意&#xff0c;如果你删除 num 中的所有数字&#xff0c;则 num 变为 0。 返回最少需要多少次操作可以使 num 变成特殊数字。 如…

第二证券:台风的后遗症竟然是台股!

今日早盘&#xff0c;中国台湾的台湾加权指数开盘大跌逾4%&#xff0c;台积电跌超6%。此前&#xff0c;因为飓风的原因&#xff0c;台湾股市暂停生意两天。暂停生意前&#xff0c;台湾加权指数收报22871点&#xff0c;上升614点&#xff0c;涨幅高达2.76%。 剖析人士认为&…

opencv - py_calib3d - py_epipolar_geometry 对极几何

文章目录 Epipolar Geometry 对极几何目标基本概念代码练​​习 Epipolar Geometry 对极几何 目标 在本节中&#xff0c; 我们将学习多视图几何的基础知识我们将了解什么是对极点、对极线、对极约束等。 基本概念 当我们使用针孔相机拍摄图像时&#xff0c;我们会丢失一个…

解锁人工智能学习中的数学密钥

一、启航&#xff1a;奠定数学基础 1. 线性代数&#xff1a;AI的入门语言 学习目标&#xff1a;掌握向量、矩阵的基本概念及运算&#xff0c;理解线性空间、线性变换及特征值、特征向量的意义。学习建议&#xff1a;从基础教材入手&#xff0c;如《线性代数及其应用》&#x…

Godot入门 03世界构建1.0版

在game场景&#xff0c;删除StaticBody2D节点&#xff0c;添加TileMap节点 添加TileSet图块集 添加TileSet源 拖动图片到图块&#xff0c;自动创建图块 使用橡皮擦擦除。取消橡皮擦后按住Shift创建大型图块。 进入选择模式&#xff0c;TileMap选择绘制&#xff0c;选中图块后在…

PostgreSQL 数据库 安装

1、官网下载 起源与发展&#xff1a;PostgreSQL最初起源于加州大学伯克利分校的Postgres项目&#xff0c;该项目始于1986年&#xff0c;并一直演进到1994年。在1995年&#xff0c;Postgres项目增加了SQL翻译程序&#xff0c;并更名为Postgres95。随后&#xff0c;在1996年&…

dsp c6657 SYS/BIOS学习笔记

1 SYS/BIOS简介 SYS/BIOS是一种用于TI的DSP平台的嵌入式操作系统&#xff08;RTOS&#xff09;。 2 任务 2.1 任务调度 SYS/BIOS任务线程有0-31个优先级&#xff08;默认0-15&#xff0c;优先级0被空闲线程使用&#xff0c;任务最低优先级为1&#xff0c;最高优先级为15&am…

解决zabbix-server7 中文乱码问题

系统使用centos9 安装中文支持 yum install -y fontconfig langpacks-zh_CN.noarch 检查是否已有中文字体&#xff1a; fc-list :langzh 看到 直接使用GOOGLE的字体 ln -fs /usr/share/fonts/google-noto-cjk/NotoSansCJK-DemiLight.ttc /etc/alternatives/zabbix-web-fo…

Activiti学习之入门个人任务(07)

这里写目录标题 一、分配任务负责人1.1 固定分配1.2 表达式分配1.2.1 UEL表达式1.2.2 使用流程变量分配任务1.2.3 注意事项 1.3 监听器分配 二、查询任务2.1 查询负责人待办2.2 关联businessKey 三、办理任务 一、分配任务负责人 1.1 固定分配 在进行业务流程建模时指定固定的…

上传文件传参 pc端vue的formData

formData let formData new FormData(); formData.append("file", blob, ref ".png"); //添加参数并且重新命名文件名称 if(ref.toString().indexOf(qrcode) > 0) formData.append(noStbg, true)//添加参数 uploadType(formData, sour…

Ruoyi-WMS部署

所需软件 1、JDK&#xff1a;8 安装包&#xff1a;https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmlopen in new window 安装文档&#xff1a;https://cloud.tencent.com/developer/article/1698454open in new window 2、Redis 3.0 安装包&a…

算法日记day 20(中序后序遍历序列构造二叉树|最大、合并、搜索二叉树)

一、中序后序序列构造二叉树 题目&#xff1a; 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,…

Web动画(lottie篇)

一、Lottie简介 Lottie是一个库&#xff0c;可以解析使用AE制作的动画&#xff08;需要用bodymovin导出为json格式&#xff09;&#xff0c;支持web、ios、android和react native。在web侧&#xff0c;lottie-web库可以解析导出的动画json文件&#xff0c;并将其以svg或者canva…

近期代码报错解决笔记

1.TypeError: ‘bool’ object is not callable 想print("Type of head:", type(entity_emb[head]))&#xff0c;结果报如下错误&#xff1a; 源代码&#xff1a; 因为 print 仍然被当作一个布尔值处理&#xff0c;而不是作为函数调用。这个问题的根源在于 print …