如果要获取独特的度量指标,使用Textfile Collector来获取独特的度量指标

你好,我是sugitak。今年我正在省能源模式下进行活动,所以这只是一个普通的条目。

引言

Prometheus监控的对象被称为Exporter。Exporter会以Prometheus格式在/metrics路径下公开数据。而且,Exporter可以使用各种库很容易地实现。

使用Golang库的示例

// A minimal example of how to include Prometheus instrumentation.
package main

import (
    "flag"
    "log"
    "net/http"

    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var addr = flag.String("listen-address", ":8080", "The address to listen on for HTTP requests.")

func main() {
    flag.Parse()
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(*addr, nil))
}

从 https://github.com/prometheus/client_golang 的 examples/simple/main.go 文件中提取。

使用Python库的示例

from prometheus_client import start_http_server, Summary
import random
import time

# Create a metric to track time spent and requests made.
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')

# Decorate function with metric.
@REQUEST_TIME.time()
def process_request(t):
    """A dummy function that takes some time."""
    time.sleep(t)

if __name__ == '__main__':
    # Start up the server to expose the metrics.
    start_http_server(8000)
    # Generate some requests.
    while True:
        process_request(random.random())

来自 https://github.com/prometheus/client_python 的 README.md。

这并不像你想的那样简单!真遗憾!!!

为什么这么辛苦呢?

不知怎么的,我觉得编写监控脚本并不那么困难。
比如说,用Nagios的话只需要返回值是0、1还是2,而为了适配Cacti的SNMP,只需将数据写入特定的文件。至于为了适配Zabbix的脚本,最终目标也只是输出数字而已。

当我们考虑监视时,或许我们会下意识地想象出一个“一旦执行就结束”的脚本。

但是,如果要创建一个导出器,那肯定要创建一个服务器。创建服务器意味着要使用比简单脚本更正式的面向对象的方法,并且该库在某种程度上已经隐藏了无法看见的世界。

如果感到痛苦,可以尝试使用轻松的方法。

轻松的方法

使用 Prometheus 的话,我认为肯定会运行 node_exporter,它有一个叫做 –collector.textfile.directory 的选项。
通过这个选项指定一个目录,node_exporter 会查看该目录下的 *.prom 文件,并将内容由 node_exporter 输出。由于管理对象不会增加太多,所以非常方便!实用!太棒了!牛!

这个功能被称为Textfile Collector,所以在查看其他资料时,请记住它的名字。
另外,提到术语的话,当访问node_exporter时会显示大量的度量指标,而那种格式的名称被称为文本格式。我以前一直以为叫Prometheus格式,但是错了。真是悲伤。

里久哥,什么是文本格式?

好吧,刚才的Textfile收集器的内容实际上是文本格式的。为了回忆起来,让我们从node_exporter的输出中提取出来。

# 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
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 14
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.9.2"} 1

你是说把这种东西称为“文本格式”对吧?

困難之处在于,无论是看起来像是注释的部分,还是包含在其中的所有内容,都是以“文本格式”呈现的。换句话说,仅仅输出 “go_gc_duration_seconds_sum 0” 是不够的。

因此,我们应该使用库来解决这个问题。

编写用于文本文件收集器的脚本

让我们使用 https://github.com/prometheus/client_python,轻松地编写适用于textfile collector的脚本吧!

框架大致是这样的。与之前相比,简单得令人震撼!

#!/usr/bin/env python3
import time
from prometheus_client import write_to_textfile, REGISTRY

TMP_PATH = '/path/to/textfile/directory/hogefuga.prom'

while True:
    write_to_textfile(TMP_PATH, REGISTRY)
    time.sleep(10)

这个库的关键是 write_to_textfile,它将所有存储在该库中的数据以文本格式写入文件。REGISTRY是一种所谓的魔法(希望它成为默认参数…我要创建一个PR…)。顺便提一下,这个文件必须是一个实际文件路径…不能使用标准输入输出或者/dev下的文件夹。然而,作为替代,它支持原子写入,因此不需要担心在写入过程中的操作。放心!

添加计量器(Gauge)

Gauge是用来输入喜欢的值的东西。比如温度,内存使用量,每分钟的访问次数,就是这些东西吧。我觉得可能是最常用的吧。
随意填入随机值的例子:

#!/usr/bin/env python3
import random
import time
from prometheus_client import Gauge, write_to_textfile, REGISTRY

