【Go】基于telegraf进行自定义插件开发(二)

news2024/9/25 18:32:00

基于telegraf进行自定义插件开发(二)

  • 前言
  • 正文
    • 设计
    • 开发过程
      • 单个服务的处理
      • 结构体同时定义了string和数值类型
      • 适配本机服务或者多个ip来源
    • 程序打包
  • 结语

前言

书接上会,这次记录一下我基于telegraf进行的hdfs监控组件的开发工作,这其中也包括了开发完成后如何进行打包等事项。

我的应用场景是,依赖于telegraf去监控大数据组件,所以第一个开发的就是hdfs的采集插件。

正文

设计

开始写代码前,大概规划一下整体的目录,我的想法是,除去README.mdsample.conf文件以外,将Namenode、JournalNode、DataNode组件的个性指标获取方法分开存放,然后把指标的清单放在单独的文件中:
在这里插入图片描述
metrics.go中定义了全部的指标:
在这里插入图片描述

接下来是input的配置块部分,原先我考虑把组件拆分开来,后来觉得那样要整好几个目录,太麻烦,而且从设计的概念上来说,我希望在所有有服务的节点上都部署telegraf,所以每一个telegraf只需要负责自己本机的服务的指标采集,最终定义这样的HDFS结构体:

type HDFS struct {
	Scheme          string          `toml:"scheme"`
	ResponseTimeout config.Duration `toml:"response_timeout"`
	NameNode        *NameNode       `toml:"namenode"`
	JournalNode     *JournalNode    `toml:"journalnode"`
	DataNode        *DataNode       `toml:"datanode"`
	// tls option
	tls.ClientConfig

	// http client
	client *http.Client
	Log    telegraf.Logger
}

type NameNode struct {
	Servers  []string `toml:"servers"`
	HttpPort int      `toml:"http_port"`
	RpcPort  int      `toml:"rpc_port"`
}

三种角色的结构体和NameNode一致,只需要提供服务器清单、http端口和rpc端口即可。

开发过程

单个服务的处理

以Namenode指标数据的获取为例,其实就是通过jmx获取json数据,然后进行解析,以RPC指标为例,结构体细节如下:

type RpcMetrics struct {
	ReceivedBytes              float32 `json:"ReceivedBytes"`
	SentBytes                  float32 `json:"SentBytes"`
	RpcQueueTimeNumOps         float32 `json:"RpcQueueTimeNumOps"`
	RpcQueueTimeAvgTime        float32 `json:"RpcQueueTimeAvgTime"`
	RpcProcessingTimeNumOps    float32 `json:"RpcProcessingTimeNumOps"`
	RpcProcessingTimeAvgTime   float32 `json:"RpcProcessingTimeAvgTime"`
	RpcAuthenticationFailures  float32 `json:"RpcAuthenticationFailures"`
	RpcAuthenticationSuccesses float32 `json:"RpcAuthenticationSuccesses"`
	RpcAuthorizationFailures   float32 `json:"RpcAuthorizationFailures"`
	RpcAuthorizationSuccesses  float32 `json:"RpcAuthorizationSuccesses"`
	NumActiveRpcHandler        float32 `json:"NumActiveRpcHandler"`
	RpcClientBackoff           float32 `json:"RpcClientBackoff"`
	RpcSlowCalls               float32 `json:"RpcSlowCalls"`
	NumOpenConnections         float32 `json:"NumOpenConnections"`
	CallQueueLength            float32 `json:"CallQueueLength"`
	NumDroppedConnections      float32 `json:"NumDroppedConnections"`
}

每一块的指标数据都用单独的方法进行处理,这样方便进行代码的划分,处理rpc指标的方法在这里就是gatherRpcMetrics

func (h *HDFS) gatherRpcMetrics(data map[string]interface{}, role string, acc telegraf.Accumulator, tags map[string]string, rpcMetrics *RpcMetrics) error {
	if err := bindToStruct(rpcMetrics, data); err != nil {
		return err
	}
	rpcFields, err := convertor.StructToMap(*rpcMetrics)
	if err != nil {
		return err
	}
	acc.AddGauge(fmt.Sprintf("hdfs_%s_rpc", role), rpcFields, tags)
	return nil
}

传入的data数据就是指标数据,是个map,role变量是为了方法能够复用,hdfs的journanodedatanodenamenode都有rpc指标,在进行获取的时候打上role,acc和tags不用多说,是为了生成指标用的,rpcMetrics就是我们生成的一个空的结构体,rpc的指标比较特殊,全都是浮点型,所以可以借助lancet库的StructToMap方法直接把指标结构转成map,这样就省去了写field结构体的功夫了;

