server

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 64 Imported by: 0

Documentation

Overview

Package server is the Stampede control plane: the REST API, the run manager, live streams and the embedded web UI.

Index

Constants

View Source
const DefaultSchedulerInterval = 15 * time.Second

DefaultSchedulerInterval is how often the scheduler looks for due schedules unless Config.SchedulerInterval says otherwise.

View Source
const DriftCheckTimeout = 3 * time.Minute

DriftCheckTimeout bounds one scheduled drift check's dry run.

View Source
const DryRunGateTimeout = 2 * time.Minute

DryRunGateTimeout bounds the dry run a project can require before load.

View Source
const MetricsRetentionInterval = time.Hour

MetricsRetentionInterval is how often per-second metrics past the retention are deleted on plain PostgreSQL.

View Source
const SessionCookie = "stampede_session"

SessionCookie is the name of the login cookie.

Variables

This section is empty.

Functions

func CoordinatorWorkers

func CoordinatorWorkers(c *coordinator.Coordinator) func() []WorkerInfo

CoordinatorWorkers adapts a coordinator for GET /workers.

Types

type AIConfig

type AIConfig struct {
	// NewProvider builds a provider client (tests inject fakes). The
	// default is provider.New.
	NewProvider func(provider.Config) (provider.Provider, error)
	// Workers bounds concurrently running jobs (default 2).
	Workers int
	// MaxQueued bounds jobs waiting for a worker (default 20).
	MaxQueued int
	// DefaultMonthlyTokenCap applies to providers saved without a cap
	// (default 2,000,000 tokens).
	DefaultMonthlyTokenCap int64
	// JobTimeout bounds one job (default 30 minutes).
	JobTimeout time.Duration
	// Transport overrides the dry run's HTTP transport (tests).
	Transport http.RoundTripper
}

AIConfig configures optional AI journey generation. Providers and keys are configured per organisation through the API; nothing here is needed for the feature to work.

type AutoExecutor

type AutoExecutor struct {
	Local       Executor
	Distributed *DistributedExecutor
}

AutoExecutor uses connected workers when there are any and otherwise runs load inside the server, so a single-machine install works with no extra setup.

func (*AutoExecutor) Start

func (a *AutoExecutor) Start(ctx context.Context, spec ExecSpec) (Execution, error)

Start picks an executor for this run.

type Config

type Config struct {
	Store   *store.Store
	Keyring *keyring.Keyring
	Logger  *slog.Logger
	// Executor runs load. The default runs it inside the server process.
	Executor Executor
	// Workers lists connected workers for GET /workers (optional).
	Workers func() []WorkerInfo
	// UI is the built web app; nil serves only the API.
	UI fs.FS
	// SecureCookies sets the Secure flag (enable behind HTTPS).
	SecureCookies bool
	// DBRetryFor is how long writes at the end of a run (its report and
	// final status) are retried while the database is unreachable
	// (default two minutes).
	DBRetryFor time.Duration
	// TLS, when set, serves the API and web UI over HTTPS.
	TLS *tls.Config
	// RedirectAddr, with TLS, also listens for plain HTTP there and
	// redirects to HTTPS; RedirectHandler (for ACME HTTP-01 challenges)
	// wraps the redirect when set.
	RedirectAddr    string
	RedirectHandler func(fallback http.Handler) http.Handler
	// SessionTTL is how long a login lasts (default 7 days).
	SessionTTL time.Duration
	// HardCaps bound every run regardless of target settings.
	HardCaps safety.Caps
	// AbortFloor stops any run whose target is clearly failing, even when
	// its scenario sets no abort limits. Nil disables it.
	AbortFloor *scenario.Abort
	// DataDir is where CSV and JSON feeder files for server runs live.
	// Empty disables file feeders on the server.
	DataDir string
	// TrustedProxies are the reverse proxies whose X-Forwarded-For header
	// is believed. Empty means the connection's address is the client.
	TrustedProxies []netip.Prefix
	// Clock is replaceable in tests.
	Now func() time.Time
	// AI configures optional AI journey generation (see handlers_ai.go).
	AI AIConfig
	// Notify configures run notifications (see notifications.go).
	Notify NotifyConfig
	// OIDC turns on single sign-on (see oidc.go).
	OIDC *OIDCConfig
	// ReplicaAddr is this replica's address, recorded for operators.
	ReplicaAddr string
	// ReplicaHeartbeat and ReplicaStale tune how often a replica refreshes
	// its row and how old a row may get before its runs are settled
	// (defaults 5s and 30s).
	ReplicaHeartbeat, ReplicaStale time.Duration
	// SchedulerInterval is how often StartScheduler looks for due
	// schedules (default 15s).
	SchedulerInterval time.Duration
}

Config configures the server.

type DistributedExecutor

type DistributedExecutor struct {
	Coordinator *coordinator.Coordinator
}

DistributedExecutor runs load on workers connected to a coordinator.

func (*DistributedExecutor) Start

func (d *DistributedExecutor) Start(ctx context.Context, spec ExecSpec) (Execution, error)

Start shards the run across connected workers.

type ExecEvent

type ExecEvent struct {
	Type    string
	Message string
	Worker  string
	Details map[string]any
}

ExecEvent is something worth recording about a run: a worker joining, being lost or saturated, a safety stop.

type ExecResult