TMP_PATH = '/path/to/textfile/directory/hogefuga.prom'

g = Gauge('fuga_requests', 'Gauge')
while True:
    g.set(random.randint(1, 100))

    write_to_textfile(TMP_PATH, REGISTRY)
    time.sleep(10)

这是一个仅创建一个Gauge对象并设置值的例子。无论在实际使用中做什么,最终都只是在这个主循环中调用外部API之类的东西。简单容易。在Gauge()的第一个参数中指定了度量名称。第二个参数是帮助字符串,可以为空。

添加一个计数器

Counter 是指那些在运行 ifconfig 命令后显示的接收数据包数量和错误数量等类似的指标,它们被称为“一旦上升就不会再下降(除非重启)”的东西。

#!/usr/bin/env python3
import time
from prometheus_client import Counter, write_to_textfile, REGISTRY

TMP_PATH = '/path/to/textfile/directory/hogefuga.prom'

c = Counter('piyo_count', 'piyopiyo hiyoko san')
c.inc(100) # 初期値

while True:
    c.inc()

    write_to_textfile(TMP_PATH, REGISTRY)
    time.sleep(10)

在基本上,计数器(Counter)只能使用inc()方法。换句话说,它只能增加,而不能减少。
虽然不能设置值,但是如果在脚本开始时想要指定初始值,只需使用inc(<初始值>)即可,所以可能不会太困扰。如果有困扰的话,可以考虑使用测量器(gauge)而不是计数器(counter)。

大致完成

嗯,就像这样,通过使用 Counter 和 Gauge 两个实例,我们得到了下面这样的示例脚本。

#!/usr/bin/env python3
import random
import time
from prometheus_client import Counter, Gauge, write_to_textfile, REGISTRY

TMP_PATH = '/path/to/textfile/directory/hogefuga.prom'

if __name__ == '__main__':
    c = Counter('piyo_count', 'piyopiyo hiyoko san')
    g = Gauge('fuga_requests', 'Gauge')
    while True:
        c.inc()
        g.set(random.randint(1, 100))

        write_to_textfile(TMP_PATH, REGISTRY)
        time.sleep(10)

只需要大约20行。做的事情也相当明了。然后只需要将这个脚本放入supervisord等,从此之后node_exporter会输出这些内容。很不错呢。

$ curl localhost:9100/metrics 2>/dev/null
# HELP fuga_requests Gauge
# TYPE fuga_requests gauge
fuga_requests 100
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 4.1397e-05
go_gc_duration_seconds{quantile="0.25"} 4.1397e-05
go_gc_duration_seconds{quantile="0.5"} 4.3575e-05
go_gc_duration_seconds{quantile="0.75"} 4.3575e-05
go_gc_duration_seconds{quantile="1"} 4.3575e-05
(略)
# HELP node_time System time in seconds since epoch (1970).
# TYPE node_time gauge
node_time 1.5138587445742888e+09
# HELP piyo_count piyopiyo hiyoko san
# TYPE piyo_count counter
piyo_count 86
# HELP python_info Python platform information
# TYPE python_info gauge
python_info{implementation="CPython",major="2",minor="7",patchlevel="10",version="2.7.10"} 1

实际上,当我查看 node_exporter 的输出时,情况是这样的。
哎呀,根据最后一行的信息,看起来我不小心是在使用 python2 而不是 python3 运行的(๑˃̵ᴗ˂̵)

总结

当考虑使用Prometheus来采集自定义指标时,编写独立的Exporter需要一些调试和琐碎的工作,相当费劲。我们想要像传统的监控一样,通过简单的脚本增加监控项。因此,我向大家简要介绍了使用node_exporter的Textfile Collector的方法和基本脚本编写。

借助Textfile Collector,获取自定义指标将变得简单,但是实际上还是增加了自定义实现的数量,这一点是无法改变的。对于那些注重监控工具的可移植性的人来说,可能并不想这样做,而是希望在其中添加类似statsd这样通用的机制。

这次可能做不到那么完美,但是作为获取独特指标的方法来说,这也算是一个目标了吧。

看今年的圣诞节倒计时日历,根据填充的程度来看,大约只有一半左右,但是各个领域都有高质量的文章,真是太棒了。虽然很抱歉我们迟到了,但是能够参加真是光荣。

诸位,祝您度过一个愉快的冬天。愿您过上符剑生活!

广告
将在 10 秒后关闭
bannerAds