Skip to content

Commit e558993

Browse files
committed
tsnet: split bytes and routes metrics tests
Updates tailscale#13420 Signed-off-by: Kristoffer Dalby <[email protected]>
1 parent 06d929f commit e558993

File tree

1 file changed

+123
-61
lines changed

1 file changed

+123
-61
lines changed

tsnet/tsnet_test.go

Lines changed: 123 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -936,16 +936,136 @@ func sendData(logf func(format string, args ...any), ctx context.Context, bytesC
936936
return nil
937937
}
938938

939-
func TestUserMetrics(t *testing.T) {
939+
func TestUserMetricsByteCounters(t *testing.T) {
940940
flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/13420")
941941
tstest.ResourceCheck(t)
942942
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
943943
defer cancel()
944944

945-
controlURL, c := startControl(t)
946-
s1, s1ip, s1PubKey := startServer(t, ctx, controlURL, "s1")
945+
controlURL, _ := startControl(t)
946+
s1, s1ip, _ := startServer(t, ctx, controlURL, "s1")
947947
s2, s2ip, _ := startServer(t, ctx, controlURL, "s2")
948948

949+
lc1, err := s1.LocalClient()
950+
if err != nil {
951+
t.Fatal(err)
952+
}
953+
954+
lc2, err := s2.LocalClient()
955+
if err != nil {
956+
t.Fatal(err)
957+
}
958+
959+
// Force an update to the netmap to ensure that the metrics are up-to-date.
960+
s1.lb.DebugForceNetmapUpdate()
961+
s2.lb.DebugForceNetmapUpdate()
962+
963+
// Wait for both nodes to have a peer in their netmap.
964+
waitForCondition(t, "waiting for netmaps to contain peer", 90*time.Second, func() bool {
965+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
966+
defer cancel()
967+
status1, err := lc1.Status(ctx)
968+
if err != nil {
969+
t.Logf("getting status: %s", err)
970+
return false
971+
}
972+
status2, err := lc2.Status(ctx)
973+
if err != nil {
974+
t.Logf("getting status: %s", err)
975+
return false
976+
}
977+
return len(status1.Peers()) > 0 && len(status2.Peers()) > 0
978+
})
979+
980+
// ping to make sure the connection is up.
981+
res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
982+
if err != nil {
983+
t.Fatalf("pinging: %s", err)
984+
}
985+
t.Logf("ping success: %#+v", res)
986+
987+
mustDirect(t, t.Logf, lc1, lc2)
988+
989+
// 1 megabytes
990+
bytesToSend := 1 * 1024 * 1024
991+
992+
// This asserts generates some traffic, it is factored out
993+
// of TestUDPConn.
994+
start := time.Now()
995+
err = sendData(t.Logf, ctx, bytesToSend, s1, s2, s1ip, s2ip)
996+
if err != nil {
997+
t.Fatalf("Failed to send packets: %v", err)
998+
}
999+
t.Logf("Sent %d bytes from s1 to s2 in %s", bytesToSend, time.Since(start).String())
1000+
1001+
ctxLc, cancelLc := context.WithTimeout(context.Background(), 5*time.Second)
1002+
defer cancelLc()
1003+
metrics1, err := lc1.UserMetrics(ctxLc)
1004+
if err != nil {
1005+
t.Fatal(err)
1006+
}
1007+
1008+
parsedMetrics1, err := parseMetrics(metrics1)
1009+
if err != nil {
1010+
t.Fatal(err)
1011+
}
1012+
1013+
// Allow the metrics for the bytes sent to be off by 15%.
1014+
bytesSentTolerance := 1.15
1015+
1016+
t.Logf("Metrics1:\n%s\n", metrics1)
1017+
1018+
// Verify that the amount of data recorded in bytes is higher or equal to the data sent
1019+
inboundBytes1 := parsedMetrics1[`tailscaled_inbound_bytes_total{path="direct_ipv4"}`]
1020+
if inboundBytes1 < float64(bytesToSend) {
1021+
t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, inboundBytes1)
1022+
}
1023+
1024+
// But ensure that it is not too much higher than the data sent.
1025+
if inboundBytes1 > float64(bytesToSend)*bytesSentTolerance {
1026+
t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, inboundBytes1)
1027+
}
1028+
1029+
metrics2, err := lc2.UserMetrics(ctx)
1030+
if err != nil {
1031+
t.Fatal(err)
1032+
}
1033+
1034+
parsedMetrics2, err := parseMetrics(metrics2)
1035+
if err != nil {
1036+
t.Fatal(err)
1037+
}
1038+
1039+
t.Logf("Metrics2:\n%s\n", metrics2)
1040+
1041+
// Verify that the amount of data recorded in bytes is higher or equal than the data sent.
1042+
outboundBytes2 := parsedMetrics2[`tailscaled_outbound_bytes_total{path="direct_ipv4"}`]
1043+
if outboundBytes2 < float64(bytesToSend) {
1044+
t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, outboundBytes2)
1045+
}
1046+
1047+
// But ensure that it is not too much higher than the data sent.
1048+
if outboundBytes2 > float64(bytesToSend)*bytesSentTolerance {
1049+
t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, outboundBytes2)
1050+
}
1051+
}
1052+
1053+
func TestUserMetricsRouteGauges(t *testing.T) {
1054+
// Windows does not seem to support or report back routes when running in
1055+
// userspace via tsnet. So, we skip this check on Windows.
1056+
// TODO(kradalby): Figure out if this is correct.
1057+
if runtime.GOOS == "windows" {
1058+
t.Skipf("skipping on windows")
1059+
}
1060+
flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/13420")
1061+
tstest.ResourceCheck(t)
1062+
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
1063+
defer cancel()
1064+
1065+
controlURL, c := startControl(t)
1066+
s1, _, s1PubKey := startServer(t, ctx, controlURL, "s1")
1067+
s2, _, _ := startServer(t, ctx, controlURL, "s2")
1068+
9491069
s1.lb.EditPrefs(&ipn.MaskedPrefs{
9501070
Prefs: ipn.Prefs{
9511071
AdvertiseRoutes: []netip.Prefix{
@@ -973,24 +1093,11 @@ func TestUserMetrics(t *testing.T) {
9731093
t.Fatal(err)
9741094
}
9751095

976-
// ping to make sure the connection is up.
977-
res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
978-
if err != nil {
979-
t.Fatalf("pinging: %s", err)
980-
}
981-
t.Logf("ping success: %#+v", res)
982-
983-
ht := s1.lb.HealthTracker()
984-
ht.SetUnhealthy(testWarnable, health.Args{"Text": "Hello world 1"})
985-
9861096
// Force an update to the netmap to ensure that the metrics are up-to-date.
9871097
s1.lb.DebugForceNetmapUpdate()
9881098
s2.lb.DebugForceNetmapUpdate()
9891099

9901100
wantRoutes := float64(2)
991-
if runtime.GOOS == "windows" {
992-
wantRoutes = 0
993-
}
9941101

9951102
// Wait for the routes to be propagated to node 1 to ensure
9961103
// that the metrics are up-to-date.
@@ -1002,31 +1109,11 @@ func TestUserMetrics(t *testing.T) {
10021109
t.Logf("getting status: %s", err)
10031110
return false
10041111
}
1005-
if runtime.GOOS == "windows" {
1006-
// Windows does not seem to support or report back routes when running in
1007-
// userspace via tsnet. So, we skip this check on Windows.
1008-
// TODO(kradalby): Figure out if this is correct.
1009-
return true
1010-
}
10111112
// Wait for the primary routes to reach our desired routes, which is wantRoutes + 1, because
10121113
// the PrimaryRoutes list will contain a exit node route, which the metric does not count.
10131114
return status1.Self.PrimaryRoutes != nil && status1.Self.PrimaryRoutes.Len() == int(wantRoutes)+1
10141115
})
10151116

1016-
mustDirect(t, t.Logf, lc1, lc2)
1017-
1018-
// 1 megabytes
1019-
bytesToSend := 1 * 1024 * 1024
1020-
1021-
// This asserts generates some traffic, it is factored out
1022-
// of TestUDPConn.
1023-
start := time.Now()
1024-
err = sendData(t.Logf, ctx, bytesToSend, s1, s2, s1ip, s2ip)
1025-
if err != nil {
1026-
t.Fatalf("Failed to send packets: %v", err)
1027-
}
1028-
t.Logf("Sent %d bytes from s1 to s2 in %s", bytesToSend, time.Since(start).String())
1029-
10301117
ctxLc, cancelLc := context.WithTimeout(context.Background(), 5*time.Second)
10311118
defer cancelLc()
10321119
metrics1, err := lc1.UserMetrics(ctxLc)
@@ -1039,9 +1126,6 @@ func TestUserMetrics(t *testing.T) {
10391126
t.Fatal(err)
10401127
}
10411128

1042-
// Allow the metrics for the bytes sent to be off by 15%.
1043-
bytesSentTolerance := 1.15
1044-
10451129
t.Logf("Metrics1:\n%s\n", metrics1)
10461130

10471131
// The node is advertising 4 routes:
@@ -1059,17 +1143,6 @@ func TestUserMetrics(t *testing.T) {
10591143
t.Errorf("metrics1, tailscaled_approved_routes: got %v, want %v", got, want)
10601144
}
10611145

1062-
// Verify that the amount of data recorded in bytes is higher or equal to the data sent
1063-
inboundBytes1 := parsedMetrics1[`tailscaled_inbound_bytes_total{path="direct_ipv4"}`]
1064-
if inboundBytes1 < float64(bytesToSend) {
1065-
t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, inboundBytes1)
1066-
}
1067-
1068-
// But ensure that it is not too much higher than the data sent.
1069-
if inboundBytes1 > float64(bytesToSend)*bytesSentTolerance {
1070-
t.Errorf(`metrics1, tailscaled_inbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, inboundBytes1)
1071-
}
1072-
10731146
metrics2, err := lc2.UserMetrics(ctx)
10741147
if err != nil {
10751148
t.Fatal(err)
@@ -1091,17 +1164,6 @@ func TestUserMetrics(t *testing.T) {
10911164
if got, want := parsedMetrics2["tailscaled_approved_routes"], 0.0; got != want {
10921165
t.Errorf("metrics2, tailscaled_approved_routes: got %v, want %v", got, want)
10931166
}
1094-
1095-
// Verify that the amount of data recorded in bytes is higher or equal than the data sent.
1096-
outboundBytes2 := parsedMetrics2[`tailscaled_outbound_bytes_total{path="direct_ipv4"}`]
1097-
if outboundBytes2 < float64(bytesToSend) {
1098-
t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected higher (or equal) than %d, got: %f`, bytesToSend, outboundBytes2)
1099-
}
1100-
1101-
// But ensure that it is not too much higher than the data sent.
1102-
if outboundBytes2 > float64(bytesToSend)*bytesSentTolerance {
1103-
t.Errorf(`metrics2, tailscaled_outbound_bytes_total{path="direct_ipv4"}: expected lower than %f, got: %f`, float64(bytesToSend)*bytesSentTolerance, outboundBytes2)
1104-
}
11051167
}
11061168

11071169
func waitForCondition(t *testing.T, msg string, waitTime time.Duration, f func() bool) {

0 commit comments

Comments
 (0)