From 219d02bdc3a24a24aa53ef6c6117048dce3d88ec Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 4 Mar 2026 22:30:36 -0500 Subject: [PATCH] fix(coderd): poll for metrics in TestWorkspaceProvisionerdServerMetrics (#22644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem `TestWorkspaceProvisionerdServerMetrics` flakes because metric assertions run immediately after `AwaitWorkspaceBuildJobCompleted` returns, but metrics are updated **asynchronously after the DB transaction commits** in `completeWorkspaceBuildJob`. The timeline in the provisioner server: 1. DB transaction commits (`provisionerdserver.go:~2362`) — job marked completed 2. Audit logging, notifications, DB queries (`~2370-2427`) 3. **Metric `.Observe()`** (`~2463`) — happens ~100 lines later The test synchronization (`AwaitWorkspaceBuildJobCompleted`) polls for `CompletedAt != nil`, which fires at step 1. The metric assertion then executes before step 3, causing the flake. ## Fix Wrap all three metric assertions (prebuild creation, prebuild claim, regular workspace creation) in `require.Eventually` to poll until the metric appears, then assert on the value. ## Test - `go test -run TestWorkspaceProvisionerdServerMetrics -count=5` — all pass - `go test -race -run TestWorkspaceProvisionerdServerMetrics -count=1` — clean --- enterprise/coderd/workspaces_test.go | 39 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index e40c0fa485..a5d2c70ded 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -3022,14 +3022,19 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) { runningPrebuilds := coderdenttest.GetRunningPrebuilds(ctx, t, db, 1) require.Len(t, runningPrebuilds, 1) - // Then: the histogram value for prebuilt workspace creation should be updated - prebuildCreationHistogram := promhelp.HistogramValue(t, reg, "coderd_workspace_creation_duration_seconds", prometheus.Labels{ + // Then: the histogram value for prebuilt workspace creation should be updated. + // The metric is updated asynchronously after the DB transaction commits, + // so we need to poll for it. + prebuildCreationLabels := prometheus.Labels{ "organization_name": organizationName.Name, "template_name": templatePrebuild.Name, "preset_name": presetsPrebuild[0].Name, "type": "prebuild", - }) - require.NotNil(t, prebuildCreationHistogram) + } + require.Eventually(t, func() bool { + return promhelp.MetricValue(t, reg, "coderd_workspace_creation_duration_seconds", prebuildCreationLabels) != nil + }, testutil.WaitShort, testutil.IntervalFast) + prebuildCreationHistogram := promhelp.HistogramValue(t, reg, "coderd_workspace_creation_duration_seconds", prebuildCreationLabels) require.Equal(t, uint64(1), prebuildCreationHistogram.GetSampleCount()) // Given: a running prebuilt workspace, ready to be claimed @@ -3050,13 +3055,18 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) { workspace := coderdenttest.MustClaimPrebuild(ctx, t, client, userClient, user.Username, versionPrebuild, presetsPrebuild[0].ID) require.Equal(t, prebuild.ID, workspace.ID) - // Then: the histogram value for prebuilt workspace claim should be updated - prebuildClaimHistogram := promhelp.HistogramValue(t, reg, "coderd_prebuilt_workspace_claim_duration_seconds", prometheus.Labels{ + // Then: the histogram value for prebuilt workspace claim should be updated. + // The metric is updated asynchronously after the DB transaction commits, + // so we need to poll for it. + prebuildClaimLabels := prometheus.Labels{ "organization_name": organizationName.Name, "template_name": templatePrebuild.Name, "preset_name": presetsPrebuild[0].Name, - }) - require.NotNil(t, prebuildClaimHistogram) + } + require.Eventually(t, func() bool { + return promhelp.MetricValue(t, reg, "coderd_prebuilt_workspace_claim_duration_seconds", prebuildClaimLabels) != nil + }, testutil.WaitShort, testutil.IntervalFast) + prebuildClaimHistogram := promhelp.HistogramValue(t, reg, "coderd_prebuilt_workspace_claim_duration_seconds", prebuildClaimLabels) require.Equal(t, uint64(1), prebuildClaimHistogram.GetSampleCount()) // Given: no histogram value for regular workspaces creation @@ -3077,14 +3087,19 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) { require.NoError(t, err) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, regularWorkspace.LatestBuild.ID) - // Then: the histogram value for regular workspace creation should be updated - regularWorkspaceHistogram := promhelp.HistogramValue(t, reg, "coderd_workspace_creation_duration_seconds", prometheus.Labels{ + // Then: the histogram value for regular workspace creation should be updated. + // The metric is updated asynchronously after the DB transaction commits, + // so we need to poll for it. + regularWorkspaceLabels := prometheus.Labels{ "organization_name": organizationName.Name, "template_name": templateNoPrebuild.Name, "preset_name": presetsNoPrebuild[0].Name, "type": "regular", - }) - require.NotNil(t, regularWorkspaceHistogram) + } + require.Eventually(t, func() bool { + return promhelp.MetricValue(t, reg, "coderd_workspace_creation_duration_seconds", regularWorkspaceLabels) != nil + }, testutil.WaitShort, testutil.IntervalFast) + regularWorkspaceHistogram := promhelp.HistogramValue(t, reg, "coderd_workspace_creation_duration_seconds", regularWorkspaceLabels) require.Equal(t, uint64(1), regularWorkspaceHistogram.GetSampleCount()) }