Как заставить обновлять значение метрики exporter для prometheus на golang

почтенные граждане!

Судьба заставила меня заняться изготовлением собственного экспортера для "Prometheus" на golang. С тем и другим столкнулся впервые. Экспотер должен "по просьбе" "Prometheus"-а обращаться к таблице в базе данных postgresql, вычитывать из нее одну запись, и одно поле из записи возвращать "Prometheus"-у.

Гуглил, комбинировал, на текущий момент получил код, который приведен ниже. Проблема в том, что код в main() выполняется один раз при старте, успешно запускется http-сервер, и далее ничего не происходит. netstat-ом вижу, что сервер слушает порт, "Prometheus" считает, что экспотрер работает правильно, но при этом значение метрики в "Prometheus" остается то, которое было определено при старте скрипта, хотя, достоверно, в базу пишутся разные новые значения.

Аналогичный экспортер сделал на python-е, который мало-мало знаю - там работает нормально. Подскажите, как заставить сервер на golang-e, в ответ на запросы "Prometheus", возвращать актуальные значение метрики.

package main
import (
    "database/sql"
    "fmt"
    "time"
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    _ "github.com/lib/pq"
)

type mtr struct{
    id int
    moment time.Time
    cpu_load float64
}

func main() {
    metric := prometheus.NewGauge(prometheus.GaugeOpts{Name: "example_gauge", Help: "An example gauge metric",},)
    prometheus.MustRegister(metric)
    metric.Set(get_metrics())
    http.Handle("/metrics", promhttp.Handler())
    fmt.Println("Starting web server\n")
    err := http.ListenAndServe(":9990", nil)
    if err != nil {
    fmt.Println("http.ListenAndServer: %v\n", err)
    }
}

func get_metrics() float64 {
    connStr := "host=192.168.208.101 port=5432 user=masterdb password=passwdb dbname=edudb sslmode=disable"
    db, err := sql.Open("postgres", connStr)
    if err != nil {
            panic(err)
    }
    defer db.Close()
    if db != nil {
        fmt.Println("Is Connect to db")
    }
    row := db.QueryRow("SELECT id, curr_time, cpu_load FROM edutbl ORDER BY id DESC LIMIT 1;")
    if err != nil {
        panic(err)
    }
    fmt.Println("Is Row")
    m := mtr{}
    err = row.Scan(&m.cpu_load, &m.moment, &m.cpu_load)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(m.cpu_load)
    fmt.Println("Hendler")
    fmt.Println("L-n-S")
    return m.cpu_load
}

Ответы (1 шт):

Автор решения: Pak Uula

Вам нужно реализовать свой собственный Collector

Метод Collector.Collect вызывается в тот момент, когда прометей опрашивает процесс о новых значениях метрик. Посмотрите пример

В вашем коде вы устанавливаете метрику только один раз вызовом metric.Set(get_metrics()). Неудивительно, что она не обновляется со временем.

→ Ссылка