【问题标题】:How to re-evaluate promhttp.Handler on database change?如何在数据库更改时重新评估 promhttp.Handler?
【发布时间】:2019-06-02 05:38:59
【问题描述】:

我可能滥用promhttp.Handler() 来实现我的微服务的用例来告诉我:

  • 版本
  • 如果有数据库连接

如果有更好的方法来监控我的微服务,请告诉我!

我不确定如何构造句柄,以便在调用 /metrics 时重新评估 db.Ping()

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

【问题讨论】:

  • 实现并注册一个Collector。它将为每个 /metric 请求调用。请参阅文档中的示例以开始使用。
  • 你不是在滥用用例,这很常见(关于版本,请参阅robust perception article。关于ping,更常见的是在你无法加入时提出指标请求并设置为关闭状态服务。另一种方法是返回错误代码,因为如果服务不可加入,公开指标可能没有意义,并且会在目标 up 指标中报告。
  • 收集器的例子似乎有点复杂! godoc.org/github.com/prometheus/client_golang/…
  • @MichaelDoubez 找不到在 ping 失败时返回错误代码的简单示例 github.com/…
  • 这是我在play.golang.org/p/NhlVgt2oOrJ的地方

标签: go microservices prometheus


【解决方案1】:

您还可以在调用promhttp.Handler() 之前添加一个执行preflight routine(即您的ping 测试)的中间件挂钩。但是,在收集时,我认为指标应该已经被统计过了;并且不是在集合实例中生成的。所以...

尝试一个单独的 go-routine,它会定期轮询数据库连接的健康状况。这避免了任何混乱的钩子或自定义收集器:

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)
        }
    }()

    // ...
}

【讨论】:

    猜你喜欢
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2014-04-01
    • 2010-12-27
    • 2017-04-07
    • 1970-01-01
    相关资源
    最近更新 更多