Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3cde6ae

Browse files
committed
fix: prebuilt workspace creation duration metric
1 parent7365da1 commit3cde6ae

File tree

3 files changed

+186
-96
lines changed

3 files changed

+186
-96
lines changed

‎coderd/provisionerdserver/metrics.go‎

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,14 @@ func (m *Metrics) Register(reg prometheus.Registerer) error {
100100
returnreg.Register(m.workspaceClaimTimings)
101101
}
102102

103-
func (fWorkspaceTimingFlags)count()int {
104-
count:=0
105-
iff.IsPrebuild {
106-
count++
107-
}
108-
iff.IsClaim {
109-
count++
110-
}
111-
iff.IsFirstBuild {
112-
count++
113-
}
114-
returncount
115-
}
116-
117-
// getWorkspaceTimingType returns the type of the workspace build:
118-
// - isPrebuild: if the workspace build corresponds to the creation of a prebuilt workspace
119-
// - isClaim: if the workspace build corresponds to the claim of a prebuilt workspace
120-
// - isWorkspaceFirstBuild: if the workspace build corresponds to the creation of a regular workspace
121-
// (not created from the prebuild pool)
103+
// getWorkspaceTimingType classifies a workspace build:
104+
// - PrebuildCreation: creation of a prebuilt workspace
105+
// - PrebuildClaim: claim of an existing prebuilt workspace
106+
// - WorkspaceCreation: first build of a regular (non-prebuilt) workspace
107+
//
108+
// Note: order matters. Creating a prebuilt workspace is also a first build
109+
// (IsPrebuild && IsFirstBuild). We check IsPrebuild before IsFirstBuild so
110+
// prebuilds take precedence. This is the only case where two flags can be true.
122111
funcgetWorkspaceTimingType(flagsWorkspaceTimingFlags)WorkspaceTimingType {
123112
switch {
124113
caseflags.IsPrebuild:
@@ -149,14 +138,6 @@ func (m *Metrics) UpdateWorkspaceTimingsMetrics(
149138
"isClaim",flags.IsClaim,
150139
"isWorkspaceFirstBuild",flags.IsFirstBuild)
151140

152-
ifflags.count()>1 {
153-
m.logger.Warn(ctx,"invalid workspace timing flags",
154-
"isPrebuild",flags.IsPrebuild,
155-
"isClaim",flags.IsClaim,
156-
"isWorkspaceFirstBuild",flags.IsFirstBuild)
157-
return
158-
}
159-
160141
workspaceTimingType:=getWorkspaceTimingType(flags)
161142
switchworkspaceTimingType {
162143
caseWorkspaceCreation:

‎enterprise/coderd/coderdenttest/coderdenttest.go‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"crypto/ed25519"
66
"crypto/rand"
77
"crypto/tls"
8+
"database/sql"
89
"io"
910
"net/http"
1011
"os/exec"
@@ -18,6 +19,9 @@ import (
1819
"github.com/stretchr/testify/assert"
1920
"github.com/stretchr/testify/require"
2021

22+
"github.com/coder/coder/v2/coderd/util/ptr"
23+
"github.com/coder/coder/v2/enterprise/coderd/prebuilds"
24+
2125
"cdr.dev/slog"
2226

2327
"github.com/coder/coder/v2/coderd/coderdtest"
@@ -446,3 +450,99 @@ func newExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
446450

447451
returncloser
448452
}
453+
454+
funcGetRunningPrebuilds(
455+
ctx context.Context,
456+
t*testing.T,
457+
db database.Store,
458+
prebuildInstancesint,
459+
) []database.GetRunningPrebuiltWorkspacesRow {
460+
t.Helper()
461+
462+
varrunningPrebuilds []database.GetRunningPrebuiltWorkspacesRow
463+
testutil.Eventually(ctx,t,func(context.Context)bool {
464+
rows,err:=db.GetRunningPrebuiltWorkspaces(ctx)
465+
iferr!=nil {
466+
returnfalse
467+
}
468+
469+
for_,row:=rangerows {
470+
runningPrebuilds=append(runningPrebuilds,row)
471+
472+
agents,err:=db.GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx,row.ID)
473+
iferr!=nil {
474+
returnfalse
475+
}
476+
477+
for_,agent:=rangeagents {
478+
err=db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
479+
ID:agent.ID,
480+
LifecycleState:database.WorkspaceAgentLifecycleStateReady,
481+
StartedAt: sql.NullTime{Time:time.Now().Add(time.Hour),Valid:true},
482+
ReadyAt: sql.NullTime{Time:time.Now().Add(-1*time.Hour),Valid:true},
483+
})
484+
iferr!=nil {
485+
returnfalse
486+
}
487+
}
488+
}
489+
490+
t.Logf("found %d running prebuilds so far, want %d",len(runningPrebuilds),prebuildInstances)
491+
returnlen(runningPrebuilds)==prebuildInstances
492+
},testutil.IntervalSlow,"prebuilds not running")
493+
494+
returnrunningPrebuilds
495+
}
496+
497+
funcRunReconciliationLoop(
498+
ctx context.Context,
499+
t*testing.T,
500+
db database.Store,
501+
reconciler*prebuilds.StoreReconciler,
502+
presets []codersdk.Preset,
503+
) {
504+
t.Helper()
505+
506+
state,err:=reconciler.SnapshotState(ctx,db)
507+
require.NoError(t,err)
508+
ps,err:=state.FilterByPreset(presets[0].ID)
509+
require.NoError(t,err)
510+
require.NotNil(t,ps)
511+
actions,err:=reconciler.CalculateActions(ctx,*ps)
512+
require.NoError(t,err)
513+
require.NotNil(t,actions)
514+
require.NoError(t,reconciler.ReconcilePreset(ctx,*ps))
515+
}
516+
517+
funcClaimPrebuild(
518+
ctx context.Context,
519+
t*testing.T,
520+
client*codersdk.Client,
521+
userClient*codersdk.Client,
522+
usernamestring,
523+
version codersdk.TemplateVersion,
524+
presetID uuid.UUID,
525+
autostartSchedule...string,
526+
) codersdk.Workspace {
527+
t.Helper()
528+
529+
varstartSchedulestring
530+
iflen(autostartSchedule)>0 {
531+
startSchedule=autostartSchedule[0]
532+
}
533+
534+
workspaceName:=strings.ReplaceAll(testutil.GetRandomName(t),"_","-")
535+
userWorkspace,err:=userClient.CreateUserWorkspace(ctx,username, codersdk.CreateWorkspaceRequest{
536+
TemplateVersionID:version.ID,
537+
Name:workspaceName,
538+
TemplateVersionPresetID:presetID,
539+
AutostartSchedule:ptr.Ref(startSchedule),
540+
})
541+
require.NoError(t,err)
542+
build:=coderdtest.AwaitWorkspaceBuildJobCompleted(t,userClient,userWorkspace.LatestBuild.ID)
543+
require.Equal(t,build.Job.Status,codersdk.ProvisionerJobSucceeded)
544+
workspace:=coderdtest.MustWorkspace(t,client,userWorkspace.ID)
545+
assert.Equal(t,codersdk.WorkspaceTransitionStart,workspace.LatestBuild.Transition)
546+
547+
returnworkspace
548+
}

