1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
12 "github.com/prometheus/client_golang/prometheus"
13 "github.com/prometheus/client_golang/prometheus/promhttp"
16 type observer interface{ Observe(float64) }
17 type setter interface{ Set(float64) }
20 reg *prometheus.Registry
21 statsGauges map[string]setter
22 observers map[string]observer
27 func newMetrics() *metrics {
29 reg: prometheus.NewRegistry(),
30 statsGauges: map[string]setter{},
31 observers: map[string]observer{},
35 func (m *metrics) DurationObserver(name, help string) observer {
38 if obs, ok := m.observers[name]; ok {
41 summary := prometheus.NewSummary(prometheus.SummaryOpts{
43 Subsystem: "keepbalance",
46 m.reg.MustRegister(summary)
47 m.observers[name] = summary
51 // UpdateStats updates prometheus metrics using the given
52 // balancerStats. It creates and registers the needed gauges on its
54 func (m *metrics) UpdateStats(s balancerStats) {
59 s2g := map[string]gauge{
60 "total": {s.current, "current backend storage usage"},
61 "garbage": {s.garbage, "garbage (unreferenced, old)"},
62 "transient": {s.unref, "transient (unreferenced, new)"},
63 "overreplicated": {s.overrep, "overreplicated"},
64 "underreplicated": {s.underrep, "underreplicated"},
65 "lost": {s.lost, "lost"},
67 m.setupOnce.Do(func() {
68 // Register gauge(s) for each balancerStats field.
69 addGauge := func(name, help string) {
70 g := prometheus.NewGauge(prometheus.GaugeOpts{
76 m.statsGauges[name] = g
78 for name, gauge := range s2g {
79 switch gauge.Value.(type) {
81 for _, sub := range []string{"blocks", "bytes", "replicas"} {
82 addGauge(name+"_"+sub, sub+" of "+gauge.Help)
85 addGauge(name, gauge.Help)
87 panic(fmt.Sprintf("bad gauge type %T", gauge.Value))
91 // Set gauges to values from s.
92 for name, gauge := range s2g {
93 switch val := gauge.Value.(type) {
95 m.statsGauges[name+"_blocks"].Set(float64(val.blocks))
96 m.statsGauges[name+"_bytes"].Set(float64(val.bytes))
97 m.statsGauges[name+"_replicas"].Set(float64(val.replicas))
99 m.statsGauges[name].Set(float64(val))
101 m.statsGauges[name].Set(float64(val))
103 panic(fmt.Sprintf("bad gauge type %T", gauge.Value))
108 func (m *metrics) Handler(log promhttp.Logger) http.Handler {
109 return promhttp.HandlerFor(m.reg, promhttp.HandlerOpts{