Files
coder/scaletest/workspaceupdates/config.go
T
Ethan 65ac6cb42a feat(scaletest): add runner for coder connect load gen (#19904)
Relates to https://github.com/coder/internal/issues/889.

This PR adds a scaletest runner that simulates a single Coder Connect client receiving workspace updates.

An instance of a workspace updates runner does the following:
- Creates a user, if a session token is not supplied.
- Attempts to repeatedly dial the Coder Connect endpoint, with a configurable (two minutes by default) timeout. 
- Once dialed successfully, waits for any other concurrently executing runners to also dial successfully, or timeout (using the barrier).
- Starts a configurable number of workspace builds.
- Waits for that many workspaces to be seen over the workspace updates stream (with a configurable timeout).

Exposes two prometheus metrics:
- `workspace_updates_latency_seconds` - `HistogramVec`. Labels = `{username, num_owned_workspaces, workspace_name}`
  - This is the time between starting a workspace build, and receiving both the corresponding workspace update.
- `workspace_updates_errors_total` - `NewCounterVec`. Labels = `{username, num_owned_workspaces, action}`
  - The number of times a specific action of the runner has failed, per user/client.
2025-09-30 17:28:58 +10:00

78 lines
2.1 KiB
Go

package workspaceupdates
import (
"sync"
"time"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/createusers"
"github.com/coder/coder/v2/scaletest/workspacebuild"
)
type Config struct {
// User is the configuration for the user to create.
User createusers.Config `json:"user"`
// Workspace is the configuration for the workspace to create. The workspace
// will be built using the new user.
//
// OrganizationID is ignored and set to the new user's organization ID.
Workspace workspacebuild.Config `json:"workspace"`
// WorkspaceCount is the number of workspaces to create.
WorkspaceCount int64 `json:"power_user_workspaces"`
// WorkspaceUpdatesTimeout is how long to wait for all expected workspace updates.
WorkspaceUpdatesTimeout time.Duration `json:"workspace_updates_timeout"`
// DialTimeout is how long to wait to successfully dial the Coder Connect
// endpoint.
DialTimeout time.Duration `json:"dial_timeout"`
Metrics *Metrics `json:"-"`
// DialBarrier is used to ensure all runners have dialed the Coder Connect
// endpoint before creating their workspace(s).
DialBarrier *sync.WaitGroup `json:"-"`
}
func (c Config) Validate() error {
if err := c.User.Validate(); err != nil {
return xerrors.Errorf("user config: %w", err)
}
c.Workspace.OrganizationID = c.User.OrganizationID
// This value will be overwritten during the test.
c.Workspace.UserID = codersdk.Me
if err := c.Workspace.Validate(); err != nil {
return xerrors.Errorf("workspace config: %w", err)
}
if c.Workspace.Request.Name != "" {
return xerrors.New("workspace name cannot be overridden")
}
if c.WorkspaceCount <= 0 {
return xerrors.New("workspace_count must be greater than 0")
}
if c.DialBarrier == nil {
return xerrors.New("dial barrier must be set")
}
if c.WorkspaceUpdatesTimeout <= 0 {
return xerrors.New("workspace_updates_timeout must be greater than 0")
}
if c.DialTimeout <= 0 {
return xerrors.New("dial_timeout must be greater than 0")
}
if c.Metrics == nil {
return xerrors.New("metrics must be set")
}
return nil
}