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

Commitf4bfcb6

Browse files
committed
review p1
1 parent556549b commitf4bfcb6

File tree

4 files changed

+75
-175
lines changed

4 files changed

+75
-175
lines changed

‎scaletest/coderconnect/config.go‎

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,16 @@ import (
44
"sync"
55
"time"
66

7-
"github.com/google/uuid"
87
"golang.org/x/xerrors"
98

109
"github.com/coder/coder/v2/codersdk"
10+
"github.com/coder/coder/v2/scaletest/createusers"
1111
"github.com/coder/coder/v2/scaletest/workspacebuild"
1212
)
1313

14-
typeUserConfigstruct {
15-
// OrganizationID is the ID of the organization to add the user to.
16-
OrganizationID uuid.UUID`json:"organization_id"`
17-
// Username is the username of the new user.
18-
Usernamestring`json:"username"`
19-
// Email is the email of the new user.
20-
Emailstring`json:"email"`
21-
// SessionToken is the session token of an already existing user. If set, no
22-
// user will be created.
23-
SessionTokenstring`json:"session_token"`
24-
}
25-
26-
func (cUserConfig)Validate()error {
27-
ifc.OrganizationID==uuid.Nil {
28-
returnxerrors.New("organization_id must not be a nil UUID")
29-
}
30-
ifc.SessionToken!="" {
31-
ifc.Username!="" {
32-
returnxerrors.New("username must be empty when session_token is set")
33-
}
34-
ifc.Email!="" {
35-
returnxerrors.New("email must be empty when session_token is set")
36-
}
37-
}
38-
39-
returnnil
40-
}
41-
4214
typeConfigstruct {
4315
// User is the configuration for the user to create or use.
44-
UserUserConfig`json:"user"`
16+
Usercreateusers.Config`json:"user"`
4517

4618
// Workspace is the configuration for the workspace to create. The workspace
4719
// will be built using the new user.
@@ -55,13 +27,10 @@ type Config struct {
5527
// WorkspaceUpdatesTimeout is how long to wait for all expected workspace updates.
5628
WorkspaceUpdatesTimeout time.Duration`json:"workspace_updates_timeout"`
5729

58-
// DialTimeout is how long to waitforthe Coder Connect endpoint to be
59-
//reachable.
30+
// DialTimeout is how long to waitto successfully dialthe Coder Connect
31+
//endpoint.
6032
DialTimeout time.Duration`json:"dial_timeout"`
6133

62-
// NoCleanup determines whether users and workspaces should be left after the test.
63-
NoCleanupbool`json:"no_cleanup"`
64-
6534
Metrics*Metrics`json:"-"`
6635

6736
// DialBarrier is used to ensure all runners have dialed the Coder Connect

‎scaletest/coderconnect/metrics.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ func NewMetrics(reg prometheus.Registerer) *Metrics {
2222
Subsystem:"scaletest",
2323
Name:"workspace_updates_latency_seconds",
2424
Help:"Time between starting a workspace build and receiving both the agent update and workspace update",
25-
}, []string{"username","owned_workspaces","workspace"}),
25+
}, []string{"username","num_owned_workspaces","workspace_name"}),
2626
WorkspaceUpdatesErrorsTotal:*prometheus.NewCounterVec(prometheus.CounterOpts{
2727
Namespace:"coderd",
2828
Subsystem:"scaletest",
2929
Name:"workspace_updates_errors_total",
3030
Help:"Total number of workspace updates errors",
31-
}, []string{"username","owned_workspaces","action"}),
31+
}, []string{"username","num_owned_workspaces","action"}),
3232
}
3333

3434
reg.MustRegister(m.WorkspaceUpdatesLatencySeconds)

‎scaletest/coderconnect/run.go‎

Lines changed: 44 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ import (
77
"net/http"
88
"time"
99

10-
"github.com/google/uuid"
1110
"golang.org/x/xerrors"
1211

1312
"github.com/coder/websocket"
1413

1514
"cdr.dev/slog"
1615
"cdr.dev/slog/sloggers/sloghuman"
1716
"github.com/coder/coder/v2/coderd/tracing"
18-
"github.com/coder/coder/v2/coderd/util/syncmap"
1917
"github.com/coder/coder/v2/codersdk"
2018
"github.com/coder/coder/v2/codersdk/workspacesdk"
2119
"github.com/coder/coder/v2/scaletest/createusers"
@@ -34,11 +32,10 @@ type Runner struct {
3432
workspacebuildRunners []*workspacebuild.Runner
3533

3634
// workspace name to workspace
37-
workspaces*syncmap.Map[string,*workspace]
35+
workspacesmap[string]*workspace
3836
}
3937

4038
typeworkspacestruct {
41-
workspaceID uuid.UUID
4239
buildStartTime time.Time
4340
updateLatency time.Duration
4441
}
@@ -53,7 +50,7 @@ func NewRunner(client *codersdk.Client, cfg Config) *Runner {
5350
return&Runner{
5451
client:client,
5552
cfg:cfg,
56-
workspaces:syncmap.New[string,*workspace](),
53+
workspaces:make(map[string]*workspace),
5754
}
5855
}
5956

@@ -73,62 +70,43 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
7370
r.client.SetLogger(logger)
7471
r.client.SetLogBodies(true)
7572

76-
var (
77-
client=r.client
78-
user codersdk.User
79-
errerror
80-
)
81-
ifr.cfg.User.SessionToken!="" {
82-
user,err=client.User(ctx,"me")
83-
iferr!=nil {
84-
returnxerrors.Errorf("get user with session token: %w",err)
85-
}
86-
}else {
87-
createUserConfig:= createusers.Config{
88-
OrganizationID:r.cfg.User.OrganizationID,
89-
Username:r.cfg.User.Username,
90-
Email:r.cfg.User.Email,
91-
}
92-
iferr:=createUserConfig.Validate();err!=nil {
93-
returnxerrors.Errorf("validate create user config: %w",err)
94-
}
95-
r.createUserRunner=createusers.NewRunner(r.client,createUserConfig)
96-
newUser,err:=r.createUserRunner.RunReturningUser(ctx,id,logs)
97-
iferr!=nil {
98-
returnxerrors.Errorf("create user: %w",err)
99-
}
100-
user=newUser.User
101-
client=codersdk.New(r.client.URL)
102-
client.SetSessionToken(newUser.SessionToken)
103-
client.SetLogger(logger)
104-
client.SetLogBodies(true)
73+
r.createUserRunner=createusers.NewRunner(r.client,r.cfg.User)
74+
newUser,err:=r.createUserRunner.RunReturningUser(ctx,id,logs)
75+
iferr!=nil {
76+
returnxerrors.Errorf("create user: %w",err)
10577
}
78+
user:=newUser.User
79+
client:=codersdk.New(r.client.URL,
80+
codersdk.WithSessionToken(newUser.SessionToken),
81+
codersdk.WithLogger(logger),
82+
codersdk.WithLogBodies())
10683

107-
_,_=fmt.Fprintf(logs,"Usinguser %q(id: %s)\n",user.Username,user.ID)
84+
logger.Info(ctx,fmt.Sprintf("user %qcreated",user.Username),slog.F("id",user.ID.String()))
10885

10986
dialCtx,cancel:=context.WithTimeout(ctx,r.cfg.DialTimeout)
11087
defercancel()
11188

112-
_,_=fmt.Fprintf(logs,"Connecting to workspace updates stream for user %s\n",user.Username)
89+
logger.Info(ctx,"connecting to workspace updates stream")
11390
clients,err:=r.dialCoderConnect(dialCtx,client,user,logger)
11491
iferr!=nil {
11592
returnxerrors.Errorf("coder connect dial failed: %w",err)
11693
}
117-
_,_=fmt.Fprintf(logs,"Successfully connected to workspace updates stream\n")
94+
logger.Info(ctx,"connected to workspace updates stream")
95+
deferclients.Closer.Close()
11896

11997
watchCtx,cancelWatch:=context.WithCancel(ctx)
12098
defercancelWatch()
12199

122100
completionCh:=make(chanerror,1)
123101
gofunc() {
124-
completionCh<-r.watchWorkspaceUpdates(watchCtx,clients,user,logs)
102+
completionCh<-r.watchWorkspaceUpdates(watchCtx,clients,user,logger)
125103
}()
126104

127105
reachedBarrier=true
128106
r.cfg.DialBarrier.Done()
129107
r.cfg.DialBarrier.Wait()
130108

131-
workspaceRunners:=make([]*workspacebuild.Runner,0,r.cfg.WorkspaceCount)
109+
r.workspacebuildRunners=make([]*workspacebuild.Runner,0,r.cfg.WorkspaceCount)
132110
fori:=ranger.cfg.WorkspaceCount {
133111
workspaceName,err:=loadtestutil.GenerateWorkspaceName(id)
134112
iferr!=nil {
@@ -140,23 +118,21 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
140118
workspaceBuildConfig.Request.Name=workspaceName
141119

142120
runner:=workspacebuild.NewRunner(client,workspaceBuildConfig)
143-
workspaceRunners=append(workspaceRunners,runner)
121+
r.workspacebuildRunners=append(r.workspacebuildRunners,runner)
144122

145-
_,_=fmt.Fprintf(logs,"Creating workspace %d/%d...\n",i+1,r.cfg.WorkspaceCount)
123+
logger.Info(ctx,fmt.Sprintf("creating workspace %d/%d",i+1,r.cfg.WorkspaceCount))
146124

147125
// Record build start time before running the workspace build
148-
r.workspaces.Store(workspaceName,&workspace{
126+
r.workspaces[workspaceName]=&workspace{
149127
buildStartTime:time.Now(),
150-
})
128+
}
151129
err=runner.Run(ctx,fmt.Sprintf("%s-%d",id,i),logs)
152130
iferr!=nil {
153131
returnxerrors.Errorf("create workspace %d: %w",i,err)
154132
}
155133
}
156134

157-
r.workspacebuildRunners=workspaceRunners
158-
159-
_,_=fmt.Fprintf(logs,"Waiting up to %v for workspace updates to complete...\n",r.cfg.WorkspaceUpdatesTimeout)
135+
logger.Info(ctx,fmt.Sprintf("waiting up to %v for workspace updates to complete...",r.cfg.WorkspaceUpdatesTimeout))
160136

161137
waitUpdatesCtx,cancel:=context.WithTimeout(ctx,r.cfg.WorkspaceUpdatesTimeout)
162138
defercancel()
@@ -166,7 +142,7 @@ func (r *Runner) Run(ctx context.Context, id string, logs io.Writer) error {
166142
iferr!=nil {
167143
returnxerrors.Errorf("workspace updates streaming failed: %w",err)
168144
}
169-
_,_=fmt.Fprintf(logs,"Workspace updates streaming completed successfully\n")
145+
logger.Info(ctx,"workspace updates streaming completed successfully")
170146
returnnil
171147
case<-waitUpdatesCtx.Done():
172148
ifwaitUpdatesCtx.Err()==context.DeadlineExceeded {
@@ -209,114 +185,65 @@ func (r *Runner) dialCoderConnect(ctx context.Context, client *codersdk.Client,
209185

210186
// watchWorkspaceUpdates processes workspace updates and returns error or nil
211187
// once all expected workspaces and agents are seen.
212-
func (r*Runner)watchWorkspaceUpdates(ctx context.Context,clients*tailnet.ControlProtocolClients,user codersdk.User,logs io.Writer)error {
213-
deferclients.Closer.Close()
214-
188+
func (r*Runner)watchWorkspaceUpdates(ctx context.Context,clients*tailnet.ControlProtocolClients,user codersdk.User,logger slog.Logger)error {
215189
expectedWorkspaces:=r.cfg.WorkspaceCount
216-
seenWorkspaces:=0
217-
// Workspace ID to agent update arrival time.
218-
// At the end, we reconcile to see which took longer, and mark that as the
219-
// latency.
220-
agents:=make(map[uuid.UUID]time.Time)
190+
// workspace name to time the update was seen
191+
seenWorkspaces:=make(map[string]time.Time)
221192

222-
_,_=fmt.Fprintf(logs,"Waiting for %d workspaces and their agents\n",expectedWorkspaces)
193+
logger.Info(ctx,fmt.Sprintf("waiting for %d workspaces and their agents",expectedWorkspaces))
223194
for {
224195
select {
225196
case<-ctx.Done():
226-
_,_=fmt.Fprintf(logs,"Context canceled while waiting for workspace updates: %v\n",ctx.Err())
197+
logger.Error(ctx,"context canceled while waiting for workspace updates",slog.Error(ctx.Err()))
227198
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"context_done")
228199
returnctx.Err()
229200
default:
230201
}
231202

232203
update,err:=clients.WorkspaceUpdates.Recv()
233204
iferr!=nil {
234-
_,_=fmt.Fprintf(logs,"Workspace updates stream error: %v\n",err)
205+
logger.Error(ctx,"workspace updates stream error",slog.Error(err))
235206
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"recv")
236207
returnxerrors.Errorf("receive workspace update: %w",err)
237208
}
209+
recvTime:=time.Now()
238210

239211
for_,ws:=rangeupdate.UpsertedWorkspaces {
240-
wsID,err:=uuid.FromBytes(ws.Id)
241-
iferr!=nil {
242-
_,_=fmt.Fprintf(logs,"Invalid workspace ID in update: %v\n",err)
243-
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"bad_workspace_id")
244-
continue
245-
}
246-
247-
iftracking,ok:=r.workspaces.Load(ws.GetName());ok {
248-
iftracking.updateLatency==0 {
249-
r.workspaces.Store(ws.GetName(),&workspace{
250-
workspaceID:wsID,
251-
buildStartTime:tracking.buildStartTime,
252-
updateLatency:time.Since(tracking.buildStartTime),
253-
})
254-
seenWorkspaces++
255-
}
256-
}elseif!ok {
257-
returnxerrors.Errorf("received update for unknown workspace %q (id: %s)",ws.GetName(),wsID)
258-
}
212+
seenWorkspaces[ws.Name]=recvTime
259213
}
260214

261-
for_,agent:=rangeupdate.UpsertedAgents {
262-
wsID,err:=uuid.FromBytes(agent.WorkspaceId)
263-
iferr!=nil {
264-
_,_=fmt.Fprintf(logs,"Invalid workspace ID in agent update: %v\n",err)
265-
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"bad_agent_workspace_id")
266-
continue
267-
}
268-
269-
if_,ok:=agents[wsID];!ok {
270-
agents[wsID]=time.Now()
271-
}
272-
}
273-
274-
ifseenWorkspaces==int(expectedWorkspaces)&&len(agents)==int(expectedWorkspaces) {
275-
// For each workspace, record the latency from build start to
276-
// workspace update, or agent update, whichever is later.
277-
r.workspaces.Range(func(wsNamestring,ws*workspace)bool {
278-
ifagentTime,ok:=agents[ws.workspaceID];ok {
279-
agentLatency:=agentTime.Sub(ws.buildStartTime)
280-
ifagentLatency>ws.updateLatency {
281-
// Update in-place, so GetMetrics is accurate.
282-
ws.updateLatency=agentLatency
283-
}
284-
}else {
285-
// Unreachable, recorded for debugging
286-
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"missing_agent")
215+
iflen(seenWorkspaces)==int(expectedWorkspaces) {
216+
forwsName,seenTime:=rangeseenWorkspaces {
217+
ws,ok:=r.workspaces[wsName]
218+
if!ok {
219+
logger.Error(ctx,"received update for unexpected workspace",slog.F("workspace",wsName),slog.F("seen_workspaces",seenWorkspaces))
220+
r.cfg.Metrics.AddError(user.Username,r.cfg.WorkspaceCount,"unexpected_workspace")
221+
returnxerrors.Errorf("received update for unexpected workspace %q",wsName)
287222
}
223+
ws.updateLatency=seenTime.Sub(ws.buildStartTime)
288224
r.cfg.Metrics.RecordCompletion(ws.updateLatency,user.Username,r.cfg.WorkspaceCount,wsName)
289-
returntrue
290-
})
291-
_,_=fmt.Fprintf(logs,"Updates received for all %d workspaces and agents\n",expectedWorkspaces)
225+
}
226+
logger.Info(ctx,fmt.Sprintf("updates received for all %d workspaces and agents",expectedWorkspaces))
292227
returnnil
293228
}
294229
}
295230
}
296231

297232
const (
298233
WorkspaceUpdatesLatencyMetric="workspace_updates_latency_seconds"
299-
WorkspaceUpdatesErrorsTotal="workspace_updates_errors_total"
300234
)
301235

302236
func (r*Runner)GetMetrics()map[string]any {
303237
latencyMap:=make(map[string]float64)
304-
r.workspaces.Range(func(wsNamestring,ws*workspace)bool {
238+
forwsName,ws:=ranger.workspaces {
305239
latencyMap[wsName]=ws.updateLatency.Seconds()
306-
returntrue
307-
})
240+
}
308241
returnmap[string]any{
309-
WorkspaceUpdatesErrorsTotal:r.cfg.Metrics.numErrors.Load(),
310242
WorkspaceUpdatesLatencyMetric:latencyMap,
311243
}
312244
}
313245

314246
func (r*Runner)Cleanup(ctx context.Context,idstring,logs io.Writer)error {
315-
ifr.cfg.NoCleanup {
316-
_,_=fmt.Fprintln(logs,"skipping cleanup")
317-
returnnil
318-
}
319-
320247
fori,runner:=ranger.workspacebuildRunners {
321248
ifrunner!=nil {
322249
_,_=fmt.Fprintf(logs,"Cleaning up workspace %d/%d...\n",i+1,len(r.workspacebuildRunners))
@@ -327,6 +254,7 @@ func (r *Runner) Cleanup(ctx context.Context, id string, logs io.Writer) error {
327254
}
328255

329256
ifr.createUserRunner!=nil {
257+
_,_=fmt.Fprintln(logs,"Cleaning up user...")
330258
iferr:=r.createUserRunner.Cleanup(ctx,id,logs);err!=nil {
331259
returnxerrors.Errorf("cleanup user: %w",err)
332260
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp