Files
tailscale/net/udprelay/metrics_test.go
T
Alex Valiushko 4b7585df77 net/udprelay: add tailscaled_peer_relay_endpoints gauge (#18265)
New gauge reflects endpoints state via labels:
- open, when both peers are connected and ready to talk, and
- connecting. when at least one peer hasn't connected yet.

Corresponding client metrics are logged as
- udprelay_endpoints_connecting
- udprelay_endpoints_open

Updates tailscale/corp#30820

Change-Id: Idb1baa90a38c97847e14f9b2390093262ad0ea23

Signed-off-by: Alex Valiushko <alexvaliushko@tailscale.com>
2026-01-21 21:55:37 -08:00

110 lines
3.4 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package udprelay
import (
"fmt"
"slices"
"testing"
qt "github.com/frankban/quicktest"
"tailscale.com/util/usermetric"
)
func TestMetricsLifecycle(t *testing.T) {
c := qt.New(t)
deregisterMetrics()
r := &usermetric.Registry{}
m := registerMetrics(r)
// Expect certain prom names registered.
have := r.MetricNames()
want := []string{
"tailscaled_peer_relay_forwarded_packets_total",
"tailscaled_peer_relay_forwarded_bytes_total",
"tailscaled_peer_relay_endpoints",
}
slices.Sort(have)
slices.Sort(want)
c.Assert(have, qt.CmpEquals(), want)
// Validate countForwarded.
m.countForwarded(true, true, 1, 1)
c.Assert(m.forwarded44Bytes.Value(), qt.Equals, int64(1))
c.Assert(m.forwarded44Packets.Value(), qt.Equals, int64(1))
c.Assert(cMetricForwarded44Bytes.Value(), qt.Equals, int64(1))
c.Assert(cMetricForwarded44Packets.Value(), qt.Equals, int64(1))
m.countForwarded(true, false, 2, 2)
c.Assert(m.forwarded46Bytes.Value(), qt.Equals, int64(2))
c.Assert(m.forwarded46Packets.Value(), qt.Equals, int64(2))
c.Assert(cMetricForwarded46Bytes.Value(), qt.Equals, int64(2))
c.Assert(cMetricForwarded46Packets.Value(), qt.Equals, int64(2))
m.countForwarded(false, true, 3, 3)
c.Assert(m.forwarded64Bytes.Value(), qt.Equals, int64(3))
c.Assert(m.forwarded64Packets.Value(), qt.Equals, int64(3))
c.Assert(cMetricForwarded64Bytes.Value(), qt.Equals, int64(3))
c.Assert(cMetricForwarded64Packets.Value(), qt.Equals, int64(3))
m.countForwarded(false, false, 4, 4)
c.Assert(m.forwarded66Bytes.Value(), qt.Equals, int64(4))
c.Assert(m.forwarded66Packets.Value(), qt.Equals, int64(4))
c.Assert(cMetricForwarded66Bytes.Value(), qt.Equals, int64(4))
c.Assert(cMetricForwarded66Packets.Value(), qt.Equals, int64(4))
// Validate client metrics deregistration.
m.updateEndpoint(endpointClosed, endpointOpen)
deregisterMetrics()
c.Check(cMetricForwarded44Bytes.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded44Packets.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded46Bytes.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded46Packets.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded64Bytes.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded64Packets.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded66Bytes.Value(), qt.Equals, int64(0))
c.Check(cMetricForwarded66Packets.Value(), qt.Equals, int64(0))
for k := range cMetricEndpoints {
c.Check(cMetricEndpoints[k].Value(), qt.Equals, int64(0))
}
}
func TestMetricsEndpointTransitions(t *testing.T) {
c := qt.New(t)
var states = []endpointState{
endpointClosed,
endpointConnecting,
endpointOpen,
}
for _, a := range states {
for _, b := range states {
t.Run(fmt.Sprintf("%s-%s", a, b), func(t *testing.T) {
deregisterMetrics()
r := &usermetric.Registry{}
m := registerMetrics(r)
m.updateEndpoint(a, b)
var wantA, wantB int64
switch {
case a == b:
wantA, wantB = 0, 0
case a == endpointClosed:
wantA, wantB = 0, 1
case b == endpointClosed:
wantA, wantB = -1, 0
default:
wantA, wantB = -1, 1
}
if a != endpointClosed {
c.Check(m.endpoints[a].Value(), qt.Equals, wantA)
c.Check(cMetricEndpoints[a].Value(), qt.Equals, wantA)
}
if b != endpointClosed {
c.Check(m.endpoints[b].Value(), qt.Equals, wantB)
c.Check(cMetricEndpoints[b].Value(), qt.Equals, wantB)
}
})
}
}
}