‎enterprise/coderd/workspaces_test.go‎

Lines changed: 78 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,113 +2879,122 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) {
28792879
t.Parallel()
28802880

28812881
// Setup
2882-
log:=testutil.Logger(t)
2882+
clock:=quartz.NewMock(t)
2883+
ctx:=testutil.Context(t,testutil.WaitSuperLong)
2884+
db,pb:=dbtestutil.NewDB(t,dbtestutil.WithDumpOnFailure())
2885+
logger:=testutil.Logger(t)
28832886
reg:=prometheus.NewRegistry()
2884-
provisionerdserverMetrics:=provisionerdserver.NewMetrics(log)
2887+
provisionerdserverMetrics:=provisionerdserver.NewMetrics(logger)
28852888
err:=provisionerdserverMetrics.Register(reg)
28862889
require.NoError(t,err)
2887-
client,db,owner:=coderdenttest.NewWithDatabase(t,&coderdenttest.Options{
2890+
client,_,api,owner:=coderdenttest.NewWithAPI(t,&coderdenttest.Options{
28882891
Options:&coderdtest.Options{
2892+
Database:db,
2893+
Pubsub:pb,
28892894
IncludeProvisionerDaemon:true,
2895+
Clock:clock,
28902896
ProvisionerdServerMetrics:provisionerdserverMetrics,
28912897
},
2892-
LicenseOptions:&coderdenttest.LicenseOptions{
2893-
Features: license.Features{
2894-
codersdk.FeatureWorkspacePrebuilds:1,
2895-
},
2896-
},
28972898
})
28982899

2899-
// Given: a template and a template version with a preset without prebuild instances
2900-
presetNoPrebuildID:=uuid.New()
2901-
versionNoPrebuild:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,nil)
2902-
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,versionNoPrebuild.ID)
2903-
templateNoPrebuild:=coderdtest.CreateTemplate(t,client,owner.OrganizationID,versionNoPrebuild.ID)
2904-
presetNoPrebuild:=dbgen.Preset(t,db, database.InsertPresetParams{
2905-
ID:presetNoPrebuildID,
2906-
TemplateVersionID:versionNoPrebuild.ID,
2907-
})
2900+
// Setup Prebuild reconciler
2901+
cache:=files.New(prometheus.NewRegistry(),&coderdtest.FakeAuthorizer{})
2902+
reconciler:=prebuilds.NewStoreReconciler(
2903+
db,pb,cache,
2904+
codersdk.PrebuildsConfig{},
2905+
logger,
2906+
clock,
2907+
prometheus.NewRegistry(),
2908+
notifications.NewNoopEnqueuer(),
2909+
api.AGPL.BuildUsageChecker,
2910+
)
2911+
varclaimer agplprebuilds.Claimer=prebuilds.NewEnterpriseClaimer(db)
2912+
api.AGPL.PrebuildsClaimer.Store(&claimer)
2913+
2914+
organizationName,err:=client.Organization(ctx,owner.OrganizationID)
2915+
require.NoError(t,err)
2916+
userClient,user:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID,rbac.RoleMember())
29082917