最后通过AddGauge方法把直接增加上,就完成了一个指标的获取、处理、注册了。

结构体同时定义了string和数值类型

在进行指标获取的过程中,遇到了一个问题,那就是指标结构体中既有string类型又有float32类型,因为我在把结构体转成map的时候,统一使用的StructToMap这个方法,虽然这个方法能够自动的也把string转化,但是这在telegraf的指标注册是会有问题,如下:

	threadingField := map[string]interface{}{
		"CurrentThreadCpuTime":    "123123",
		"CurrentThreadUserTime":   1
	}
	acc.AddGauge(fmt.Sprintf("hdfs_test_threading", role), threadingField, tags)

上面的这个指标,注册后会产生一个hdfs_test_threading{"CurrentThreadCpuTime"="123123"} 1的指标,字符串数据会被自动打成label,有这种特征的指标在进行结构体设计的时候要这样做:

	FSNamesystem struct {
		IsActive        float32 `json:"IsActive"`
		FSNamesystemMsg `json:",inline"`
	}
	FSNamesystemMsg struct {
		ExpiredHeartbeats                            float32 `json:"ExpiredHeartbeats"`
		TransactionsSinceLastCheckpoint              float32 `json:"TransactionsSinceLastCheckpoint"`
		TransactionsSinceLastLogRoll                 float32 `json:"TransactionsSinceLastLogRoll"`
		LastWrittenTransactionId                     float32 `json:"LastWrittenTransactionId"`
		LastCheckpointTime                           float32 `json:"LastCheckpointTime"`
		CapacityTotal                                float32 `json:"CapacityTotal"`
		CapacityTotalGB                              float32 `json:"CapacityTotalGB"`
	}

把数值的指标放在一个结构体中,其他类型的放在上层里,在进行解析的时候就能正常的进行解析了。

适配本机服务或者多个ip来源

一开始在进行设计的时候,考虑到可能会在一个节点上采集多个其他节点的服务指标,所以就允许服务器信息写成list,比如servers = ["host01", "host02"],在进行指标获取时,直接启动协程进行操作:

	if h.NameNode != nil {
		servers := getNodeList(h.NameNode.Servers)
		var wg sync.WaitGroup
		wg.Add(len(servers))
		for _, nn := range servers {
			go func(namenode string) {
				defer wg.Done()
				conf := make(map[string]string)
				var nameservice string
				url := setConfUrl(h.Scheme, namenode, h.NameNode.HttpPort)
				if err := h.getXml(url, conf); err == nil {
					nameservice = conf["dfs.nameservices"]
				}
				tags := map[string]string{"nn": namenode, "nameservice": nameservice}
				if err := h.gatherAllNamenodeMetrics(namenode, acc, tags); err != nil {
					acc.AddGauge("hdfs_namenode_state", map[string]interface{}{"Healthy": 0}, tags)
					acc.AddError(fmt.Errorf("can not get jmx data from namenode %s", namenode))
				}
			}(nn)
		}
		wg.Wait()
	}

程序打包

telegraf提供了makefile文件进行打包操作,可以直接输入make help查看具体的使用方式,注意,打包文件中使用fpm命令作为打包工具,因此需要自己安装ruby语言环境和fpm工具,我的建议是安装尽量高版本的ruby,否则可能出现各种问题,原先我安装的2.3版本在执行fpm的时候就有问题,可以选择我用的2.6.5p114版本:

[root@bigdata-m-002 telegraf]# ruby --version
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
[root@bigdata-m-002 telegraf]# fpm -v
1.15.1

这里举个例子,比如我们准备编译成tag.gz包,使用以下命令:

make package include_packages="linux_amd64.tar.gz"

如果想要自定义一部分打包的操作,比如希望打包的tag.gz包中有自己增加的脚本文件,只需要在install部分进行增加:

