expose tailscaled_advertised_routes as a gauge

This commit is contained in:
Anton Tolchanov 2024-08-19 11:56:28 +01:00
parent 93277ea2f7
commit 2b01273124
3 changed files with 66 additions and 15 deletions

View File

@ -12,7 +12,6 @@
"encoding/base64"
"encoding/json"
"errors"
"expvar"
"fmt"
"io"
"log"
@ -119,11 +118,8 @@
"tailscale.com/wgengine/wgcfg/nmcfg"
)
var metricAdvertisedRoutes expvar.Int
func init() {
usermetric.Publish("tailscaled_advertised_routes", &metricAdvertisedRoutes)
}
var metricAdvertisedRoutes = usermetric.NewGauge(
"tailscaled_advertised_routes", "Number of routes advertised by tailscaled")
var controlDebugFlags = getControlDebugFlags()
@ -4633,11 +4629,13 @@ func (b *LocalBackend) applyPrefsToHostinfoLocked(hi *tailcfg.Hostinfo, prefs ip
hi.AllowsUpdate = envknob.AllowsRemoteUpdate() || prefs.AutoUpdate().Apply.EqualBool(true)
// count routes without exit node routes
var routes int64
for _, route := range hi.RoutableIPs {
if route.Bits() != 0 {
metricAdvertisedRoutes.Add(1)
routes++
}
}
metricAdvertisedRoutes.Set(float64(routes))
var sshHostKeys []string
if prefs.RunSSH() && envknob.CanSSHD() {

View File

@ -7,6 +7,8 @@
import (
"expvar"
"fmt"
"io"
"net/http"
"tailscale.com/metrics"
@ -33,14 +35,40 @@ func NewMultiLabelMap[T comparable](name string, promType, helpText string) *met
return m
}
// Publish declares a named exported variable. This should be called from a
// package's init function when it creates its Vars.
//
// Note that usermetric are not protected against duplicate
// metrics name. It is the caller's responsibility to ensure that
// the name is unique.
func Publish(name string, v expvar.Var) {
vars.Set(name, v)
// Gauge is a gauge metric with no labels.
type Gauge struct {
m *expvar.Float
help string
}
// NewGauge creates and register a new gauge metric with the given name and help text.
func NewGauge(name, help string) *Gauge {
m := &expvar.Float{}
vars.Set(name, m)
return &Gauge{m, help}
}
// Set sets the gauge to the given value.
func (g *Gauge) Set(v float64) {
g.m.Set(v)
}
// WritePrometheus writes the gauge metric in Prometheus format to the given writer.
// This satisfies the varz.PrometheusWriter interface.
func (g *Gauge) WritePrometheus(w io.Writer, name string) {
io.WriteString(w, "# TYPE ")
io.WriteString(w, name)
io.WriteString(w, " gauge\n")
if g.help != "" {
io.WriteString(w, "# HELP ")
io.WriteString(w, name)
io.WriteString(w, " ")
io.WriteString(w, g.help)
io.WriteString(w, "\n")
}
io.WriteString(w, name)
fmt.Fprintf(w, " %v\n", g.m.Value())
}
// Handler returns a varz.Handler that serves the userfacing expvar contained

View File

@ -0,0 +1,25 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package usermetric
import (
"bytes"
"testing"
)
func TestGauge(t *testing.T) {
g := NewGauge("test_gauge", "This is a test gauge")
g.Set(15)
var buf bytes.Buffer
g.WritePrometheus(&buf, "test_gauge")
const want = `# TYPE test_gauge gauge
# HELP test_gauge This is a test gauge
test_gauge 15
`
if got := buf.String(); got != want {
t.Errorf("got %q; want %q", got, want)
}
}