Documentation
¶
Overview ¶
Package agent runs one host's share of a distributed load test.
An agent is a supervisor, not a load generator. It joins the coordinator, spawns worker processes on its host, subdivides the quota it was given across them, and relays their telemetry upward. Keeping supervision out of the processes that generate load is what allows a worker to be killed, crash, or be starved of CPU without taking the host's participation in the run down with it.
Index ¶
- Constants
- type Agent
- func (a *Agent) OnAccepted(_ context.Context, msg *loadwavev1.Accepted) error
- func (a *Agent) OnHeartbeat(session *control.Session, beat *loadwavev1.NodeHeartbeat)
- func (a *Agent) OnJoin(_ context.Context, session *control.Session) error
- func (a *Agent) OnLeave(session *control.Session)
- func (a *Agent) OnLog(_ *control.Session, event *loadwavev1.LogEvent)
- func (a *Agent) OnMetrics(_ *control.Session, batch *loadwavev1.MetricBatch)
- func (a *Agent) OnRunStatus(session *control.Session, update *loadwavev1.RunStatusUpdate)
- func (a *Agent) OnSetQuota(_ context.Context, msg *loadwavev1.SetQuota) error
- func (a *Agent) OnStartRun(_ context.Context, msg *loadwavev1.StartRun) error
- func (a *Agent) OnStopRun(_ context.Context, msg *loadwavev1.StopRun) error
- func (a *Agent) Run(ctx context.Context) error
- func (a *Agent) SocketPath() string
- type Config
Constants ¶
const ( // DefaultVUsPerCore is the advertised capacity per core. Virtual users // are goroutines blocked on network I/O for most of their lives, so a // core carries far more of them than it could carry busy threads. DefaultVUsPerCore = 1000 )
Defaults for a zero Config.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent supervises one host's worker processes.
func (*Agent) OnAccepted ¶
OnAccepted implements control.Handler.
func (*Agent) OnHeartbeat ¶
func (a *Agent) OnHeartbeat(session *control.Session, beat *loadwavev1.NodeHeartbeat)
OnHeartbeat implements control.SessionHandler.
Each worker's VU count is kept separately and summed, rather than accumulated into a running total. A worker that dies between heartbeats simply stops contributing at the next recount, where an incremental total would keep its VUs on the books forever.
func (*Agent) OnLog ¶
func (a *Agent) OnLog(_ *control.Session, event *loadwavev1.LogEvent)
OnLog implements control.SessionHandler.
func (*Agent) OnMetrics ¶
func (a *Agent) OnMetrics(_ *control.Session, batch *loadwavev1.MetricBatch)
OnMetrics implements control.SessionHandler.
Batches are relayed to the coordinator unchanged, still carrying the worker's own node id. Merging them here would save a little bandwidth but would cost the operator the ability to see which process in a fleet is misbehaving, which is exactly the question a distributed run raises.
func (*Agent) OnRunStatus ¶
func (a *Agent) OnRunStatus(session *control.Session, update *loadwavev1.RunStatusUpdate)
OnRunStatus implements control.SessionHandler.
Worker phases are folded into a single agent-level phase rather than relayed one by one. The coordinator decides a run is over when every participating agent reports a terminal phase, and forwarding each worker's status verbatim would have the agent's phase flapping between its workers' — so a run with one worker still going could look finished.
func (*Agent) OnSetQuota ¶
OnSetQuota implements control.Handler.
func (*Agent) OnStartRun ¶
OnStartRun implements control.Handler.
func (*Agent) OnStopRun ¶
OnStopRun implements control.Handler.
Stopping waits for workers to wind down, which takes as long as the plan's grace period allows. That cannot happen on the control stream's receive goroutine: blocking there would stop the agent noticing anything else the coordinator says, including a follow-up hard stop.
func (*Agent) SocketPath ¶
SocketPath returns the worker control socket's filesystem path.
type Config ¶
type Config struct {
// NodeID identifies this agent to the coordinator. Reconnecting with the
// same id is what lets the coordinator recognise a returning agent rather
// than counting it twice.
NodeID string
// CoordinatorTarget is the coordinator's gRPC address.
CoordinatorTarget string
// Workers is how many worker processes to spawn per run. Zero derives it
// from the core count.
Workers int
// MaxVUs is the ceiling this agent advertises. Zero derives one from the
// core count.
MaxVUs int
// Labels are advertised to the coordinator, for operator-facing grouping.
Labels map[string]string
// SocketPath is where the worker control socket lives. Zero picks a path
// under the system temporary directory.
SocketPath string
// WorkerArgs are appended to every spawned worker's command line.
WorkerArgs []string
// Executable is the binary to spawn as a worker. Empty uses this process's
// own path, which is almost always right: a Go SDK test compiles its
// scenarios into the same binary that runs the agent.
Executable string
Logger *slog.Logger
}
Config describes an agent.