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 (
1111 "strings"
1212
1313 "github.com/picosh/pico/pkg/apps/pgs"
14+ "github.com/picosh/pico/pkg/metrics"
1415 "github.com/picosh/pico/pkg/shared"
16+ "github.com/prometheus/client_golang/prometheus"
1517 "github.com/prometheus/client_golang/prometheus/promhttp"
1618 )
1719
......@@ -36,6 +38,7 @@ func main() {
3638 }
3739
3840 go pgs.CacheMgmt(ctx, cfg, cache, nil)
41+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pgs-cdn")
3942
4043 portStr := fmt.Sprintf(":%s", cfg.WebPort)
4144 cfg.Logger.Info(
+3, -0
......@@ -19,10 +19,12 @@ import (
1919
2020 "github.com/picosh/pico/pkg/db"
2121 "github.com/picosh/pico/pkg/db/postgres"
22+ picoMetrics "github.com/picosh/pico/pkg/metrics"
2223 "github.com/picosh/pico/pkg/shared"
2324 "github.com/picosh/pico/pkg/shared/router"
2425 "github.com/picosh/utils/pipe"
2526 "github.com/picosh/utils/pipe/metrics"
27+ "github.com/prometheus/client_golang/prometheus"
2628 "github.com/prometheus/client_golang/prometheus/promhttp"
2729 "golang.org/x/crypto/ssh"
2830 )
......@@ -956,6 +958,7 @@ func StartApiServer() {
956958 portStr := fmt.Sprintf(":%s", cfg.Port)
957959 logger.Info("starting server on port", "port", cfg.Port)
958960
961+ picoMetrics.RegisterServerInfo(prometheus.DefaultRegisterer, "auth")
959962 err := http.ListenAndServe(portStr, mux)
960963 if err != nil {
961964 logger.Info("http-serve", "err", err.Error())
+3, -0
......@@ -7,8 +7,10 @@ import (
77 "time"
88
99 "github.com/picosh/pico/pkg/db/postgres"
10+ "github.com/picosh/pico/pkg/metrics"
1011 "github.com/picosh/pico/pkg/shared"
1112 "github.com/picosh/pico/pkg/shared/router"
13+ "github.com/prometheus/client_golang/prometheus"
1214 "github.com/prometheus/client_golang/prometheus/promhttp"
1315 )
1416
......@@ -143,5 +145,6 @@ func StartApiServer() {
143145 "domain", cfg.Domain,
144146 )
145147
148+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "feeds")
146149 logger.Error(http.ListenAndServe(portStr, web.mux()).Error())
147150 }
+2, -0
......@@ -9,6 +9,7 @@ import (
99
1010 "github.com/picosh/pico/pkg/db"
1111 "github.com/picosh/pico/pkg/db/postgres"
12+ "github.com/picosh/pico/pkg/metrics"
1213 "github.com/picosh/pico/pkg/shared"
1314 "github.com/picosh/pico/pkg/shared/router"
1415 "github.com/prometheus/client_golang/prometheus"
......@@ -369,6 +370,7 @@ func StartApiServer() {
369370 web := &webRouter{cfg: cfg, db: db}
370371 handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux())
371372 handler = router.NewUserMetrics("pastes", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler)
373+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pastes")
372374
373375 portStr := fmt.Sprintf(":%s", cfg.Port)
374376 logger.Info(
+2, -0
......@@ -18,6 +18,7 @@ import (
1818 "github.com/hashicorp/golang-lru/v2/expirable"
1919 "github.com/picosh/pico/pkg/db"
2020 "github.com/picosh/pico/pkg/httpcache"
21+ "github.com/picosh/pico/pkg/metrics"
2122 "github.com/picosh/pico/pkg/shared"
2223 "github.com/picosh/pico/pkg/shared/router"
2324 "github.com/picosh/pico/pkg/storage"
......@@ -166,6 +167,7 @@ func StartApiServer(cfg *Config) {
166167 "port", cfg.WebPort,
167168 "domain", cfg.Domain,
168169 )
170+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pgs")
169171 err := http.ListenAndServe(portStr, NewSiteMetrics(cfg, "pgs", false).Handler(httpCache))
170172 cfg.Logger.Error(
171173 "listen and serve",
+2, -0
......@@ -16,6 +16,7 @@ import (
1616
1717 "github.com/gorilla/websocket"
1818 "github.com/picosh/pico/pkg/db/postgres"
19+ "github.com/picosh/pico/pkg/metrics"
1920 "github.com/picosh/pico/pkg/shared"
2021 "github.com/picosh/pico/pkg/shared/router"
2122 "github.com/picosh/utils/pipe"
......@@ -514,6 +515,7 @@ func StartApiServer() {
514515 web := &webRouter{cfg: cfg, db: db, conn: newPipeConn(info)}
515516 handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux())
516517 handler = router.NewUserMetrics("pipe", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler)
518+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "pipe")
517519
518520 portStr := fmt.Sprintf(":%s", cfg.Port)
519521 logger.Info(
+2, -0
......@@ -16,6 +16,7 @@ import (
1616 "github.com/gorilla/feeds"
1717 "github.com/picosh/pico/pkg/db"
1818 "github.com/picosh/pico/pkg/db/postgres"
19+ "github.com/picosh/pico/pkg/metrics"
1920 "github.com/picosh/pico/pkg/shared"
2021 "github.com/picosh/pico/pkg/shared/router"
2122 "github.com/picosh/pico/pkg/storage"
......@@ -992,6 +993,7 @@ func StartApiServer() {
992993 web := &webRouter{cfg: cfg, db: dbpool, storage: st}
993994 handler := router.NewHostRouter(cfg.Domain, cfg.Space, web.mainMux(), web.sitesMux())
994995 handler = router.NewUserMetrics("prose", prometheus.DefaultRegisterer, router.UserMetricsOpts{}).Handler(handler)
996+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, "prose")
995997
996998 portStr := fmt.Sprintf(":%s", cfg.Port)
997999 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 (
2323
2424 "github.com/antoniomika/syncmap"
2525 "github.com/go-andiamo/splitter"
26+ "github.com/picosh/pico/pkg/metrics"
2627 "github.com/prometheus/client_golang/prometheus"
2728 "github.com/prometheus/client_golang/prometheus/promauto"
2829 "github.com/prometheus/client_golang/prometheus/promhttp"
......@@ -368,6 +369,8 @@ func (s *SSHServer) ListenAndServe() error {
368369 },
369370 }, []string{"command", "user"})
370371
372+ metrics.RegisterServerInfo(prometheus.DefaultRegisterer, s.Config.App)
373+
371374 // The handler reads the default registerer, so build it before the
372375 // listener is published rather than in the goroutine.
373376 mux := http.NewServeMux()