2909-
// Given: a template and a template version with a preset with a prebuild instance
2910-
presetPrebuildID:=uuid.New()
2911-
versionPrebuild:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,nil)
2912-
_=coderdtest.AwaitTemplateVersionJobCompleted(t,client,versionPrebuild.ID)
2918+
// Setup template and template version with a preset with 1 prebuild instance
2919+
versionPrebuild:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,templateWithAgentAndPresetsWithPrebuilds(1))
2920+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,versionPrebuild.ID)
29132921
templatePrebuild:=coderdtest.CreateTemplate(t,client,owner.OrganizationID,versionPrebuild.ID)
2914-
presetPrebuild:=dbgen.Preset(t,db, database.InsertPresetParams{
2915-
ID:presetPrebuildID,
2916-
TemplateVersionID:versionPrebuild.ID,
2917-
DesiredInstances: sql.NullInt32{Int32:1,Valid:true},
2918-
})
2919-
// Given: a prebuild workspace
2920-
wb:=dbfake.WorkspaceBuild(t,db, database.WorkspaceTable{
2921-
OwnerID:database.PrebuildsSystemUserID,
2922-
TemplateID:templatePrebuild.ID,
2923-
}).Seed(database.WorkspaceBuild{
2924-
TemplateVersionID:versionPrebuild.ID,
2925-
TemplateVersionPresetID: uuid.NullUUID{
2926-
UUID:presetPrebuildID,
2927-
Valid:true,
2928-
},
2929-
}).WithAgent(func(agent []*proto.Agent) []*proto.Agent {
2930-
returnagent
2931-
}).Do()
2922+
presetsPrebuild,err:=client.TemplateVersionPresets(ctx,versionPrebuild.ID)
2923+
require.NoError(t,err)
2924+
require.Len(t,presetsPrebuild,1)
29322925

