英文:
Golang Prometheus Exporter - Pull metrics on demand
问题
根据Prometheus文档中的定义,当编写exporter时,它指出了以下内容:
>指标应该只在Prometheus抓取它们时从应用程序中获取,exporter不应该根据自己的定时器执行抓取。
以下代码在技术上可以正常工作,并发布了一个包含自定义指标的适当页面。因此,它解决了我的业务需求。
然而,它是低效的,并且运行一个无限循环来不断更新值。这与上述文档中提到的仅在Prometheus抓取时生成指标值的做法不符。
为了只在Prometheus抓取exporter端点时获取指标,这意味着我需要以某种方式监听http.ListenAndServe()
对象上的GET请求。我该如何做到这一点?
在我的阅读中,我发现了http.HandlerFunc()
而不是http.Handler()
,它似乎走在正确的道路上,但我无法将其与promhttp.Handler()
配合使用,我对此感到非常困惑。
英文:
As defined in the prometheus documentation, when writing exporters it states the following:
>Metrics should only be pulled from the application when Prometheus scrapes them, exporters should not perform scrapes based on their own timers.
The following code technically works fine, and publishes an appropriate page with my custom metric. So it solves my business need as-is.
However, it is inefficient and running an infinite loop to constantly update the value. This does not match the above mentioned practice from the documentation of only generating metric values when Prometheus scrapes.
package main
import (
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
var metricSystemTime = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "custom_system_time", Help: "Timestamp in unix epoch format"})
prometheus.MustRegister(metricSystemTime)
go startServer()
for {
metricSystemTime.Set(float64(time.Now().Unix()))
time.Sleep(1 * time.Second)
}
}
func startServer() {
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":19100", nil))
}
In order to only pull metrics when prometheus scrapes the exporter endpoint, that means I need to somehow listen for GET requests on the http.ListenAndServe()
object? How can I do that?
In my reading I found http.HandlerFunc()
instead of http.Handler()
which seems to be going down the right path, but I can't get it to work with promhttp.Handler()
and I'm getting pretty lost on it.
答案1
得分: 7
在进行了大量搜索后,我找到了解决方法。希望这对将来的某个人有所帮助。
这是一个可工作的导出器,符合只在进行Prometheus抓取时收集指标的要求:
- 没有无限循环,没有内部定时器。
- 每次Prometheus抓取导出器时,根据原始问题中的文档发布新的指标。
package main
import (
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type Collector struct {
// 为每个在newCollector()函数中定义的收集器添加下面的行
systemTime *prometheus.Desc
}
// 在这里声明你的导出器指标,称为"collectors"
func newCollector() *Collector {
return &Collector{
systemTime: prometheus.NewDesc("my_system_time",
"System timestamp in unix epoch format",
nil, nil,
),
// 在这里添加更多的收集器(即指标定义)
}
}
func (collector *Collector) Describe(ch chan<- *prometheus.Desc) {
// 对于上面声明的每个收集器,添加下面的行
ch <- collector.systemTime
}
// 当Prometheus抓取导出器时,此函数将运行。它将为指标设置一个新值
// 我不知道它是如何工作的,但它确实可以。
func (collector *Collector) Collect(ch chan<- prometheus.Metric) {
var setSystemTime float64
// 计算指标的值
setSystemTime = float64(time.Now().Unix())
// 在这里设置指标的"新"值
// 此示例是一个Gauge,但它可以是任何Prom指标类型
ch <- prometheus.MustNewConstMetric(collector.systemTime, prometheus.GaugeValue, setSystemTime)
}
// 主函数,生成收集器和Web服务器
func main() {
collector := newCollector()
prometheus.MustRegister(collector)
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":19100", nil))
}
希望这能帮到你!
英文:
Figured it out after doing a lot of searching. Hopefully this helps someone in the future.
Here is a working exporter that fits the requirement of only gathering metrics when a prometheus scrape happens
- No endless loops, no internal timers.
- Publishes new metrics every time Prometheus scrapes the exporter, as defined in the documentation from the original question.
package main
import (
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type Collector struct {
// Add one of the below lines for each collector you define in the newCollector() function
systemTime *prometheus.Desc
}
// Declare your exporter metrics here. Referred to as "collectors"
func newCollector() *Collector {
return &Collector{
systemTime: prometheus.NewDesc("my_system_time",
"System timestamp in unix epoch format",
nil, nil,
),
// Add more collectors (aka metric definitions) here
}
}
func (collector *Collector) Describe(ch chan<- *prometheus.Desc) {
// Add one of these lines for each of your collectors declared above
ch <- collector.systemTime
}
// This fuction runs when Prometheus scrapes the exporter. It will set a new value for the metric(s)
// I have no idea how it works, but it does.
func (collector *Collector) Collect(ch chan<- prometheus.Metric) {
var setSystemTime float64
// Calculate the value of the metric
setSystemTime = float64(time.Now().Unix())
// Here is where you set the "new" value for the metric
// This example is a Gauge, but it can be any Prom metric type
ch <- prometheus.MustNewConstMetric(collector.systemTime, prometheus.GaugeValue, setSystemTime)
}
// Main function, spawns the collector and the web server
func main() {
collector := newCollector()
prometheus.MustRegister(collector)
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":19100", nil))
}
答案2
得分: -2
你引用的文档是关于编写导出器的。导出器通常是一个实用程序,它以自定义格式从另一个应用程序中提取指标,并以Prometheus格式公开它们。
你展示的代码是一种正确的方式来为你自己的应用程序添加指标。你的业务逻辑在进行时更新指标,当请求时,HTTP服务器会提供当前的指标值。
英文:
The documentation you quoted is about writing an exporter. The exporter usually is an utility that extracts metrics from another application in a custom format and exposes them in prometheus format.
The code you showed is a correct way to instrument your own application. Your business logic updates the metric as it goes and the HTTP server serves the current metric value when requested.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论