Documentation
¶
Overview ¶
Package scenario defines the Stampede scenario file format: its types, parsing, validation and the templating used inside steps.
Index ¶
- Constants
- Variables
- func CheckTraceURL(tmpl string) string
- func FormatMetric(metric string, v float64) string
- func GRPCCodeName(s string) (string, bool)
- func IsAbsoluteURL(s string) bool
- func IsReserved(name string) bool
- func JSONPathToGJSON(p string) (string, error)
- func PathTemplate(p string) string
- func StepURL(st Step) (u string, ok bool)
- func Stringify(v any) string
- func ToNative(v ref.Val) any
- func TraceLink(tmpl, traceID string) string
- func ValidateRegions(regions map[string]Percent) []string
- func WalkSteps(steps []Step, fn func(Step))
- type Abort
- type Arrival
- type Branch
- type Browser
- type BrowserAction
- type CAction
- type CBranch
- type CBrowser
- type CCheck
- type CExpect
- type CGRPC
- type CGraphQL
- type CJourney
- type CLoop
- type CPlugin
- type CRequest
- type CSSE
- type CSelectorValue
- type CSend
- type CStep
- type CWS
- type Check
- type Duration
- type Endpoint
- type Expect
- type Expr
- type Extractor
- type FaultAgent
- type FaultStep
- type Faults
- type Feeder
- type GRPC
- type GRPCCheck
- type GRPCCodes
- type GraphQL
- type Group
- type HTTPOptions
- type JSONCheck
- type JSONTemplate
- type Journey
- type JourneyGoal
- type KV
- type Load
- type Loop
- type Metadata
- type MetricKind
- type Network
- type Observe
- type Overrides
- type Percent
- type Persisted
- type Plan
- type PlanStage
- type PluginStep
- type Program
- type PrometheusObserve
- type Rate
- type Recording
- type Replay
- type Request
- type SQLFeeder
- type SSE
- type SSEUntil
- type Scenario
- type Scope
- type SelectorValue
- type Send
- type Stage
- type StatusMatcher
- func (m StatusMatcher) Empty() bool
- func (m StatusMatcher) MarshalJSON() ([]byte, error)
- func (m StatusMatcher) MarshalYAML() (any, error)
- func (m StatusMatcher) Match(code int) bool
- func (m StatusMatcher) String() string
- func (m *StatusMatcher) UnmarshalJSON(b []byte) error
- func (m *StatusMatcher) UnmarshalYAML(n *yaml.Node) error
- type Step
- type StepKind
- type Target
- type Template
- type ThinkTime
- type Threshold
- type TracesObserve
- type ValidationError
- type Viewport
- type WebSocket
Constants ¶
const ( ExtractJSON = "json" ExtractHeader = "header" ExtractCookie = "cookie" ExtractRegex = "regex" ExtractCSS = "css" ExtractStatus = "status" ExtractBody = "body" )
Extractor kinds.
const ( ExecConstantVUs = "constant-vus" ExecRampingVUs = "ramping-vus" ExecConstantRate = "constant-rate" ExecRampingRate = "ramping-rate" ExecIterations = "iterations" )
Executor names.
const ( MetricP50 = "p50" MetricP90 = "p90" MetricP95 = "p95" MetricP99 = "p99" MetricP999 = "p99.9" MetricMax = "max" MetricMean = "mean" MetricErrors = "errors" MetricChecks = "checks" MetricDropped = "dropped" MetricRPS = "rps" MetricCount = "count" )
Metric names that thresholds can refer to.
const ( FeedSequential = "sequential" FeedUnique = "unique" FeedRandom = "random" FeedPerVU = "per-vu" )
Feeder modes.
const ( ModeVUs = "vus" ModeRate = "rate" )
Load modes.
const APIVersion = "stampede.dev/v1"
APIVersion is the scenario format version this build reads and writes.
const ExecReplay = "replay"
ExecReplay is the executor of replay plans.
const KindScenario = "Scenario"
KindScenario is the only document kind currently defined.
const (
MaxObserveQueries = 20
)
Limits on the observe block.
const MaxReplaySpan = 7 * 24 * time.Hour
MaxReplaySpan is the longest a replay may last, after speed.
const ModeReplay = "replay"
ModeReplay replays a recorded arrival pattern (load.mode: replay).
const ScopeAll = "http"
ScopeAll is the threshold scope that covers every request.
const TraceIDPlaceholder = "{traceId}"
TraceIDPlaceholder is replaced by a trace ID in trace link templates.
Variables ¶
var ( // IntegrationNameRe matches the names of server integrations and // notification channels. IntegrationNameRe = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}$`) )
var Shapes = []string{"smoke", "baseline", "stress", "spike", "soak", "breakpoint", "steps", "recovery", "wave"}
Shapes lists the traffic shape presets.
Functions ¶
func CheckTraceURL ¶
CheckTraceURL validates a trace link template and returns a problem, or "" when it is usable.
func FormatMetric ¶
FormatMetric renders a value in a metric's natural unit.
func GRPCCodeName ¶
GRPCCodeName returns the canonical name of a gRPC status code given in any case, with or without underscores (NOT_FOUND, NotFound, not_found).
func IsAbsoluteURL ¶
IsAbsoluteURL reports whether a step URL names its own scheme and host, rather than a path joined to target.baseURL.
func IsReserved ¶
IsReserved reports whether name is a built-in expression variable and so cannot be used as an extracted variable name.
func JSONPathToGJSON ¶
JSONPathToGJSON converts the JSONPath subset Stampede accepts into a gjson path. Supported: $, .key, ['key'], ["key"], [n], [*] and .length.
$.items[0].id -> items.0.id $.items[*].id -> items.#.id $['odd key'].x -> odd key.x (escaped) $.items.length -> items.#
func PathTemplate ¶
PathTemplate replaces ids in a path with placeholders: /api/orders/42/items/9f1c... becomes /api/orders/{id}/items/{hex}.
func StepURL ¶
StepURL returns where a step sends traffic as written (templates not rendered): the URL of an HTTP, GraphQL, SSE, WebSocket or browser step or a goto action, or a gRPC step's target. ok is false for steps that send nothing or use the target's base URL implicitly.
func ToNative ¶
ToNative converts a CEL value into plain Go values (string, int64, float64, bool, nil, []any, map[string]any).
func ValidateRegions ¶
ValidateRegions checks a region split: known-looking names, every share above zero and a total of 100%.
Types ¶
type Abort ¶
type Abort struct {
// Errors is the failed-request ratio that trips the abort.
Errors *Percent `yaml:"errors,omitempty" json:"errors,omitempty"`
// P95 is the latency that trips the abort.
P95 Duration `yaml:"p95,omitempty" json:"p95,omitempty"`
// For is how long the limit must be exceeded (default 10s).
For Duration `yaml:"for,omitempty" json:"for,omitempty"`
}
Abort ends a run when errors or latency stay above a limit for a while, so a broken target is not hammered for the rest of the test.
type Arrival ¶
type Arrival struct {
At time.Duration // since the first request, after Speed
Endpoint int
// Target is the path and query to request.
Target string
Body string
ContentType string
}
Arrival is one recorded request.
type Branch ¶
type Branch struct {
Weight int `yaml:"weight" json:"weight"`
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Steps []Step `yaml:"steps" json:"steps"`
}
Branch is one weighted alternative inside a branch step.
type Browser ¶
type Browser struct {
URL string
// Timeout bounds each action (default the target timeout).
Timeout Duration
Viewport *Viewport
Steps []Step
}
Browser opens URL in a browser page as one virtual user would, then runs Steps (browser actions) in that page.
type BrowserAction ¶
type BrowserAction struct {
Target string
Pairs []SelectorValue
Timeout Duration
}
BrowserAction is one action in a browser page. Target is the URL for goto, the CSS selector for click and waitFor, and the key for press. Pairs map selectors to values for fill (text to type) and assert (text the element must contain), in order.
type CAction ¶
type CAction struct {
Target *Template
Pairs []CSelectorValue
Timeout Duration
}
CAction is a compiled browser action.
type CBrowser ¶
CBrowser is a compiled browser block: the page is opened at URL and the block's Steps (actions) run in it.
type CCheck ¶
type CCheck struct {
Status StatusMatcher
BodyContains *Template
JSON []JSONCheck
MaxLatency Duration
Expr *Expr
// Schema validates the body; see SchemaProblem.
Schema *jsonschema.Schema
// NeedsJSON is set when the check reads the parsed body.
NeedsJSON bool
}
CCheck is a compiled response check.
func (*CCheck) SchemaProblem ¶
SchemaProblem validates body against the check's schema and returns "" when it passes, or the first problem.
type CGRPC ¶
type CGRPC struct {
// Service is the service's full name and Method the method's name.
Service string
Method string
// Target is nil when calls go to target.baseURL's host.
Target *Template
Message *JSONTemplate
Metadata []KV
Protoset string
Proto []string
ImportPaths []string
// Codes are the accepted status code names (canonical, such as
// NOT_FOUND); CheckedStatus is set when the scenario listed them.
Codes []string
CheckedStatus bool
}
CGRPC is a compiled gRPC call.
type CGraphQL ¶
type CGraphQL struct {
// Query is nil when only a persisted query hash is sent.
Query *Template
Variables *JSONTemplate
OperationName string
Persisted bool
// Hash is the persisted query's SHA-256 in hex when it is known at
// compile time; empty means hash the rendered query.
Hash string
AllowErrors bool
}
CGraphQL is a compiled GraphQL operation.
type CPlugin ¶
type CPlugin struct {
// Plugin and Step split "mqtt.publish".
Plugin, Step string
// With renders the step's config.
With *JSONTemplate
// Config is the config as written, for checking it against the
// plugin's schema; Templated lists the JSON pointers of its strings
// that contain ${} expressions, whose type is only known at run time.
Config map[string]any
Templated []string
}
CPlugin is a compiled plugin step.
type CRequest ¶
type CRequest struct {
Method string
URL *Template
Headers []KV
Query []KV
JSON *JSONTemplate
Body *Template
Form []KV
Check *CCheck
Extract []Extractor
Timeout Duration
}
CRequest is a compiled HTTP request.
type CSelectorValue ¶
type CSelectorValue struct {
Selector, Value *Template
}
CSelectorValue is a selector and its value, both templates.
type CSend ¶
type CSend struct {
Text *Template
JSON *JSONTemplate
}
CSend is a compiled WebSocket message: exactly one of Text and JSON.
type CStep ¶
type CStep struct {
ID int
Kind StepKind
Name string
Journey string
If *Expr
Req *CRequest
Think *ThinkTime
Branches []CBranch
// BranchTotal is the sum of branch weights.
BranchTotal int
Loop *CLoop
Group string
Steps []*CStep
// GraphQL and SSE are set for their step kinds, whose HTTP parts are
// in Req.
GraphQL *CGraphQL
SSE *CSSE
// WS is set for ws steps: Req holds the handshake and Steps run on
// the connection.
WS *CWS
// Browser is set for browser steps, whose Steps run in the page;
// Action for the actions inside them.
Browser *CBrowser
Action *CAction
Send *CSend
Expect *CExpect
// GRPC is set for grpc steps; Req holds their check (without status),
// extractors and timeout.
GRPC *CGRPC
// Script is set for script steps.
Script *script.Program
// Plugin is set for plugin steps; Req holds their check, extractors
// and timeout.
Plugin *CPlugin
}
CStep is a compiled step.
type Check ¶
type Check struct {
// Status accepts exact codes (200), lists ([200, 201]) or classes ("2xx").
Status StatusMatcher `yaml:"status,omitempty" json:"status,omitempty"`
BodyContains string `yaml:"bodyContains,omitempty" json:"bodyContains,omitempty"`
// JSON maps a JSONPath to the expected value. The special value
// "exists" only requires the path to be present.
JSON map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
MaxLatency Duration `yaml:"maxLatency,omitempty" json:"maxLatency,omitempty"`
// Expr is a boolean expression over status, headers, body and json.
Expr string `yaml:"expr,omitempty" json:"expr,omitempty"`
// Schema validates the JSON body against a JSON Schema (draft 2020-12
// unless the schema says otherwise): an inline object, or the path of
// a .json, .yaml or .yml file relative to the scenario.
Schema any `yaml:"schema,omitempty" json:"schema,omitempty"`
// AllowErrors (GraphQL only) accepts a response whose errors array is
// not empty; by default that fails the step.
AllowErrors bool `yaml:"allowErrors,omitempty" json:"allowErrors,omitempty"`
}
Check asserts on a response. Failed checks count as errors.
type Duration ¶
Duration is a time.Duration that reads "500ms", "2s", "1m30s", "4h" or "2d" from YAML/JSON, and treats a bare number as seconds.
func ParseDuration ¶
ParseDuration parses a Stampede duration string.
func (Duration) MarshalJSON ¶
func (Duration) MarshalYAML ¶
func (*Duration) UnmarshalJSON ¶
type Endpoint ¶
Endpoint is one method and path template, e.g. GET /api/products/{id}.
func (Endpoint) JourneyName ¶
JourneyName names the endpoint's journey. Journey names cannot hold '/', so GET /api/products/{id} becomes "GET api.products.{id}".
type Expect ¶
type Expect struct {
// Match is a regex over the message.
Match string `yaml:"match,omitempty" json:"match,omitempty"`
// JSON maps a JSONPath to the expected value, or "exists".
JSON map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
Timeout Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
// Extract reads variables from the matching message.
Extract map[string]string `yaml:"-" json:"-"`
}
Expect waits for a message that matches every condition given; other messages are skipped. With no condition the next message matches.
type Expr ¶
type Expr struct {
// contains filtered or unexported fields
}
Expr is a compiled expression.
func (*Expr) Eval ¶
func (e *Expr) Eval(vars interpreter.Activation) (any, error)
Eval evaluates the expression against vars.
func (*Expr) EvalBool ¶
func (e *Expr) EvalBool(vars interpreter.Activation) (bool, error)
EvalBool evaluates a condition.
type Extractor ¶
type Extractor struct {
Var string
Kind string
Src string
// GJSON path for json extractors.
GJSON string
Regex *regexp.Regexp
CSS cascadia.Sel
// Attr is the attribute read by CSS extractors (text when empty).
Attr string
}
Extractor pulls a value out of a response into a variable.
func ParseExtractor ¶
ParseExtractor parses an extraction rule:
$.path JSONPath into the response body header:Name response header cookie:name cookie set by the response regex:pattern first capture group (or whole match) in the body css:selector text of the first match; css:selector@attr for an attribute status | body the status code or the whole body
type FaultAgent ¶
type FaultAgent struct {
URL string `yaml:"url,omitempty" json:"url,omitempty"`
Token string `yaml:"token,omitempty" json:"token,omitempty"`
Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
}
FaultAgent is where the agent's control API is. With stampede run, set URL and Token (both may be templated, for example ${env.AGENT_URL} and ${secret.AGENT_TOKEN}). On a server, name an agent integration instead: the server only contacts URLs an admin configured.
type FaultStep ¶
type FaultStep struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
At Duration `yaml:"at" json:"at"`
For Duration `yaml:"for" json:"for"`
// Proxy names one of the agent's proxies.
Proxy string `yaml:"proxy,omitempty" json:"proxy,omitempty"`
Latency Duration `yaml:"latency,omitempty" json:"latency,omitempty"`
Jitter Duration `yaml:"jitter,omitempty" json:"jitter,omitempty"`
Bandwidth string `yaml:"bandwidth,omitempty" json:"bandwidth,omitempty"`
Reset bool `yaml:"reset,omitempty" json:"reset,omitempty"`
Refuse bool `yaml:"refuse,omitempty" json:"refuse,omitempty"`
Blackhole bool `yaml:"blackhole,omitempty" json:"blackhole,omitempty"`
// Container is a Docker container; Action is pause, stop, kill or
// restart.
Container string `yaml:"container,omitempty" json:"container,omitempty"`
Action string `yaml:"action,omitempty" json:"action,omitempty"`
// Deployment is a Kubernetes deployment (namespace/name) scaled to
// Replicas.
Deployment string `yaml:"deployment,omitempty" json:"deployment,omitempty"`
Replicas *int `yaml:"replicas,omitempty" json:"replicas,omitempty"`
}
FaultStep is one fault: what to break, from At (after the load starts) for For. Set exactly one of Proxy, Container or Deployment.
type Faults ¶
type Faults struct {
Agent FaultAgent `yaml:"agent" json:"agent"`
Timeline []FaultStep `yaml:"timeline" json:"timeline"`
}
Faults is a timeline of faults injected by a stampede agent.
type Feeder ¶
type Feeder struct {
CSV string `yaml:"csv,omitempty" json:"csv,omitempty"`
JSON string `yaml:"json,omitempty" json:"json,omitempty"`
List []any `yaml:"list,omitempty" json:"list,omitempty"`
// Range generates integers from Range[0] to Range[1] inclusive.
Range []int64 `yaml:"range,omitempty" json:"range,omitempty"`
// Generate makes a fresh row of fake data for every use: field name to
// kind, such as email, name, uuid, int(1,100) or text(5MB). Mode and
// OnExhausted do not apply.
Generate map[string]string `yaml:"generate,omitempty" json:"generate,omitempty"`
// SQL reads rows from a database query when the run starts.
SQL *SQLFeeder `yaml:"sql,omitempty" json:"sql,omitempty"`
// Mode is one of unique, sequential, random or per-vu (default sequential).
Mode string `yaml:"mode,omitempty" json:"mode,omitempty"`
// OnExhausted applies to unique mode: "stop" ends the virtual user,
// "wrap" starts again from the first row (default stop).
OnExhausted string `yaml:"onExhausted,omitempty" json:"onExhausted,omitempty"`
}
Feeder supplies test data rows to virtual users.
type GRPC ¶
type GRPC struct {
// Method is "package.Service/Method".
Method string
// Target is grpc://host:port or grpcs://host:port; empty means the
// host of target.baseURL (TLS for https). It may use env, secret and
// vars, which are rendered once when the run starts.
Target string
// Message is the request as JSON (protojson field names); strings may
// contain ${} expressions.
Message any
Metadata map[string]string
// Descriptors come from server reflection unless Protoset (a
// FileDescriptorSet) or Proto (source files, found under ImportPaths)
// is set.
Protoset string
Proto []string
ImportPaths []string
Check *GRPCCheck
Extract map[string]string
Timeout Duration
}
GRPC calls a unary or server-streaming gRPC method.
type GRPCCheck ¶
type GRPCCheck struct {
Status GRPCCodes `yaml:"status,omitempty" json:"status,omitempty"`
JSON map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
MaxLatency Duration `yaml:"maxLatency,omitempty" json:"maxLatency,omitempty"`
Expr string `yaml:"expr,omitempty" json:"expr,omitempty"`
}
GRPCCheck asserts on a gRPC response. Status lists the accepted status codes by name (default OK); the rest work as for HTTP, on the response rendered as JSON.
type GraphQL ¶
type GraphQL struct {
Request
Query string
Variables any
OperationName string
// Persisted sends an automatic persisted query (APQ): the query's
// SHA-256 first, and the full query only if the server does not know it.
Persisted *Persisted
}
GraphQL is a GraphQL operation sent as an HTTP POST. Request holds the endpoint, headers, check, extract and timeout.
type HTTPOptions ¶
type HTTPOptions struct {
// Connections is "per-vu" (each virtual user keeps its own keep-alive
// connections, like browsers; the default) or "shared" (one pool for
// all users, like a service client).
Connections string `yaml:"connections,omitempty" json:"connections,omitempty"`
// HTTP2 enables HTTP/2 over TLS when the server offers it.
HTTP2 bool `yaml:"http2,omitempty" json:"http2,omitempty"`
// H2C speaks HTTP/2 without TLS to http:// targets, with prior
// knowledge rather than an upgrade from HTTP/1.1.
H2C bool `yaml:"h2c,omitempty" json:"h2c,omitempty"`
// DisableKeepAlive opens a new connection for every request.
DisableKeepAlive bool `yaml:"disableKeepAlive,omitempty" json:"disableKeepAlive,omitempty"`
// InsecureSkipVerify disables TLS certificate checks (test targets only).
InsecureSkipVerify bool `yaml:"insecureSkipVerify,omitempty" json:"insecureSkipVerify,omitempty"`
// DNSCacheTTL is how long a host name lookup is reused across
// connections (default 30s). Set "0s" to resolve on every connection.
DNSCacheTTL *Duration `yaml:"dnsCacheTTL,omitempty" json:"dnsCacheTTL,omitempty"`
// MaxRedirects caps followed redirects (default 10, 0 keeps the default,
// -1 disables following).
MaxRedirects int `yaml:"maxRedirects,omitempty" json:"maxRedirects,omitempty"`
// TLSResumption is "per-vu" (each user resumes only its own TLS
// sessions, like separate browsers; the default with per-vu
// connections), "shared" (any user resumes any session; the default
// with shared connections) or "off" (a full handshake on every new
// connection).
TLSResumption string `yaml:"tlsResumption,omitempty" json:"tlsResumption,omitempty"`
}
HTTPOptions tunes connection behaviour so it resembles real clients.
type JSONTemplate ¶
type JSONTemplate struct {
// contains filtered or unexported fields
}
JSONTemplate is a JSON value whose strings may contain templates.
func (*JSONTemplate) Source ¶
func (j *JSONTemplate) Source() string
Source returns every template source in the JSON value, joined by newlines, for static analysis such as finding referenced feeders.
func (*JSONTemplate) Value ¶
func (j *JSONTemplate) Value(vars interpreter.Activation) (any, error)
Value evaluates the JSON template into plain Go values.
type Journey ¶
type Journey struct {
Name string `yaml:"name" json:"name"`
Weight int `yaml:"weight,omitempty" json:"weight,omitempty"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`
Target *JourneyGoal `yaml:"target,omitempty" json:"target,omitempty"`
Steps []Step `yaml:"steps" json:"steps"`
}
Journey is one path a user takes through the product.
type JourneyGoal ¶
type JourneyGoal struct {
P50 Duration `yaml:"p50,omitempty" json:"p50,omitempty"`
P90 Duration `yaml:"p90,omitempty" json:"p90,omitempty"`
P95 Duration `yaml:"p95,omitempty" json:"p95,omitempty"`
P99 Duration `yaml:"p99,omitempty" json:"p99,omitempty"`
Errors *Percent `yaml:"errors,omitempty" json:"errors,omitempty"`
}
JourneyGoal is a per-journey target, stricter or looser than the global one.
type Load ¶
type Load struct {
// Shape picks a preset (smoke, baseline, stress, spike, soak,
// breakpoint, steps, recovery, wave). Explicit Stages override it.
Shape string `yaml:"shape,omitempty" json:"shape,omitempty"`
// Mode is "rate" (open model: start journeys on a schedule) or "vus"
// (closed model: a fixed population loops). Default vus.
Mode string `yaml:"mode,omitempty" json:"mode,omitempty"`
VUs int `yaml:"vus,omitempty" json:"vus,omitempty"`
Rate Rate `yaml:"rate,omitempty" json:"rate,omitempty"`
Duration Duration `yaml:"duration,omitempty" json:"duration,omitempty"`
// Start and Max bound preset shapes. In rate mode they are rates
// ("50/s"); in vus mode they are user counts.
Start string `yaml:"start,omitempty" json:"start,omitempty"`
Max string `yaml:"max,omitempty" json:"max,omitempty"`
Stages []Stage `yaml:"stages,omitempty" json:"stages,omitempty"`
// Steps and StepDuration tune the breakpoint and steps shapes; Cycles
// tunes the wave shape.
Steps int `yaml:"steps,omitempty" json:"steps,omitempty"`
StepDuration Duration `yaml:"stepDuration,omitempty" json:"stepDuration,omitempty"`
Cycles int `yaml:"cycles,omitempty" json:"cycles,omitempty"`
// Iterations runs a fixed number of journeys in total, shared by VUs.
Iterations int `yaml:"iterations,omitempty" json:"iterations,omitempty"`
// MaxVUs caps the user pool in rate mode (default: sized automatically).
MaxVUs int `yaml:"maxVUs,omitempty" json:"maxVUs,omitempty"`
// GracefulStop lets in-flight iterations finish after the end (default 30s).
GracefulStop Duration `yaml:"gracefulStop,omitempty" json:"gracefulStop,omitempty"`
// Abort stops the run early when the target is clearly failing.
Abort *Abort `yaml:"abort,omitempty" json:"abort,omitempty"`
// Replay sends recorded traffic (mode: replay).
Replay *Replay `yaml:"replay,omitempty" json:"replay,omitempty"`
// Regions splits a distributed run's load by worker region, such as
// {mumbai: 50%, frankfurt: 30%, virginia: 20%}. The shares must add
// up to 100%. In-process runs ignore it.
Regions map[string]Percent `yaml:"regions,omitempty" json:"regions,omitempty"`
}
Load describes how much traffic to generate and its shape over time.
func (*Load) RegionFractions ¶
RegionFractions returns the region split as fractions, or nil when the load is not split by region.
type Metadata ¶
type Metadata struct {
Name string `yaml:"name" json:"name"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`
}
Metadata names and labels a scenario.
type MetricKind ¶
type MetricKind int
MetricKind says how a metric's value is expressed.
const ( KindLatency MetricKind = iota KindRatio KindRate KindCount )
Metric kinds.
type Network ¶
type Network struct {
Profile string `yaml:"profile,omitempty" json:"profile,omitempty"`
RTT Duration `yaml:"rtt,omitempty" json:"rtt,omitempty"`
Down string `yaml:"down,omitempty" json:"down,omitempty"`
Up string `yaml:"up,omitempty" json:"up,omitempty"`
// Jitter varies each round trip by up to this much either way.
Jitter Duration `yaml:"jitter,omitempty" json:"jitter,omitempty"`
// Loss is the share of transfers stalled by a retransmission ("1%").
Loss *Percent `yaml:"loss,omitempty" json:"loss,omitempty"`
}
Network emulates a slower network inside the load generator: a profile (slow-3g, 3g, 4g, slow-wifi) and/or explicit round-trip time and bandwidth in bits per second ("1.6mbps", "768kbps"). Explicit values override the profile's.
type Observe ¶
type Observe struct {
Prometheus *PrometheusObserve `yaml:"prometheus,omitempty" json:"prometheus,omitempty"`
Traces *TracesObserve `yaml:"traces,omitempty" json:"traces,omitempty"`
}
Observe connects a run to the system under test's own telemetry.
type Overrides ¶
type Overrides struct {
Shape string
Mode string
VUs int
MaxVUs int
Rate string
Duration string
Start string
Max string
Iterations int
}
Overrides change a scenario's load at run time without editing the file, for example "same journeys, spike shape".
type Percent ¶
type Percent float64
Percent is a ratio stored as a fraction (1% = 0.01). It reads "1%", "0.5%" or a bare fraction such as 0.01.
func ParsePercent ¶
ParsePercent parses "1%" or a fraction.
func (Percent) MarshalJSON ¶
func (Percent) MarshalYAML ¶
func (*Percent) UnmarshalJSON ¶
type Persisted ¶
type Persisted struct {
SHA256 string `yaml:"sha256,omitempty" json:"sha256,omitempty"`
}
Persisted configures an automatic persisted query. An empty SHA256 is computed from the query.
type Plan ¶
type Plan struct {
Shape string
Mode string
Executor string
// Start is the value at time zero; each stage ramps linearly from the
// previous value to its Target. Values are users or rates per second.
Start float64
Stages []PlanStage
// Constant executors use Value for Duration.
Value float64
Duration time.Duration
Iterations int
VUs int
// Rates is the planned rate in each second of a replay plan.
Rates []float64
// MaxVUs caps the pool in rate mode.
MaxVUs int
GracefulStop time.Duration
// StopOnFail ends the run once a threshold fails (breakpoint shape).
StopOnFail bool
}
Plan is a load section resolved into concrete executor settings.
func (*Plan) TotalDuration ¶
TotalDuration is the planned length of the load phase, excluding the graceful stop.
type PluginStep ¶
type PluginStep struct {
// Use is "<plugin>.<step>".
Use string
// With is the step's config: a mapping whose strings may contain ${}
// expressions, checked against the schema the plugin describes.
With map[string]any
// Check and Extract work on the JSON object the step returns.
Check *Check
Extract map[string]string
Timeout Duration
}
PluginStep runs a step implemented by a plugin, such as mqtt.publish.
type Program ¶
type Program struct {
Scenario *Scenario
BaseURL *Template
Headers []KV
Journeys []*CJourney
Thresholds []Threshold
// Steps indexes every request step by ID for metric reporting.
Steps []*CStep
// TotalWeight is the sum of journey weights.
TotalWeight int
}
Program is a scenario compiled for execution: every template and expression is parsed once, ahead of the run.
func Compile ¶
Compile validates the scenario's dynamic parts and returns an executable program. It checks that every variable is defined before it is used.
A replay scenario's recording is loaded first if it is not yet, so call Compile after ResolvePaths.
func (*Program) PluginNames ¶
PluginNames returns the plugins a program uses, sorted.
type PrometheusObserve ¶
type PrometheusObserve struct {
// URL is the Prometheus base URL (stampede run only). It may be
// templated, for example ${env.PROM_URL}.
URL string `yaml:"url,omitempty" json:"url,omitempty"`
// BearerToken is sent as Authorization: Bearer (stampede run only).
// It may be templated, for example ${secret.PROM_TOKEN}.
BearerToken string `yaml:"bearerToken,omitempty" json:"bearerToken,omitempty"`
// Integration names a Prometheus integration configured on the server
// (server runs only; the server never fetches a URL from a scenario).
Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
// Queries maps a short name to a PromQL expression.
Queries map[string]string `yaml:"queries" json:"queries"`
}
PrometheusObserve names PromQL queries charted in the report. After the run each query is evaluated over the run's time range.
func (*PrometheusObserve) QueryNames ¶
func (p *PrometheusObserve) QueryNames() []string
QueryNames returns the query names in a stable (sorted) order.
type Rate ¶
type Rate float64
Rate is a number of events per second. It reads "50/s", "3000/m", "100/h" or a bare number (per second).
func (Rate) MarshalJSON ¶
func (Rate) MarshalYAML ¶
func (*Rate) UnmarshalJSON ¶
type Recording ¶
type Recording struct {
// Endpoints are the distinct method and path templates, in order of
// first appearance. Each becomes a journey.
Endpoints []Endpoint
// Arrivals are the requests to send, ordered by At.
Arrivals []Arrival
// Skipped counts lines or entries left out (unparseable, static,
// other hosts, over the limit).
Skipped int
}
Recording is a loaded replay file.
func ParseRecording ¶
ParseRecording reads an access log or HAR file into a recording.
func (*Recording) RatePerSecond ¶
RatePerSecond counts arrivals in each second.
type Replay ¶
type Replay struct {
// File is an access log (common/combined format) or a HAR recording.
File string `yaml:"file" json:"file"`
// Format is auto (default), log or har.
Format string `yaml:"format,omitempty" json:"format,omitempty"`
// Speed divides recorded gaps: 2 replays an hour in 30 minutes.
Speed float64 `yaml:"speed,omitempty" json:"speed,omitempty"`
// Limit caps the number of requests replayed (default 100000).
Limit int `yaml:"limit,omitempty" json:"limit,omitempty"`
// Host keeps only HAR requests to this host (default: the most
// frequent host in the recording).
Host string `yaml:"host,omitempty" json:"host,omitempty"`
// Static keeps requests for static assets (.js, .css, images, fonts),
// which are skipped by default.
Static bool `yaml:"static,omitempty" json:"static,omitempty"`
// contains filtered or unexported fields
}
Replay reproduces recorded traffic: every request in an access log or HAR file is sent at its recorded time (divided by Speed), as an open model, so the target sees the recorded arrival pattern.
type Request ¶
type Request struct {
Method string
URL string
Headers map[string]string
Query map[string]string
// Exactly one body form may be set.
JSON any
Body string
Form map[string]string
Check *Check
Extract map[string]string
Timeout Duration
}
Request is an HTTP call.
type SQLFeeder ¶
type SQLFeeder struct {
// Driver is postgres or mysql.
Driver string `yaml:"driver" json:"driver"`
// DSN is the connection string; ${env.X} and ${secret.X} are expanded.
DSN string `yaml:"dsn" json:"dsn"`
Query string `yaml:"query" json:"query"`
// Limit caps the rows read (default and maximum 1,000,000).
Limit int `yaml:"limit,omitempty" json:"limit,omitempty"`
}
SQLFeeder reads a feeder's rows from a query. Each worker runs it, so the database must be reachable from the workers.
type SSE ¶
SSE reads a server-sent event stream. Request holds the HTTP parts; the method defaults to GET, or POST when a body is set (as LLM APIs expect).
type SSEUntil ¶
type SSEUntil struct {
Events int `yaml:"events,omitempty" json:"events,omitempty"`
Match string `yaml:"match,omitempty" json:"match,omitempty"`
Duration Duration `yaml:"duration,omitempty" json:"duration,omitempty"`
}
SSEUntil says when to stop reading a stream. Events and Match are requirements: the stream must deliver them. Duration caps the stream; on its own, reaching it ends the step successfully. With none set the step reads until the server closes the stream.
type Scenario ¶
type Scenario struct {
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
Kind string `yaml:"kind" json:"kind"`
Metadata Metadata `yaml:"metadata" json:"metadata"`
Target Target `yaml:"target" json:"target"`
Vars map[string]any `yaml:"vars,omitempty" json:"vars,omitempty"`
Data map[string]Feeder `yaml:"data,omitempty" json:"data,omitempty"`
Journeys []Journey `yaml:"journeys" json:"journeys"`
Load Load `yaml:"load" json:"load"`
Targets []string `yaml:"targets,omitempty" json:"targets,omitempty"`
// Observe links the run to the target's own telemetry: Prometheus
// metrics queried after the run and trace links for slow requests.
Observe *Observe `yaml:"observe,omitempty" json:"observe,omitempty"`
// Faults break dependencies on purpose during the run, through a
// stampede agent running next to them.
Faults *Faults `yaml:"faults,omitempty" json:"faults,omitempty"`
}
Scenario is a complete load test definition: what to hit, how users behave, how much load to apply and what counts as passing.
func Decode ¶
Decode reads a scenario without semantic validation, rejecting unknown fields. Defaults are applied.
func LoadFile ¶
LoadFile reads a scenario file. Relative feeder paths are resolved against the file's directory.
func (*Scenario) EachStep ¶
EachStep calls fn for every step of every journey, nested ones included.
func (*Scenario) LoadReplay ¶
LoadReplay reads the replay recording and turns each endpoint into a one-step journey. Call it after ResolvePaths; it does nothing unless load.mode is replay, and nothing the second time.
func (*Scenario) ResolvePaths ¶
ResolvePaths makes relative feeder and gRPC descriptor file paths relative to dir.
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
Scope lists the variable names visible to an expression, beyond the built-in roots.
func NewResponseScope ¶
NewResponseScope is a scope that also sees response variables, used by check expressions.
func (*Scope) CompileExpr ¶
CompileExpr compiles a bare expression (no ${}).
func (*Scope) CompileTemplate ¶
CompileTemplate parses and compiles every ${...} in src. "$${" escapes a literal "${".
type SelectorValue ¶
SelectorValue is one selector and its value.
type Stage ¶
type Stage struct {
Duration Duration `yaml:"duration" json:"duration"`
Target string `yaml:"target" json:"target"`
}
Stage linearly ramps to Target over Duration. Target is a user count in vus mode or a rate ("200/s") in rate mode.
type StatusMatcher ¶
type StatusMatcher struct {
// contains filtered or unexported fields
}
StatusMatcher matches HTTP status codes.
func ParseStatus ¶
func ParseStatus(s string) (StatusMatcher, error)
ParseStatus parses "200", "2xx" or "200,201".
func (StatusMatcher) Empty ¶
func (m StatusMatcher) Empty() bool
Empty reports whether no status constraint was given.
func (StatusMatcher) MarshalJSON ¶
func (m StatusMatcher) MarshalJSON() ([]byte, error)
func (StatusMatcher) MarshalYAML ¶
func (m StatusMatcher) MarshalYAML() (any, error)
func (StatusMatcher) Match ¶
func (m StatusMatcher) Match(code int) bool
Match reports whether code satisfies the matcher.
func (StatusMatcher) String ¶
func (m StatusMatcher) String() string
func (*StatusMatcher) UnmarshalJSON ¶
func (m *StatusMatcher) UnmarshalJSON(b []byte) error
func (*StatusMatcher) UnmarshalYAML ¶
func (m *StatusMatcher) UnmarshalYAML(n *yaml.Node) error
type Step ¶
type Step struct {
Kind StepKind
// Name labels the step in reports. Requests default to "METHOD path".
Name string
// If skips the step unless the expression is true.
If string
Request *Request
Think *ThinkTime
Branch []Branch
// Loop runs Steps Count times; While runs them while Cond holds, at
// most Max times.
Loop *Loop
Group *Group
// Script is JavaScript run between requests; Sets names the variables
// it sets for later steps.
Script string
Sets []string
GraphQL *GraphQL
SSE *SSE
WS *WebSocket
Browser *Browser
// Action is set for goto, click, fill, press, waitFor and assert.
Action *BrowserAction
Send *Send
Expect *Expect
GRPC *GRPC
Plugin *PluginStep
}
Step is one action within a journey. Exactly one kind-specific field is set; Kind records which.
func (Step) Checks ¶
Checks returns the response checks this step carries (HTTP, GraphQL, SSE and plugin steps), for code that adjusts them in place.
func (Step) MarshalJSON ¶
func (Step) MarshalYAML ¶
func (*Step) UnmarshalJSON ¶
UnmarshalJSON accepts the same compact form as YAML.
type StepKind ¶
type StepKind string
StepKind identifies what a step does.
const ( StepRequest StepKind = "request" StepThink StepKind = "think" StepBranch StepKind = "branch" StepLoop StepKind = "loop" StepWhile StepKind = "while" StepGroup StepKind = "group" StepScript StepKind = "script" StepGraphQL StepKind = "graphql" StepSSE StepKind = "sse" StepWS StepKind = "ws" StepSend StepKind = "send" StepExpect StepKind = "expect" StepGRPC StepKind = "grpc" StepPlugin StepKind = "plugin" // Browser opens a real browser page; the actions after it run in // that page. StepBrowser StepKind = "browser" StepGoto StepKind = "goto" StepClick StepKind = "click" StepFill StepKind = "fill" StepPress StepKind = "press" StepWaitFor StepKind = "waitFor" StepAssert StepKind = "assert" )
Step kinds.
type Target ¶
type Target struct {
// BaseURL is prefixed to relative request paths. It may be templated,
// for example ${env.TARGET_URL}.
BaseURL string `yaml:"baseURL" json:"baseURL"`
// Verify names the ownership check used for public targets:
// "dns-txt" or "well-known". Private and loopback hosts need none.
Verify string `yaml:"verify,omitempty" json:"verify,omitempty"`
Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
// Timeout is the default per-request timeout (default 30s).
Timeout Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
HTTP HTTPOptions `yaml:"http,omitempty" json:"http,omitempty"`
// Network emulates a slower network for every virtual user.
Network *Network `yaml:"network,omitempty" json:"network,omitempty"`
}
Target describes the system under test and how to connect to it.
type Template ¶
type Template struct {
// contains filtered or unexported fields
}
Template is a string with embedded ${expressions}.
func (*Template) Render ¶
func (t *Template) Render(vars interpreter.Activation) (string, error)
Render evaluates the template to a string.
func (*Template) Value ¶
func (t *Template) Value(vars interpreter.Activation) (any, error)
Value evaluates the template keeping the type when the whole template is a single expression (so "${count}" stays a number in a JSON body).
type ThinkTime ¶
ThinkTime is a pause, either fixed ("2s") or uniformly random within a range ("2s..6s").
func ParseThinkTime ¶
ParseThinkTime parses "2s" or "2s..6s".
func (ThinkTime) MarshalJSON ¶
func (ThinkTime) MarshalYAML ¶
func (*ThinkTime) UnmarshalJSON ¶
type Threshold ¶
type Threshold struct {
Source string
// Scope is ScopeAll, a journey name, or "journey/step".
Scope string
Metric string
Op string
// Value is seconds for latency, a fraction for ratios, per second for
// rates and a plain number for counts.
Value float64
}
Threshold is a parsed target such as "checkout.p95 < 800ms".
func JourneyThresholds ¶
JourneyThresholds turns a journey's target block into thresholds.
func ParseThreshold ¶
ParseThreshold parses "[scope.]metric op value".
func (Threshold) FormatValue ¶
FormatValue renders a value in the metric's unit.
type TracesObserve ¶
type TracesObserve struct {
// URL is a link template containing {traceId}, for example
// https://jaeger.example.com/trace/{traceId}.
URL string `yaml:"url,omitempty" json:"url,omitempty"`
// Integration names a traces integration configured on the server.
Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
}
TracesObserve turns the trace IDs of the slowest requests into links.
type ValidationError ¶
type ValidationError struct {
Problems []string
}
ValidationError lists every problem found in a scenario.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
type Viewport ¶
type Viewport struct {
Width int `yaml:"width" json:"width"`
Height int `yaml:"height" json:"height"`
}
Viewport is the page size in CSS pixels (default 1280×800).
type WebSocket ¶
type WebSocket struct {
URL string
Headers map[string]string
Subprotocols []string
// Timeout bounds the opening handshake.
Timeout Duration
Steps []Step
}
WebSocket opens a connection, runs Steps with it and closes it when they finish (or the iteration fails). URL may be ws://, wss://, http(s):// or a path joined to the base URL. Inside Steps, send and expect steps use the connection; any other step kind may be mixed in.