2933-
// Mark the prebuilt workspace's agent as ready so the prebuild can be claimed
2934-
// nolint:gocritic
2935-
ctx:=dbauthz.AsSystemRestricted(testutil.Context(t,testutil.WaitLong))
2936-
agent,err:=db.GetWorkspaceAgentAndLatestBuildByAuthToken(ctx,uuid.MustParse(wb.AgentToken))
2926+
// Setup template and template version with a preset without prebuild instances
2927+
versionNoPrebuild:=coderdtest.CreateTemplateVersion(t,client,owner.OrganizationID,templateWithAgentAndPresetsWithPrebuilds(0))
2928+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,versionNoPrebuild.ID)
2929+
templateNoPrebuild:=coderdtest.CreateTemplate(t,client,owner.OrganizationID,versionNoPrebuild.ID)
2930+
presetsNoPrebuild,err:=client.TemplateVersionPresets(ctx,versionNoPrebuild.ID)
29372931
require.NoError(t,err)
2938-
err=db.UpdateWorkspaceAgentLifecycleStateByID(ctx, database.UpdateWorkspaceAgentLifecycleStateByIDParams{
2939-
ID:agent.WorkspaceAgent.ID,
2940-
LifecycleState:database.WorkspaceAgentLifecycleStateReady,
2932+
require.Len(t,presetsNoPrebuild,1)
2933+
2934+
// Given: no histogram value for prebuilt workspaces creation
2935+
prebuildCreationMetric:=promhelp.MetricValue(t,reg,"coderd_workspace_creation_duration_seconds", prometheus.Labels{
2936+
"organization_name":organizationName.Name,
2937+
"template_name":templatePrebuild.Name,
2938+
"preset_name":presetsPrebuild[0].Name,
2939+
"type":"prebuild",
29412940
})
2942-
require.NoError(t,err)
2941+
require.Nil(t,prebuildCreationMetric)
29432942

2944-
organizationName,err:=client.Organization(ctx,owner.OrganizationID)
2945-
require.NoError(t,err)
2946-
user,err:=client.User(ctx,"testUser")
2947-
require.NoError(t,err)
2943+
// Given: reconciliation loop runs and starts prebuilt workspace
2944+
coderdenttest.RunReconciliationLoop(ctx,t,db,reconciler,presetsPrebuild)
2945+
runningPrebuilds:=coderdenttest.GetRunningPrebuilds(ctx,t,db,1)
2946+
require.Len(t,runningPrebuilds,1)
2947+
2948+
// Then: the histogram value for prebuilt workspace creation should be updated
2949+
prebuildCreationHistogram:=promhelp.HistogramValue(t,reg,"coderd_workspace_creation_duration_seconds", prometheus.Labels{
2950+
"organization_name":organizationName.Name,
2951+
"template_name":templatePrebuild.Name,
2952+
"preset_name":presetsPrebuild[0].Name,
2953+
"type":"prebuild",
2954+
})
2955+
require.NotNil(t,prebuildCreationHistogram)
2956+
require.Equal(t,uint64(1),prebuildCreationHistogram.GetSampleCount())
2957+
2958+
// Given: a running prebuilt workspace, ready to be claimed
2959+
prebuild:=coderdtest.MustWorkspace(t,client,runningPrebuilds[0].ID)
2960+
require.Equal(t,codersdk.WorkspaceTransitionStart,prebuild.LatestBuild.Transition)
2961+
require.Nil(t,prebuild.DormantAt)
2962+
require.Nil(t,prebuild.DeletingAt)
29482963

29492964
// Given: no histogram value for prebuilt workspaces claim
2950-
prebuiltWorkspaceHistogramMetric:=promhelp.MetricValue(t,reg,"coderd_prebuilt_workspace_claim_duration_seconds", prometheus.Labels{
2965+
prebuildClaimMetric:=promhelp.MetricValue(t,reg,"coderd_prebuilt_workspace_claim_duration_seconds", prometheus.Labels{
29512966
"organization_name":organizationName.Name,
29522967
"template_name":templatePrebuild.Name,
2953-
"preset_name":presetPrebuild.Name,
2968+
"preset_name":presetsPrebuild[0].Name,
29542969
})
2955-
require.Nil(t,prebuiltWorkspaceHistogramMetric)
2970+
require.Nil(t,prebuildClaimMetric)
29562971

29572972
// Given: the prebuilt workspace is claimed by a user
2958-
claimedWorkspace,err:=client.CreateUserWorkspace(ctx,user.ID.String(), codersdk.CreateWorkspaceRequest{
2959-
TemplateVersionID:versionPrebuild.ID,
2960-
TemplateVersionPresetID:presetPrebuildID,
2961-
Name:coderdtest.RandomUsername(t),
2962-
})
2963-
require.NoError(t,err)
2964-
coderdtest.AwaitWorkspaceBuildJobCompleted(t,client,claimedWorkspace.LatestBuild.ID)
2965-
require.Equal(t,wb.Workspace.ID,claimedWorkspace.ID)
2973+
workspace:=coderdenttest.ClaimPrebuild(ctx,t,client,userClient,user.Username,versionPrebuild,presetsPrebuild[0].ID)
2974+
require.Equal(t,prebuild.ID,workspace.ID)
29662975

29672976
// Then: the histogram value for prebuilt workspace claim should be updated
2968-
prebuiltWorkspaceHistogram:=promhelp.HistogramValue(t,reg,"coderd_prebuilt_workspace_claim_duration_seconds", prometheus.Labels{
2977+
prebuildClaimHistogram:=promhelp.HistogramValue(t,reg,"coderd_prebuilt_workspace_claim_duration_seconds", prometheus.Labels{
29692978
"organization_name":organizationName.Name,
29702979
"template_name":templatePrebuild.Name,
2971-
"preset_name":presetPrebuild.Name,
2980+
"preset_name":presetsPrebuild[0].Name,
29722981
})
2973-
require.NotNil(t,prebuiltWorkspaceHistogram)
2974-
require.Equal(t,uint64(1),prebuiltWorkspaceHistogram.GetSampleCount())
2982+
require.NotNil(t,prebuildClaimHistogram)
2983+
require.Equal(t,uint64(1),prebuildClaimHistogram.GetSampleCount())
29752984

29762985
// Given: no histogram value for regular workspaces creation
29772986
regularWorkspaceHistogramMetric:=promhelp.MetricValue(t,reg,"coderd_workspace_creation_duration_seconds", prometheus.Labels{
29782987
"organization_name":organizationName.Name,
29792988
"template_name":templateNoPrebuild.Name,
2980-
"preset_name":presetNoPrebuild.Name,
2989+
"preset_name":presetsNoPrebuild[0].Name,
29812990
"type":"regular",
29822991
})
29832992
require.Nil(t,regularWorkspaceHistogramMetric)
29842993

29852994
// Given: a user creates a regular workspace (without prebuild pool)
29862995
regularWorkspace,err:=client.CreateUserWorkspace(ctx,user.ID.String(), codersdk.CreateWorkspaceRequest{
29872996
TemplateVersionID:versionNoPrebuild.ID,
2988-
TemplateVersionPresetID:presetNoPrebuildID,
2997+
TemplateVersionPresetID:presetsNoPrebuild[0].ID,
29892998
Name:coderdtest.RandomUsername(t),
29902999
})
29913000
require.NoError(t,err)
@@ -2995,7 +3004,7 @@ func TestWorkspaceProvisionerdServerMetrics(t *testing.T) {
29953004
regularWorkspaceHistogram:=promhelp.HistogramValue(t,reg,"coderd_workspace_creation_duration_seconds", prometheus.Labels{
29963005
"organization_name":organizationName.Name,
29973006
"template_name":templateNoPrebuild.Name,
2998-
"preset_name":presetNoPrebuild.Name,
3007+
"preset_name":presetsNoPrebuild[0].Name,
29993008
"type":"regular",
30003009
})
30013010
require.NotNil(t,regularWorkspaceHistogram)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp