在Go中编写应用程序Prometheus导出器的15个步骤

tl;dr: Full example code: https://github.com/teamzerolabs/mirth_channel_exporter, read on to see step by step instructions

tl; dr:完整示例代码: https : //github.com/teamzerolabs/mirth_channel_exporter ,请继续阅读以了解逐步说明

背景(Background)

Exporters are the heart and soul of Prometheus Monitoring Pipelines. If you run into a situation where an exporter does not exist yet, you are encouraged to write your own. We will cover the steps required to make the exporter. No worries, it is quick.

出口商是Prometheus监控管道的心脏和灵魂。 如果遇到出口商尚不存在的情况,建议您编写自己的出口商。 我们将介绍制造出口商所需的步骤。 不用担心,它很快。

目标 (Goal)

  • Write an exporter in GO.

    在GO中编写导出器。
  • Exporter will call REST API against an application (Mirth Connect in this example) when scraped.

    抓取时,导出程序将针对应用程序(此示例中为“ Mirth Connect”)调用REST API。
  • Exporter will convert the result payload into Metrics.

    导出程序会将结果有效负载转换为指标。

1.设置GO和程序包依赖性 (1. Setup GO and Package Dependencies)

go mod init my_first_exporter 
go get github.com/prometheus/client_golang
go get github.com/joho/godotenv--> creates go.mod file
--> Installs dependency into the go.mod file

2.创建入口点和导入依赖项 (2. Create Entry-point and Import Dependencies)

Create main.go file, and paste in the following:

创建main.go文件,然后粘贴以下内容:

package main

import (
"github.com/joho/godotenv"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

3.放入入口点函数main() (3. Put in Entry-point function main())

func main() {
}

4.添加prometheus指标终结点并在服务器端口上侦听 (4. Add prometheus metrics endpoint and listen on the server port)

func main() {
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":9101", nil))
}

5.使用curl探索外部服务API (5. Explore External Services API with curl)

The application I am monitoring is MirthConnect. I will be making two API calls:

我正在监视的应用程序是MirthConnect。 我将进行两个API调用:

a. get channel statisticsb. get channel id and name mapping

一种。 获取频道统计信息b。 获取频道ID和名称映射

curl -k --location --request GET 'https://apihost/api/channels/statistics' \
--user admin:admin


curl -k --location --request GET 'https://apihost/api/channels/idsAndNames' \
--user admin:admin

6.将curl调用转换为go http调用,并处理结果解析 (6. Convert the curl call into go http calls, and handle the result parsing)

This is the most difficult step in the entire process if you are new to Go. For my example, my endpoints return XML payload. This means I had to deserialize XML with the “encoding/xml” package.

如果您不熟悉Go,这是整个过程中最困难的步骤。 对于我的示例,端点返回XML有效负载。 这意味着我必须使用“ encoding / xml”包对XML进行反序列化。

A successful conversion means my GO program can perform the same API calls as the curl commands. Here are some GO packages to read up about:

成功的转换意味着我的GO程序可以执行与curl命令相同的API调用。 这是一些GO包,供您阅读:

  • “crypto/tls" = specify TLS connection options.
    “io/ioutil” = reading the result payload from buffer into strings
    “net/http” = create transport and clients
    “strconv” = converting string to numbers like floating point/integer

    “ crypto / tls” =指定TLS连接选项。 “ io / ioutil” =将结果有效载荷从缓冲区读入字符串“ net / http” =创建传输和客户端“ strconv” =将字符串转换为浮点数/整数之类的数字

You can iterate through the payload and print out their values with the “log” package.

您可以遍历有效负载并使用“ log”包打印出它们的值。

7.声明普罗米修斯度量描述 (7. Declare Prometheus metric descriptions)

In Prometheus, each metric is made of the following: metric name/metric label values/metric help text/metric type/measurement.

在Prometheus中,每个指标均由以下各项组成:指标名称/指标标签值/指标帮助文本/指标类型/度量。

Example:

例:

# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.# TYPE promhttp_metric_handler_requests_total counterpromhttp_metric_handler_requests_total{code=”200"} 1.829159e+06promhttp_metric_handler_requests_total{code=”500"} 0promhttp_metric_handler_requests_total{code=”503"} 0

#由HTTP状态代码。#TYPE promhttp_metric_handler_requests_total计数器promhttp_metric_handler_requests_total {代码=” 200" } 1.829159e + 06 promhttp_metric_handler_requests_total {代码=” 500" } 0 promhttp_metric_handler_requests_total {代码=” 503" } 0 HELP promhttp_metric_handler_requests_total总数刮擦

For application scrapers, we will define Prometheus metric descriptions, which includes metric name/metric labels/metric help text.

对于应用程序抓取工具,我们将定义Prometheus度量标准描述,其中包括度量标准名称/度量标准标签/度量标准帮助文本。

messagesReceived = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", "messages_received_total"),
"How many messages have been received (per channel).",
[]string{"channel"}, nil,
)

8.使用接口存根声明Prometheus Exporter (8. Declare the Prometheus Exporter with interface stubs)

Custom exporters requires 4 stubs:

海关出口商需要4个存根:

a. A structure with member variablesb. A factory method that returns the structurec. Describe functiond. Collect function

一种。 具有成员变量的结构b。 返回结构c的工厂方法。 描述功能。 收集功能

type Exporter struct {
mirthEndpoint, mirthUsername, mirthPassword string}

func NewExporter(mirthEndpoint string, mirthUsername string, mirthPassword string) *Exporter {
return &Exporter{
mirthEndpoint: mirthEndpoint,
mirthUsername: mirthUsername,
mirthPassword: mirthPassword,
}
}func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
}func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
}

9.在describe函数中,将步骤7中的度量描述发送给它。 (9. Inside describe function, send it the metric descriptions from step 7.)

