简体   繁体   English

如何在数据库更改时重新评估 promhttp.Handler?

[英]How to re-evaluate promhttp.Handler on database change?

I'm perhaps abusing promhttp.Handler() to realise the use case for my microservice to tell me the:我可能正在滥用promhttp.Handler()来实现我的微服务的用例告诉我:

  • version版本
  • if it has database connectivity如果它有数据库连接

If there is a better way to monitor my microservices, do let me know!如果有更好的方法来监控我的微服务,请告诉我!

I'm not sure how to structure the handle in such a way that when /metrics are called, the db.Ping() is re-evaluated.我不确定如何构造句柄,以便在调用 /metrics 时重新评估db.Ping()

https://s.natalian.org/2019-06-02/msping.mp4 https://s.natalian.org/2019-06-02/msping.mp4

package main

import (
    "log"
    "net/http"
    "os"

    _ "github.com/go-sql-driver/mysql"
    "github.com/gorilla/mux"
    "github.com/jmoiron/sqlx"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

const version = "0.0.1"

type App struct {
    Router *mux.Router
    DB     *sqlx.DB
}

func main() {
    a := App{}
    a.Initialize()

    log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), a.Router))
}

func (a *App) Initialize() {
    connectionString := "root:secret@tcp(localhost:3306)/rest_api_example?multiStatements=true&sql_mode=TRADITIONAL&timeout=5s"
    var err error
    a.DB, err = sqlx.Open("mysql", connectionString)
    if err != nil {
        log.Fatal(err)
    }

    microservicecheck := prometheus.NewGaugeVec(
        prometheus.GaugeOpts{
            Name: "mscheck",
            Help: "Version with DB ping check",
        },
        []string{
            "commit",
        },
    )

    if a.DB.Ping() == nil {
        microservicecheck.WithLabelValues(version).Set(1)
    } else {
        microservicecheck.WithLabelValues(version).Set(0)
    }

    prometheus.MustRegister(microservicecheck)

    a.Router = mux.NewRouter()
    a.initializeRoutes()
}

func (a *App) initializeRoutes() {
    a.Router.Handle("/metrics", promhttp.Handler()).Methods("GET")
}

https://play.golang.org/p/9DdXnz77S55 https://play.golang.org/p/9DdXnz77S55

You could also add a middleware hook that does a preflight routine (ie your ping test) before calling promhttp.Handler() .您还可以添加一个中间件挂钩,在调用promhttp.Handler()之前执行预检例程(即您的 ping 测试promhttp.Handler() However, at collection time, I think metrics should already have been tallied;然而,在收集时,我认为指标应该已经被计算在内; and not generated at the instance of collection.而不是在集合实例中生成。 So...所以...

Try a separate go-routine that will poll the health of the DB connection at regular intervals.尝试一个单独的 go-routine,它将定期轮询数据库连接的健康状况。 This avoids any messy hooks or custom collectors:这避免了任何杂乱的钩子或自定义收集器:

var pingPollingFreq = 5 * time.Second // this should probably match the Prometheus scrape interval

func (a *App) Initialize() {       
    // ...

    prometheus.MustRegister(microservicecheck)

    go func() {
        for {
            if a.DB.Ping() == nil {
                microservicecheck.WithLabelValues(version).Set(1)
            } else {
                microservicecheck.WithLabelValues(version).Set(0)
            }
            time.Sleep(pingPollingFreq)
        }
    }()

    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM