Documentation
¶
Overview ¶
Package load provides HTTP load generation functionality. It executes concurrent requests against target endpoints with configurable rate limiting, concurrency, and duration controls.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Concurrency is the number of concurrent goroutines making requests.
// Each goroutine maintains its own HTTP client connection pool.
Concurrency int
// RPS is the target requests per second across all goroutines.
// The rate limiter distributes this evenly across workers.
RPS int
// Duration is the total time to run the load test.
Duration time.Duration
// Timeout is the maximum time to wait for a single request.
Timeout time.Duration
}
Config holds the load test configuration parameters.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults for local testing.
type LatencyStats ¶
type LatencyStats struct {
Count int64
Min time.Duration
Max time.Duration
Avg time.Duration
Total time.Duration
}
LatencyStats contains latency percentiles for an endpoint.
type LiveCounters ¶
type LiveCounters struct {
Requests atomic.Int64
Errors atomic.Int64
// contains filtered or unexported fields
}
LiveCounters holds atomic counters updated by workers and read by the progress reporter. Each field is padded to a 64-byte cache line to prevent false sharing: without padding, two atomics on the same cache line force CPU cores to invalidate each other's caches on every write, even though they are logically independent. Atomics (not a mutex) because each counter is a single independent value — a mutex would serialize all workers through one lock on every request, which is unnecessary contention. A mutex would only be needed if the reader required a consistent snapshot of multiple fields simultaneously.
type ProgressReporter ¶
type ProgressReporter struct {
// contains filtered or unexported fields
}
ProgressReporter prints a live status line at regular intervals during a load test. It reads LiveCounters atomically — no synchronization needed with the workers writing to them.
func NewProgressReporter ¶
func NewProgressReporter(counters *LiveCounters, duration time.Duration, w io.Writer) *ProgressReporter
NewProgressReporter creates a reporter that reads from the given counters. w is the output destination (os.Stderr in production, bytes.Buffer in tests).
func (*ProgressReporter) Start ¶
func (p *ProgressReporter) Start()
Start begins printing status lines every second in a background goroutine.
func (*ProgressReporter) Stop ¶
func (p *ProgressReporter) Stop()
Stop signals the reporter to stop and waits for the goroutine to exit. Safe to call multiple times.
type Result ¶
type Result struct {
Endpoint string // The endpoint path that was called
Method string // HTTP method used
StatusCode int // Response status code
Latency time.Duration // Request duration
Error error // Error if request failed
}
Result contains the outcome of a single HTTP request.
type Runner ¶
type Runner struct {
Counters LiveCounters
// contains filtered or unexported fields
}
Runner executes load tests against a target service.
func NewRunner ¶
NewRunner creates a load test runner with the given configuration.
BEHAVIOR: - Creates an HTTP client with connection pooling sized for concurrency - Initializes rate limiter to enforce RPS across all workers - Client reuses connections via keep-alive for efficiency.
func (*Runner) Run ¶
func (r *Runner) Run(ctx context.Context, targetURL string, endpoints []openapi.Endpoint) (*Stats, error)
Run executes the load test against the target URL for the configured duration. It distributes requests across all provided endpoints using round-robin scheduling.
BEHAVIOR: - Spawns cfg.Concurrency goroutines, each making sequential requests - Rate limiter enforces global RPS limit across all goroutines - Continues until context is cancelled or duration expires - Collects all results for latency analysis
CONCURRENCY MODEL: - Each goroutine has exclusive access to its iteration of the endpoint slice - Results are collected via channel to avoid lock contention - WaitGroup ensures clean shutdown before returning stats
ERROR HANDLING: - Network errors are recorded in results but don't stop the test - Context cancellation triggers graceful shutdown of all workers.
type Stats ¶
type Stats struct {
TotalRequests int64 // Total requests attempted
SuccessCount int64 // Requests with 2xx status
ErrorCount int64 // Requests that failed or returned non-2xx
Duration time.Duration // Actual test duration
EndpointLatency map[string]LatencyStats // Per-endpoint latency statistics
}
Stats aggregates results from a load test run.