.PHONY: install
install: $(buildbin)
        @mkdir -pv $(DESTDIR)$(bindir)
        @mkdir -pv $(DESTDIR)$(sysconfdir)
        @mkdir -pv $(DESTDIR)$(localstatedir)
        @if [ $(GOOS) != "windows" ]; then mkdir -pv $(DESTDIR)$(sysconfdir)/logrotate.d; fi
        @if [ $(GOOS) != "windows" ]; then mkdir -pv $(DESTDIR)$(localstatedir)/log/telegraf; fi
        @if [ $(GOOS) != "windows" ]; then mkdir -pv $(DESTDIR)$(sysconfdir)/telegraf/telegraf.d; fi
        @cp -fv $(buildbin) $(DESTDIR)$(bindir)
        @if [ $(GOOS) != "windows" ]; then cp -fv etc/telegraf.conf $(DESTDIR)$(sysconfdir)/telegraf/telegraf.conf$(conf_suffix); fi
        @if [ $(GOOS) != "windows" ]; then cp -fv etc/logrotate.d/telegraf $(DESTDIR)$(sysconfdir)/logrotate.d; fi
        @if [ $(GOOS) = "windows" ]; then cp -fv etc/telegraf_windows.conf $(DESTDIR)/telegraf.conf; fi
        @if [ $(GOOS) = "linux" ]; then scripts/check-dynamic-glibc-versions.sh $(buildbin) $(glibc_version); fi
        @if [ $(GOOS) = "linux" ]; then mkdir -pv $(DESTDIR)$(prefix)/lib/telegraf/scripts; fi
        @if [ $(GOOS) = "linux" ]; then cp -fv scripts/telegraf.service $(DESTDIR)$(prefix)/lib/telegraf/scripts; fi
        @if [ $(GOOS) = "linux" ]; then cp -fv scripts/init.sh $(DESTDIR)$(prefix)/lib/telegraf/scripts; fi
        @if [ $(GOOS) = "linux" ]; then cp -fv scripts/install_telegraf_cs6.sh $(DESTDIR)$(prefix)/install_telegraf_cs6.sh; fi

如上,我添加了最后一个部分,增加了centos6的telegraf安装脚本,方便我的一键部署,接下来直接进行打包即可:
在这里插入图片描述
打包完成后,程序包会放在build/dist/下:
在这里插入图片描述

结语

本文介绍了基于telegraf实现了一个自己的hdfs指标采集器,下一次要面对将node-exporter采集的指标替换成telegraf的改造过程,完成整个平台的采集器all-in-one变革!

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

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

相关文章

RabbitMQ实现延时队列

目录什么是延时队列延时队列的使用场景前提准备利用RabbitMQ实现延时队列延时队列优化利用RabbitMQ插件实现延迟队列什么是延时队列 延时队列,首先,它是一种队列,队列意味着内部的元素是有序的,元素出队和入队是有方向性的&#…

沃尔玛采购退款大额过不了的原因是什么?

市面上有很多伪装工具,但不是针对沃尔玛,很多软件方只是针对大众平台伪装,主要是方便程序开发人员调测系统程序,并不是能用于沃尔玛行业。而且每一个平台的风控是不—样的,我们技术团队从底层硬件环境开始配合软件控制…

【论文精读】MVSNet系列(2018-2022)总结

MVSNet系列总结1.MVSNet ECCV20182.RMVSNet CVPR20193.P-MVSNet ICCV20194.MVSCRF ICCV20195.PointMVSNet ICCV20192019年的这四篇文章各有特点,其中RMVSNet、PointMVSNet更是打开了可以继续沿着往下做的思路:6.cascade MVSNet CVPR20207.UCSNet CVPR202…

初识go变量,使用var和:=来声明变量,声明变量的三种方式

初识go变量,使用var和:来声明变量,声明变量的三种方式 Go语言的变量名由字母、数字、下划线组成,其中首个字符不能为数字。 tip:(Go语言中的变量的规范,也和其他高级语言相同) 声明变量的一般形式是使用 var 关键字: var 变量…

SpringCloud源码探析(二)-Nacos注册中心

1.概述 Nacos是Spring Cloud Alibaba中的核心组件之一,它提供了服务发现、服务配置和服务管理等功能,可以作为注册中心和配置中心使用。注册中心是微服务架构体系中的核心组件之一,Nacos比Eureka有着更强大的功能,它们都能提供服…

Java多线程系列-- ForkJoin框架,分治的艺术

前言 本篇是多线程系列中的一篇,我们在先前的一篇文章中回顾了线程池的主要知识 Java多线程基础–线程的创建与线程池管理 过去了很长时间,我们简单提要一下: 设计目的:简化线程的使用,管理与复用,避免…

Windows 远程桌面安全吗?电脑远程桌面的安全如何保障?

远程桌面会话在加密通道上运行,防止任何人通过监听网络来查看您的会话。 但是,在早期版本的 RDP 中用于加密会话的方法存在漏洞。 此漏洞可能允许使用中间人攻击 (link is external) 未经授权访问您的会话。 我们可以在 Windows 10、Windows 11 和 Wind…

学好数据结构与算法其实一点也不难

一. 初识算法 1.1 什么是算法? 定义 在数学和计算机科学领域,算法是一系列有限的严谨指令,通常用于解决一类特定问题或执行计算 In mathematics and computer science, an algorithm (/ˈlɡərɪəm/) is a finite sequence of rigorous …