type ExecResult struct {
	T0         time.Time
	End        time.Time
	StopReason string
	Phases     map[int]*[metrics.NumPhases]*metrics.Histogram
	PeakVUs    int
	Workers    int
	Notes      []string
	// Snapshots, when set, replaces the live snapshots for the report.
	Snapshots []*metrics.Snapshot
	// Annotate, when set, adds executor-specific detail to the report.
	Annotate func(*report.Report)
}

ExecResult describes a finished execution.

type ExecSpec

type ExecSpec struct {
	RunID    string
	Scenario *scenario.Scenario
	// YAML is the final scenario (overrides applied, base URL set) for
	// executors that ship it to workers.
	YAML    []byte
	Env     map[string]string
	Secrets map[string]string
	// AllowHosts are public hosts besides the target that requests may reach.
	AllowHosts []string
	TargetHost string
	// Workers is how many workers to use (0 = all available).
	Workers int
	// Regions splits load by worker region (fractions); nil does not.
	Regions map[string]float64
}

ExecSpec is everything needed to execute a run.

type Execution

type Execution interface {
	// Snapshots delivers one merged snapshot per interval, in order, and
	// is closed when the run ends.
	Snapshots() <-chan *metrics.Snapshot
	// Events is closed when the run ends.
	Events() <-chan ExecEvent
	Stop(reason string)
	Kill()
	Wait(ctx context.Context) (*ExecResult, error)
}

Execution is a run in progress.

type Executor

type Executor interface {
	Start(ctx context.Context, spec ExecSpec) (Execution, error)
}

Executor starts executions.

type LocalExecutor

type LocalExecutor struct {
	Logger *slog.Logger
}

LocalExecutor runs load inside the server process. It suits a single machine and development; use distributed workers for real load so the control plane and the generator do not compete for CPU.

func (*LocalExecutor) Start

func (l *LocalExecutor) Start(ctx context.Context, spec ExecSpec) (Execution, error)

Start compiles the scenario and runs it on an in-process engine.

type NotifyConfig

type NotifyConfig struct {
	// Sender delivers events; tests replace its backoff. The default
	// retries after 2s, 10s and 30s.
	Sender *notify.Sender
	// PublicURL is the server's external base URL, used for links to runs
	// in notifications. Empty leaves the links out.
	PublicURL string
	// KeepDeliveries is how many attempts are kept per channel (default 50).
	KeepDeliveries int
	// Concurrency bounds deliveries in flight (default 8).
	Concurrency int
}

NotifyConfig configures run notifications. Channels themselves are configured per organisation through the API.

type OIDCConfig

type OIDCConfig struct {
	Issuer       string
	ClientID     string
	ClientSecret string
	// RedirectURL is where the provider sends users back; default the
	// server's public URL + /api/v1/auth/oidc/callback.
	RedirectURL string
	// Name labels the sign-in button (default "SSO").
	Name string
	// AllowedDomains limits sign-in to these email domains (empty: any).
	AllowedDomains []string
	// DefaultRole is given to people who sign in for the first time; empty
	// means only people who already have an account may sign in.
	DefaultRole auth.Role
	// Scopes besides openid (default email and profile).
	Scopes []string
}

OIDCConfig turns on single sign-on with an OpenID Connect provider (Okta, Entra ID, Google, Keycloak, Auth0, Dex ...).

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the control plane.

func New

func New(cfg Config) (*Server, error)

New builds a server. Call Recover once at start-up to settle runs left unfinished by a previous process.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler is the root HTTP handler.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(ctx context.Context, addr string) error

ListenAndServe runs the HTTP server until ctx ends, then shuts down gracefully: active runs are stopped and their reports written.

func (*Server) Recover

func (s *Server) Recover(ctx context.Context) error

Recover marks runs that were in progress when the server last stopped.

func (*Server) ReplicaID

func (s *Server) ReplicaID() uuid.UUID

ReplicaID identifies this server process among its replicas.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context)

Shutdown stops the scheduler and every active run, and waits for reports to be written.

func (*Server) StartMetricsRetention

func (s *Server) StartMetricsRetention(ctx context.Context, d time.Duration) error

StartMetricsRetention keeps per-second run metrics for d (0 keeps them forever) and returns at once. With TimescaleDB it sets a retention policy that drops old chunks; the 10s and 1m rollups and every report stay. On plain PostgreSQL it deletes old rows every hour until ctx ends; the rollups there are views, so they lose those rows too.

func (*Server) StartScheduler

func (s *Server) StartScheduler(ctx context.Context)

StartScheduler starts the loop that fires due schedules, and returns at once. Call it only on the active replica (after Recover). It checks straight away, so firings missed while no server was running start once on start-up, then every Config.SchedulerInterval. Shutdown stops it.

type WorkerHealth

type WorkerHealth struct {
	ID, Name, Region string
	// Connected is false once the worker stopped sending heartbeats.
	Connected   bool
	Saturated   bool
	Reasons     []string
	CPUPercent  float64
	SchedLagP99 time.Duration
	GCPauseP99  time.Duration
	Dropped     uint64
	// LastHeartbeat is zero before the first sample.
	LastHeartbeat time.Time
}

WorkerHealth is one load generator's latest self-monitoring during a run.

type WorkerInfo

type WorkerInfo struct {
	ID          string
	Name        string
	Region      string
	Version     string
	Labels      map[string]string
	CPUs        int
	MemoryBytes int64
	// Protocols are the worker's drivers; Plugins its installed plugins.
	Protocols, Plugins []string
	Status             string
	RunID              string
	ConnectedAt        time.Time
	LastSeenAt         time.Time
}

WorkerInfo describes a connected worker for GET /workers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL