From 9e181b81dc00b344f7161e982b414c699905735f Mon Sep 17 00:00:00 2001 From: cabbage Date: Fri, 11 Sep 2026 09:43:24 +0000 Subject: [PATCH] test: cover daemon telemetry publication --- cmd/rvbox-server/main.go | 25 ++++++++++++++++--------- cmd/rvbox-server/main_test.go | 34 ++++++++++++++++++++++++++++++++++ cmd/rvbox/main.go | 25 ++++++++++++++++--------- cmd/rvbox/main_test.go | 28 ++++++++++++++++++++++++++++ test/coverage.toml | 18 ++++++++++++++++++ 5 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 cmd/rvbox-server/main_test.go diff --git a/cmd/rvbox-server/main.go b/cmd/rvbox-server/main.go index a46b489..64a046b 100644 --- a/cmd/rvbox-server/main.go +++ b/cmd/rvbox-server/main.go @@ -245,15 +245,7 @@ func publishServerTelemetry(ctx context.Context, persistence *store.Store, healt ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for { - sampleContext, cancel := context.WithTimeout(ctx, time.Second) - telemetry, err := persistence.Telemetry(sampleContext) - cancel() - if err != nil { - health.Inc("telemetry_read_failure") - } else { - health.SetGauge("queue_depth", float64(telemetry.QueuedCommands)) - health.SetGauge("server_charged_bytes", float64(telemetry.ChargedBytes)) - } + publishServerTelemetrySample(ctx, persistence.Telemetry, health) select { case <-ctx.Done(): return @@ -261,3 +253,18 @@ func publishServerTelemetry(ctx context.Context, persistence *store.Store, healt } } } + +// publishServerTelemetrySample performs one intentionally bounded, best-effort +// telemetry read. A failed metrics read must never affect server readiness or +// durable command processing. +func publishServerTelemetrySample(ctx context.Context, read func(context.Context) (store.Telemetry, error), health *observability.Health) { + sampleContext, cancel := context.WithTimeout(ctx, time.Second) + telemetry, err := read(sampleContext) + cancel() + if err != nil { + health.Inc("telemetry_read_failure") + return + } + health.SetGauge("queue_depth", float64(telemetry.QueuedCommands)) + health.SetGauge("server_charged_bytes", float64(telemetry.ChargedBytes)) +} diff --git a/cmd/rvbox-server/main_test.go b/cmd/rvbox-server/main_test.go new file mode 100644 index 0000000..8a63b7a --- /dev/null +++ b/cmd/rvbox-server/main_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "context" + "errors" + "testing" + + "github.com/rvbox/rvbox/internal/observability" + "github.com/rvbox/rvbox/internal/server/store" +) + +func TestPublishServerTelemetrySample_HP_OPS_07(t *testing.T) { + t.Parallel() + health := observability.New() + publishServerTelemetrySample(context.Background(), func(context.Context) (store.Telemetry, error) { + return store.Telemetry{QueuedCommands: 3, ChargedBytes: 4096}, nil + }, health) + snapshot := health.MetricsSnapshot() + if snapshot.Gauges["queue_depth"] != 3 || snapshot.Gauges["server_charged_bytes"] != 4096 { + t.Fatalf("server telemetry gauges = %#v", snapshot.Gauges) + } +} + +func TestPublishServerTelemetrySampleFailure_BH_OPS_04(t *testing.T) { + t.Parallel() + health := observability.New() + publishServerTelemetrySample(context.Background(), func(context.Context) (store.Telemetry, error) { + return store.Telemetry{}, errors.New("store unavailable") + }, health) + _, _, counters := health.Snapshot() + if counters["telemetry_read_failure"] != 1 { + t.Fatalf("telemetry failure counters = %#v", counters) + } +} diff --git a/cmd/rvbox/main.go b/cmd/rvbox/main.go index a03e154..1e33953 100644 --- a/cmd/rvbox/main.go +++ b/cmd/rvbox/main.go @@ -255,15 +255,7 @@ func publishClientTelemetry(ctx context.Context, state *spool.Store, health *obs ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for { - sampleContext, cancel := context.WithTimeout(ctx, time.Second) - telemetry, err := state.Telemetry(sampleContext) - cancel() - if err != nil { - health.Inc("telemetry_read_failure") - } else { - health.SetGauge("queue_depth", float64(telemetry.QueuedCommands)) - health.SetGauge("client_spool_bytes", float64(telemetry.ChargedBytes)) - } + publishClientTelemetrySample(ctx, state.Telemetry, health) select { case <-ctx.Done(): return @@ -272,6 +264,21 @@ func publishClientTelemetry(ctx context.Context, state *spool.Store, health *obs } } +// publishClientTelemetrySample performs one intentionally bounded, best-effort +// telemetry read. An unavailable spool metric must not interrupt reconnect or +// command supervision. +func publishClientTelemetrySample(ctx context.Context, read func(context.Context) (spool.Telemetry, error), health *observability.Health) { + sampleContext, cancel := context.WithTimeout(ctx, time.Second) + telemetry, err := read(sampleContext) + cancel() + if err != nil { + health.Inc("telemetry_read_failure") + return + } + health.SetGauge("queue_depth", float64(telemetry.QueuedCommands)) + health.SetGauge("client_spool_bytes", float64(telemetry.ChargedBytes)) +} + func clientJobProfiles(profiles config.Profiles) map[string]clientwindows.JobProfile { return map[string]clientwindows.JobProfile{ rvboxv1.ExecutionProfile_EXECUTION_PROFILE_LIGHT.String(): toJobProfile(profiles.Light), diff --git a/cmd/rvbox/main_test.go b/cmd/rvbox/main_test.go index ab86c92..352239d 100644 --- a/cmd/rvbox/main_test.go +++ b/cmd/rvbox/main_test.go @@ -2,11 +2,15 @@ package main import ( "bytes" + "context" + "errors" "net/http" "net/http/httptest" "testing" + "github.com/rvbox/rvbox/internal/client/spool" "github.com/rvbox/rvbox/internal/config" + "github.com/rvbox/rvbox/internal/observability" ) func TestClientModeSelectionRequiresExactlyOneMode_HP_WINCLI_01(t *testing.T) { @@ -77,3 +81,27 @@ func TestNonWindowsServiceModesRemainExplicitlyUnsupported_BH_WINCLI_01(t *testi t.Fatal("non-Windows tray mode unexpectedly available") } } + +func TestPublishClientTelemetrySample_HP_OPS_07(t *testing.T) { + t.Parallel() + health := observability.New() + publishClientTelemetrySample(context.Background(), func(context.Context) (spool.Telemetry, error) { + return spool.Telemetry{QueuedCommands: 2, ChargedBytes: 2048}, nil + }, health) + snapshot := health.MetricsSnapshot() + if snapshot.Gauges["queue_depth"] != 2 || snapshot.Gauges["client_spool_bytes"] != 2048 { + t.Fatalf("client telemetry gauges = %#v", snapshot.Gauges) + } +} + +func TestPublishClientTelemetrySampleFailure_BH_OPS_04(t *testing.T) { + t.Parallel() + health := observability.New() + publishClientTelemetrySample(context.Background(), func(context.Context) (spool.Telemetry, error) { + return spool.Telemetry{}, errors.New("spool unavailable") + }, health) + _, _, counters := health.Snapshot() + if counters["telemetry_read_failure"] != 1 { + t.Fatalf("telemetry failure counters = %#v", counters) + } +} diff --git a/test/coverage.toml b/test/coverage.toml index 546b0f1..4ac9504 100644 --- a/test/coverage.toml +++ b/test/coverage.toml @@ -656,6 +656,24 @@ tests = [ "internal/client/spool/telemetry_test.go:TestTelemetryReportsQueuedDurableSpool_HP_OPS_07", ] +[[requirements]] +id = "HP-OPS-07" +layer = "unit" +status = "implemented" +tests = [ + "cmd/rvbox-server/main_test.go:TestPublishServerTelemetrySample_HP_OPS_07", + "cmd/rvbox/main_test.go:TestPublishClientTelemetrySample_HP_OPS_07", +] + +[[requirements]] +id = "BH-OPS-04" +layer = "unit" +status = "implemented" +tests = [ + "cmd/rvbox-server/main_test.go:TestPublishServerTelemetrySampleFailure_BH_OPS_04", + "cmd/rvbox/main_test.go:TestPublishClientTelemetrySampleFailure_BH_OPS_04", +] + [[requirements]] id = "HP-DISPATCH-10" layer = "unit"