MSVCP140.dll下载及安装教程,dll修复方法

MSVCP140.dll是Windows操作系统中的一个DLL文件,许多程序依赖于它来正常运行。如果您尝试运行某个程序时,发现缺少MSVCP140.dll文件,那么您需要下载并安装它才能解决问题。本文将介绍如何MSVCP140.dll下载和安装MSVCP140.dll。 第一步&#x…

解决树莓派 bullseye (11) 系统无法通过 xrdp 远程连接的问题

我手上有一台树莓派 4B,使用官方镜像烧录器烧录老版本操作系统 buster (10) 时可以正常通过 Windows 远程桌面连接上,但换成最新的 bullseye (11) 系统后却无法正常连接远程桌面。 问题复现: 使用官方镜像烧录器烧录,配置用户名为…

CSDN 竞赛 32 期

CSDN 竞赛 32 期1、题目名称:传奇霸业2、题目名称:严查枪火3、题目名称:蚂蚁家族4、题目名称:运输石油小结1、题目名称:传奇霸业 传奇霸业,是兄弟就来干。 小春(HP a)遇到了一只黄金哥布林(HP x)。 小春每…

20个让你效率更高的CSS代码技巧

在本文中,我们想与您分享一个由各大css网站总结推荐的20个有用的规则和实践经验集合。有一些是面向CSS初学者的,有一些知识点是进阶型的。希望每个人通过这篇文章都能学到对自己有用的知识。好了,我们开始。1.注意外边距折叠与其他大多数属性…

从工地转行软件测试,拿下13k+年终奖是种什么体验?

最近,一则名为《我:毕业五年,存款5000。她:中传硕士,火锅店保洁》的视频走红网络,两位名校毕业生看似高开低走的就业经历,引起了很多人的共鸣。她们所传达的并不是所谓的躺平、摆烂,而是希望更多…

spark性能调优(一):Shuffle

Shuffle 一、配置项调优二、减少shuffle数据量三、避免shuffle何为shuffle? 集群中跨进程、跨节点的数据分发(Map的输出文件写到本地磁盘,Reducer把Map的输出文件拉到本地)为什么要shuffle? 准确的说,shuffle是刚需(业务场景决定的),分布式环境中,不同节点不能进行内存交换,只…

加快发展先进制造业势在必行!

众所周知,我国是制造大国,但并非制造强国。而我们在持续发展制造业的进程中也面临着诸多实际问题,如产业发展后续乏力,环境制约异常突出,技术创新能力薄弱,结构调整任务艰巨等等。故而要实现由制造大国向制…

数据结构与算法之二叉树大全

目录二叉树的定义二叉树的性质(特性)满二叉树与完全二叉树链式存储的二叉树顺序存储的二叉树线索二叉树(Threaded BinaryTree)二叉排序树(Binary Sort Tree)平衡二叉树( Balanced Binary Tree)为什么使用平衡二叉树?如…

Vue中如何利用websocket实现实时通讯

首先我们可以先做一个简单的例子来学习一下简单的websocket模拟聊天对话的功能 原理很简单,有点像VUE中的EventBus,用emit和on传来传去 首先我们可以先去自己去用node搭建一个本地服务器 步骤如下 1.新建一个app.js,然后创建pagejson.js文…

最简单的代码生成器,netcore平台,EF架构,smartsofthelp

1.dbhelper 原生SQL操作类2.Model 实体层3.EF dbfirst 生成entites 实体操作类4.EF实体接口增删改查操作方法成员5.UI 展示层SQL数据脚本Model/// <summary>/// Model实体层 /// </summary>namespace Smart.Model{/// <summary>/// 数据实体层 T_Eventsmart …

珠海数据智能监控器+SaaS平台 轻松实现SMT生产管控

数据智能监控器 兼容市面上99%的SMT设备 直接读取设备生产数据与状态&#xff0c;如&#xff1a;计划产出、实际产出、累计产出、停机、节拍、线利用率、直通率、停产时间、工单状态、OEE…… 产品功能价值 ◎ OEE不达标报警&#xff0c;一手掌握生产效能 ◎ 首检/巡检/成…

研发人员最希望项目经理和PMO能够做什么?看完不要惊讶

作为项目经理和PMO你考虑过自己在其他人眼中的形象么&#xff1f;知道各个环节最希望你做什么吗&#xff1f;对于最常打交道的研发人员&#xff0c;你知道他们最希望你做什么吗&#xff1f; 如果不能了解其他环节对你的期望&#xff0c;你往往很难获得认同&#xff0c;为此&am…