Commit 52adb76
Antonio Mika
·
2026-10-25 21:57:09 -0400 EDT
parent f7a24d3
feat(metrics): export server info with nodename and commit
10 files changed,
+109,
-0
+3,
-0
| ... | ... | @@ -11,7 +11,9 @@ import ( | |
| 11 | 11 | "strings" | |
| 12 | 12 | ||
| 13 | 13 | "github.com/picosh/pico/pkg/apps/pgs" | |
| 14 | + | "github.com/picosh/pico/pkg/metrics" | |
| 14 | 15 | "github.com/picosh/pico/pkg/shared" | |
| 16 | + | "github.com/prometheus/client_golang/prometheus" | |
| 15 | 17 | "github.com/prometheus/client_golang/prometheus/promhttp" | |
| 16 | 18 | ) | |
| 17 | 19 |
| ... | ... | @@ -36,6 +38,7 @@ func main() { | |
| 36 | 38 | } | |
| 37 | 39 | ||
| 38 | 40 | go pgs.CacheMgmt(ctx, cfg, cache, nil) | |
| 41 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pgs-cdn") | |
| 39 | 42 | ||
| 40 | 43 | portStr := fmt.Sprintf(":%s", cfg.WebPort) | |
| 41 | 44 | cfg.Logger.Info( |
+3,
-0
| ... | ... | @@ -19,10 +19,12 @@ import ( | |
| 19 | 19 | ||
| 20 | 20 | "github.com/picosh/pico/pkg/db" | |
| 21 | 21 | "github.com/picosh/pico/pkg/db/postgres" | |
| 22 | + | picoMetrics "github.com/picosh/pico/pkg/metrics" | |
| 22 | 23 | "github.com/picosh/pico/pkg/shared" | |
| 23 | 24 | "github.com/picosh/pico/pkg/shared/router" | |
| 24 | 25 | "github.com/picosh/utils/pipe" | |
| 25 | 26 | "github.com/picosh/utils/pipe/metrics" | |
| 27 | + | "github.com/prometheus/client_golang/prometheus" | |
| 26 | 28 | "github.com/prometheus/client_golang/prometheus/promhttp" | |
| 27 | 29 | "golang.org/x/crypto/ssh" | |
| 28 | 30 | ) |
| ... | ... | @@ -956,6 +958,7 @@ func StartApiServer() { | |
| 956 | 958 | portStr := fmt.Sprintf(":%s", cfg.Port) | |
| 957 | 959 | logger.Info("starting server on port", "port", cfg.Port) | |
| 958 | 960 | ||
| 961 | + | picoMetrics.RegisterServerInfo(prometheus.DefaultRegisterer, "auth") | |
| 959 | 962 | err := http.ListenAndServe(portStr, mux) | |
| 960 | 963 | if err != nil { | |
| 961 | 964 | logger.Info("http-serve", "err", err.Error()) |
+3,
-0
| ... | ... | @@ -7,8 +7,10 @@ import ( | |
| 7 | 7 | "time" | |
| 8 | 8 | ||
| 9 | 9 | "github.com/picosh/pico/pkg/db/postgres" | |
| 10 | + | "github.com/picosh/pico/pkg/metrics" | |
| 10 | 11 | "github.com/picosh/pico/pkg/shared" | |
| 11 | 12 | "github.com/picosh/pico/pkg/shared/router" | |
| 13 | + | "github.com/prometheus/client_golang/prometheus" | |
| 12 | 14 | "github.com/prometheus/client_golang/prometheus/promhttp" | |
| 13 | 15 | ) | |
| 14 | 16 |
| ... | ... | @@ -143,5 +145,6 @@ func StartApiServer() { | |
| 143 | 145 | "domain", cfg.Domain, | |
| 144 | 146 | ) | |
| 145 | 147 | ||
| 148 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "feeds") | |
| 146 | 149 | logger.Error(http.ListenAndServe(portStr, web.mux()).Error()) | |
| 147 | 150 | } |
+2,
-0
| ... | ... | @@ -9,6 +9,7 @@ import ( | |
| 9 | 9 | ||
| 10 | 10 | "github.com/picosh/pico/pkg/db" | |
| 11 | 11 | "github.com/picosh/pico/pkg/db/postgres" | |
| 12 | + | "github.com/picosh/pico/pkg/metrics" | |
| 12 | 13 | "github.com/picosh/pico/pkg/shared" | |
| 13 | 14 | "github.com/picosh/pico/pkg/shared/router" | |
| 14 | 15 | "github.com/prometheus/client_golang/prometheus" |
| ... | ... | @@ -369,6 +370,7 @@ func StartApiServer() { | |
| 369 | 370 | web := &webRouter{cfg: cfg, db: db} | |
| 370 | 371 | handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux()) | |
| 371 | 372 | handler = router.NewUserMetrics("pastes", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler) | |
| 373 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pastes") | |
| 372 | 374 | ||
| 373 | 375 | portStr := fmt.Sprintf(":%s", cfg.Port) | |
| 374 | 376 | logger.Info( |
+2,
-0
| ... | ... | @@ -18,6 +18,7 @@ import ( | |
| 18 | 18 | "github.com/hashicorp/golang-lru/v2/expirable" | |
| 19 | 19 | "github.com/picosh/pico/pkg/db" | |
| 20 | 20 | "github.com/picosh/pico/pkg/httpcache" | |
| 21 | + | "github.com/picosh/pico/pkg/metrics" | |
| 21 | 22 | "github.com/picosh/pico/pkg/shared" | |
| 22 | 23 | "github.com/picosh/pico/pkg/shared/router" | |
| 23 | 24 | "github.com/picosh/pico/pkg/storage" |
| ... | ... | @@ -166,6 +167,7 @@ func StartApiServer(cfg *Config) { | |
| 166 | 167 | "port", cfg.WebPort, | |
| 167 | 168 | "domain", cfg.Domain, | |
| 168 | 169 | ) | |
| 170 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pgs") | |
| 169 | 171 | err := http.ListenAndServe(portStr, NewSiteMetrics(cfg, "pgs", false).Handler(httpCache)) | |
| 170 | 172 | cfg.Logger.Error( | |
| 171 | 173 | "listen and serve", |
+2,
-0
| ... | ... | @@ -16,6 +16,7 @@ import ( | |
| 16 | 16 | ||
| 17 | 17 | "github.com/gorilla/websocket" | |
| 18 | 18 | "github.com/picosh/pico/pkg/db/postgres" | |
| 19 | + | "github.com/picosh/pico/pkg/metrics" | |
| 19 | 20 | "github.com/picosh/pico/pkg/shared" | |
| 20 | 21 | "github.com/picosh/pico/pkg/shared/router" | |
| 21 | 22 | "github.com/picosh/utils/pipe" |
| ... | ... | @@ -514,6 +515,7 @@ func StartApiServer() { | |
| 514 | 515 | web := &webRouter{cfg: cfg, db: db, conn: newPipeConn(info)} | |
| 515 | 516 | handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux()) | |
| 516 | 517 | handler = router.NewUserMetrics("pipe", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler) | |
| 518 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pipe") | |
| 517 | 519 | ||
| 518 | 520 | portStr := fmt.Sprintf(":%s", cfg.Port) | |
| 519 | 521 | logger.Info( |
+2,
-0
| ... | ... | @@ -16,6 +16,7 @@ import ( | |
| 16 | 16 | "github.com/gorilla/feeds" | |
| 17 | 17 | "github.com/picosh/pico/pkg/db" | |
| 18 | 18 | "github.com/picosh/pico/pkg/db/postgres" | |
| 19 | + | "github.com/picosh/pico/pkg/metrics" | |
| 19 | 20 | "github.com/picosh/pico/pkg/shared" | |
| 20 | 21 | "github.com/picosh/pico/pkg/shared/router" | |
| 21 | 22 | "github.com/picosh/pico/pkg/storage" |
| ... | ... | @@ -992,6 +993,7 @@ func StartApiServer() { | |
| 992 | 993 | web := &webRouter{cfg: cfg, db: dbpool, storage: st} | |
| 993 | 994 | handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux()) | |
| 994 | 995 | handler = router.NewUserMetrics("prose", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler) | |
| 996 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "prose") | |
| 995 | 997 | ||
| 996 | 998 | portStr := fmt.Sprintf(":%s", cfg.Port) | |
| 997 | 999 | logger.Info( |
+56,
-0
| ... | ... | @@ -0,0 +1,56 @@ | |
| 1 | + | // Package metrics holds the Prometheus metrics every pico process exports, | |
| 2 | + | // including the SSH servers, so it can't depend on pkg/shared. | |
| 3 | + | package metrics | |
| 4 | + | ||
| 5 | + | import ( | |
| 6 | + | "os" | |
| 7 | + | "runtime/debug" | |
| 8 | + | ||
| 9 | + | "github.com/prometheus/client_golang/prometheus" | |
| 10 | + | "github.com/prometheus/client_golang/prometheus/promauto" | |
| 11 | + | ) | |
| 12 | + | ||
| 13 | + | // RegisterServerInfo exports pico_server_info for app. Its value is always 1, | |
| 14 | + | // so a query can join it on instance and app to name the server and commit | |
| 15 | + | // behind any other series. | |
| 16 | + | func RegisterServerInfo(reg prometheus.Registerer, app string) { | |
| 17 | + | RegisterServerInfoCommit(reg, app, commit()) | |
| 18 | + | } | |
| 19 | + | ||
| 20 | + | // RegisterServerInfoCommit is RegisterServerInfo for a binary built without | |
| 21 | + | // VCS stamping, which sets its commit through -ldflags instead. | |
| 22 | + | func RegisterServerInfoCommit(reg prometheus.Registerer, app, commit string) { | |
| 23 | + | promauto.With(reg).NewGauge(prometheus.GaugeOpts{ | |
| 24 | + | Namespace: "pico", | |
| 25 | + | Name: "server_info", | |
| 26 | + | Help: "The server and commit a process runs on. Always 1.", | |
| 27 | + | ConstLabels: prometheus.Labels{ | |
| 28 | + | "app": app, | |
| 29 | + | "nodename": os.Getenv("NODENAME"), | |
| 30 | + | "commit": commit, | |
| 31 | + | }, | |
| 32 | + | }).Set(1) | |
| 33 | + | } | |
| 34 | + | ||
| 35 | + | // commit is the VCS revision Go stamped into the binary, with -dirty when the | |
| 36 | + | // tree had uncommitted changes. | |
| 37 | + | func commit() string { | |
| 38 | + | info, ok := debug.ReadBuildInfo() | |
| 39 | + | if !ok { | |
| 40 | + | return "" | |
| 41 | + | } | |
| 42 | + | var revision string | |
| 43 | + | var modified bool | |
| 44 | + | for _, s := range info.Settings { | |
| 45 | + | switch s.Key { | |
| 46 | + | case "vcs.revision": | |
| 47 | + | revision = s.Value | |
| 48 | + | case "vcs.modified": | |
| 49 | + | modified = s.Value == "true" | |
| 50 | + | } | |
| 51 | + | } | |
| 52 | + | if revision != "" && modified { | |
| 53 | + | revision += "-dirty" | |
| 54 | + | } | |
| 55 | + | return revision | |
| 56 | + | } |
+33,
-0
| ... | ... | @@ -0,0 +1,33 @@ | |
| 1 | + | package metrics | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "testing" | |
| 5 | + | ||
| 6 | + | "github.com/prometheus/client_golang/prometheus" | |
| 7 | + | ) | |
| 8 | + | ||
| 9 | + | func TestRegisterServerInfo(t *testing.T) { | |
| 10 | + | t.Setenv("NODENAME", "ash") | |
| 11 | + | reg := prometheus.NewRegistry() | |
| 12 | + | ||
| 13 | + | RegisterServerInfoCommit(reg, "pgs", "abc123") | |
| 14 | + | ||
| 15 | + | families, err := reg.Gather() | |
| 16 | + | if err != nil { | |
| 17 | + | t.Fatalf("gather: %v", err) | |
| 18 | + | } | |
| 19 | + | if len(families) != 1 || families[0].GetName() != "pico_server_info" { | |
| 20 | + | t.Fatalf("got %d families, want only pico_server_info", len(families)) | |
| 21 | + | } | |
| 22 | + | m := families[0].GetMetric()[0] | |
| 23 | + | labels := map[string]string{} | |
| 24 | + | for _, l := range m.GetLabel() { | |
| 25 | + | labels[l.GetName()] = l.GetValue() | |
| 26 | + | } | |
| 27 | + | if labels["app"] != "pgs" || labels["nodename"] != "ash" || labels["commit"] != "abc123" { | |
| 28 | + | t.Errorf("labels = %v, want app=pgs nodename=ash commit=abc123", labels) | |
| 29 | + | } | |
| 30 | + | if got := m.GetGauge().GetValue(); got != 1 { | |
| 31 | + | t.Errorf("value = %v, want 1", got) | |
| 32 | + | } | |
| 33 | + | } |
+3,
-0
| ... | ... | @@ -23,6 +23,7 @@ import ( | |
| 23 | 23 | ||
| 24 | 24 | "github.com/antoniomika/syncmap" | |
| 25 | 25 | "github.com/go-andiamo/splitter" | |
| 26 | + | "github.com/picosh/pico/pkg/metrics" | |
| 26 | 27 | "github.com/prometheus/client_golang/prometheus" | |
| 27 | 28 | "github.com/prometheus/client_golang/prometheus/promauto" | |
| 28 | 29 | "github.com/prometheus/client_golang/prometheus/promhttp" |
| ... | ... | @@ -368,6 +369,8 @@ func (s *SSHServer) ListenAndServe() error { | |
| 368 | 369 | }, | |
| 369 | 370 | }, []string{"command", "user"}) | |
| 370 | 371 | ||
| 372 | + | metrics.RegisterServerInfo(prometheus.DefaultRegisterer, s.Config.App) | |
| 373 | + | ||
| 371 | 374 | // The handler reads the default registerer, so build it before the | |
| 372 | 375 | // listener is published rather than in the goroutine. | |
| 373 | 376 | mux := http.NewServeMux() |