func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
ch <- up
ch <- messagesReceived
ch <- messagesFiltered
ch <- messagesQueued
ch <- messagesSent
ch <- messagesErrored
}

10.将api调用的逻辑从6移到collect函数 (10. Move the logic of api calls from 6 into the collect function)

Here we want to take the logic from step 6, and instead of printing things out to the screen, sending it into prometheus.Metric channel:

在这里,我们要采用步骤6的逻辑,而不是将内容打印到屏幕上,而是将其发送到prometheus.Metric通道:

func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
channelIdNameMap, err := e.LoadChannelIdNameMap()
if err != nil {
ch <- prometheus.MustNewConstMetric(
up, prometheus.GaugeValue, 0,
)
log.Println(err)
return}
ch <- prometheus.MustNewConstMetric(
up, prometheus.GaugeValue, 1,
)

e.HitMirthRestApisAndUpdateMetrics(channelIdNameMap, ch)
}

As you perform the api call, be sure to send in the measurements using prometheus.MustNewConstMetric(prometheus.Desc, metric type, measurement)

在执行api调用时,请务必使用prometheus.MustNewConstMetric(prometheus.Desc,度量标准类型,度量值)发送度量值

For cases where you need to pass in extra labels, include them at the end of the argument list like this:

对于需要传递额外标签的情况,可将它们包括在参数列表的末尾,如下所示:

channelError, _ := strconv.ParseFloat(channelStatsList.Channels[i].Error, 64)ch <- prometheus.MustNewConstMetric(
messagesErrored, prometheus.GaugeValue, channelError, channelName,
)

11.在主功能中声明导出器,并进行注册 (11. Declare the exporter in main function, and register it)

exporter := NewExporter(mirthEndpoint, mirthUsername, mirthPassword)
prometheus.MustRegister(exporter)

Your exporter is now ready to use!Every time you hit the metrics route, it will perform the api call, and return the result in Prometheus Text file format.The rest of the steps deal with tidying things up for easier deployment.

您的导出器现在可以使用了,每次您点击指标路由时,它将执行api调用,并以Prometheus Text文件格式返回结果。其余步骤用于整理内容以简化部署。

12.将硬编码的api路径移到标志中 (12. Move hard coded api paths into flags)

So far, we are hard coding a couple of things like application base url, metric route url, and exporter port. We can make the program more flexible by parsing these values from command line flags:

到目前为止,我们正在对一些代码进行硬编码,例如应用程序基本URL,度量路由URL和导出器端口。 通过从命令行标志解析这些值,可以使程序更灵活:

var (
listenAddress = flag.String("web.listen-address", ":9141",
"Address to listen on for telemetry")
metricsPath = flag.String("web.telemetry-path", "/metrics",
"Path under which to expose metrics")
)func main() {
flag.Parse()
...
http.Handle(*metricsPath, promhttp.Handler())
log.Fatal(http.ListenAndServe(*listenAddress, nil))
}

13.将凭证移到环境变量中 (13. Move credentials into Environment variables)

What if application endpoint changes place, or login credentials change? We can load these from environment variables. In this example, I am using the godotenv package to help with storing variable values locally in the same folder:

如果应用程序端点更改位置或登录凭据更改怎么办? 我们可以从环境变量中加载它们。 在此示例中,我使用godotenv包来帮助将变量值本地存储在同一文件夹中:

import (
"os"
)func main() {
err := godotenv.Load()
if err != nil {
log.Println("Error loading .env file, assume env variables are set.")
} mirthEndpoint := os.Getenv("MIRTH_ENDPOINT")
mirthUsername := os.Getenv("MIRTH_USERNAME")
mirthPassword := os.Getenv("MIRTH_PASSWORD")
}

14.包含一个Makefile以便在不同平台上快速构建 (14. Include a Makefile for quick building on different platforms)

Makefiles can save you a lot of typing during development. For exporters that needs to build to multiple platforms (testing on windows/mac, running in Linux), you can start with the following:

Makefile可以在开发过程中为您节省很多输入时间。 对于需要构建到多个平台的出口商(在Windows / mac上测试,在Linux上运行),您可以从以下内容开始:

linux:
GOOS=linux GOARCH=amd64 go build
mac:
GOOS=darwin GOARCH=amd64 go build

Simply invoke make mac or make linux to see different executable file show up.

只需调用make mac或make linux即可看到不同的可执行文件。

15.编写服务文件以将该守护程序作为守护程序运行 (15. Writing a service file to run this go program as a daemon)

Depending on where this exporter will run, you can either write a service file, or a Dockerfile.

根据此导出器的运行位置,您可以编写服务文件或Dockerfile。

A simple Centos 7 Service file looks like the following:

一个简单的Centos 7服务文件如下所示:

[Unit]
Description=mirth channel exporter
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
WorkingDirectory=/mirth/mirthconnect
EnvironmentFile=/etc/sysconfig/mirth_channel_exporter
ExecStart=/mirth/mirthconnect/mirth_channel_exporter

[Install]
WantedBy=multi-user.target

就这样! (That’s all!)

Throughout the flow, the only difficult step is 6. If you know what calls are available and how to parse them, the rest come naturally. Come create more exporters and get more metrics flowing today!

在整个流程中,唯一困难的步骤是6。如果您知道可用的呼叫以及如何解析它们,其余的自然而然。 快来创建更多的出口商并立即获得更多指标!

Thanks for reading, if you need to grab some application metrics quickly, you can contact us at info@teamzerolabs.com!

感谢您的阅读,如果您需要快速掌握一些应用程序指标,可以通过info@teamzerolabs.com与我们联系

翻译自: https://medium.com/teamzerolabs/15-steps-to-write-an-application-prometheus-exporter-in-go-9746b4520e26

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值