Documentation ¶
Index ¶
- Constants
- Variables
- func CPUCheckLoop()
- func CheckDashboardAlerts(grafanaClient *grafana.Client, from, to time.Time, dashboardUID string) ([]grafana.Annotation, error)
- func ExecCmd(command string) error
- func ExecCmdWithStreamFunc(command string, outputFunction func(string)) error
- func GetLocalK8sDeps() (*kubernetes.Clientset, *rest.Config, error)
- func GetLogger(t *testing.T, componentName string) zerolog.Logger
- func LabelsMapToModel(m map[string]string) model.LabelSet
- type AlertChecker
- type ClusterConfig
- type ClusterProfile
- type Config
- type Generator
- func (g *Generator) Errors() []string
- func (g *Generator) GetData() *ResponseData
- func (g *Generator) InputSharedData() interface{}
- func (g *Generator) Pause()
- func (g *Generator) Resume()
- func (g *Generator) Run(wait bool) (interface{}, bool)
- func (g *Generator) Stats() *Stats
- func (g *Generator) StatsJSON() map[string]interface{}
- func (g *Generator) Stop() (interface{}, bool)
- func (g *Generator) Wait() (interface{}, bool)
- type GrafanaOpts
- type Gun
- type HTTPMockServer
- type HTTPMockServerConfig
- type K8sClient
- type LokiClient
- type LokiConfig
- type LokiLogWrapper
- type MockGun
- type MockGunConfig
- type MockHTTPGun
- type MockHTTPGunConfig
- type MockVirtualUser
- type MockVirtualUserConfig
- type MockWSServer
- type Profile
- type Response
- type ResponseData
- type Responses
- type Sampler
- type SamplerConfig
- type ScheduleType
- type Segment
- type SliceBuffer
- type Stats
- type VUControl
- type VirtualUser
- type WSMockVU
- type WSMockVUConfig
Constants ¶
const ( DefaultRequestsCPU = "1000m" DefaultRequestsMemory = "512Mi" DefaultLimitsCPU = "1000m" DefaultLimitsMemory = "512Mi" )
k8s pods resources
const ( DefaultCallTimeout = 1 * time.Minute DefaultSetupTimeout = 1 * time.Minute DefaultTeardownTimeout = 1 * time.Minute DefaultStatsPollInterval = 5 * time.Second DefaultRateLimitUnitDuration = 1 * time.Second DefaultCallResultBufLen = 50000 DefaultGenName = "Generator" )
const (
CallGroupLabel = "call_group"
)
const (
// DefaultStepChangePrecision is default amount of steps in which we split a schedule
DefaultStepChangePrecision = 10
)
const (
K8sStatePollInterval = 1 * time.Second
)
const (
LogLevelEnvVar = "WASP_LOG_LEVEL"
)
Variables ¶
var ( ErrNoNamespace = errors.New("namespace is empty") ErrNoJobs = errors.New("HelmValues should contain \"jobs\" field used to scale your cluster jobs, jobs must be > 0") )
var ( ResourcesThresholdCheckInterval = 5 * time.Second // CPUIdleThresholdPercentage is default CPU idle threshold CPUIdleThresholdPercentage = 20 // MEMFreeThresholdPercentage is default MEM free threshold MEMFreeThresholdPercentage = 0 )
var ( ErrNoCfg = errors.New("config is nil") ErrNoImpl = errors.New("either \"gun\" or \"vu\" implementation must provided") ErrNoSchedule = errors.New("no schedule segments were provided") ErrInvalidScheduleType = errors.New("schedule type must be either of wasp.RPS, wasp.VU, use package constants") ErrCallTimeout = errors.New("generator request call timeout") ErrSetupTimeout = errors.New("generator request setup timeout") ErrSetup = errors.New("generator request setup error") ErrTeardownTimeout = errors.New("generator request teardown timeout") ErrTeardown = errors.New("generator request teardown error") ErrStartFrom = errors.New("from must be > 0") ErrInvalidSegmentDuration = errors.New("SegmentDuration must be defined") ErrNoGun = errors.New("rps load scheduleSegments selected but gun implementation is nil") ErrNoVU = errors.New("vu load scheduleSegments selected but vu implementation is nil") ErrInvalidLabels = errors.New("invalid Loki labels, labels should be [a-z][A-Z][0-9] and _") )
var DefaultBuildScript []byte
TODO: remove the whole stuff in favor of remote-runner
var DefaultDockerIgnorefile []byte
var DefaultDockerfile []byte
Functions ¶
func CPUCheckLoop ¶
func CPUCheckLoop()
CPUCheckLoop is called once by any generator, makes sense only in cluster runs on Linux
func CheckDashboardAlerts ¶
func CheckDashboardAlerts(grafanaClient *grafana.Client, from, to time.Time, dashboardUID string) ([]grafana.Annotation, error)
CheckDashobardAlerts checks for alerts in the given dashboardUUIDs between from and to times
func ExecCmdWithStreamFunc ¶
ExecCmdWithStreamFunc executes command with stream function
func GetLocalK8sDeps ¶
func GetLocalK8sDeps() (*kubernetes.Clientset, *rest.Config, error)
GetLocalK8sDeps get local k8s context config
Types ¶
type AlertChecker ¶
type AlertChecker struct { RequirementLabelKey string T *testing.T // contains filtered or unexported fields }
AlertChecker is checking alerts according to dashboardUUID and requirements labels
func NewAlertChecker ¶
func NewAlertChecker(t *testing.T) *AlertChecker
func (*AlertChecker) AnyAlerts ¶
func (m *AlertChecker) AnyAlerts(dashboardUUID, requirementLabelValue string) ([]grafana.AlertGroupsResponse, error)
AnyAlerts check if any alerts with dashboardUUID have been raised
type ClusterConfig ¶
type ClusterConfig struct { ChartPath string Namespace string KeepJobs bool UpdateImage bool DockerCmdExecPath string DockerfilePath string DockerIgnoreFilePath string BuildScriptPath string BuildCtxPath string ImageTag string RegistryName string RepoName string HelmDeployTimeoutSec string HelmValues map[string]string // contains filtered or unexported fields }
ClusterConfig defines k8s jobs settings
func (*ClusterConfig) Defaults ¶
func (m *ClusterConfig) Defaults(a int) error
func (*ClusterConfig) Validate ¶
func (m *ClusterConfig) Validate() (err error)
type ClusterProfile ¶
type ClusterProfile struct { Ctx context.Context Cancel context.CancelFunc // contains filtered or unexported fields }
ClusterProfile is a k8s cluster test for some workload profile
func NewClusterProfile ¶
func NewClusterProfile(cfg *ClusterConfig) (*ClusterProfile, error)
NewClusterProfile creates new cluster profile
type Config ¶
type Config struct { T *testing.T GenName string LoadType ScheduleType Labels map[string]string LokiConfig *LokiConfig Schedule []*Segment RateLimitUnitDuration time.Duration CallResultBufLen int StatsPollInterval time.Duration CallTimeout time.Duration SetupTimeout time.Duration TeardownTimeout time.Duration FailOnErr bool Gun Gun VU VirtualUser Logger zerolog.Logger SamplerConfig *SamplerConfig // contains filtered or unexported fields }
Config is for shared load test data and configuration
type Generator ¶
type Generator struct { Cfg *Config Log zerolog.Logger ResponsesWaitGroup *sync.WaitGroup ResponsesCtx context.Context ResponsesChan chan *Response Responses *Responses // contains filtered or unexported fields }
Generator generates load with some RPS
func NewGenerator ¶
NewGenerator creates a new generator, shoots for scheduled RPS until timeout, test logic is defined through Gun or VirtualUser
func (*Generator) InputSharedData ¶
func (g *Generator) InputSharedData() interface{}
InputSharedData returns the SharedData passed in Generator config
type GrafanaOpts ¶
type GrafanaOpts struct { GrafanaURL string `toml:"grafana_url"` GrafanaToken string `toml:"grafana_token_secret"` WaitBeforeAlertCheck time.Duration `toml:"grafana_wait_before_alert_check"` // Cooldown period to wait before checking for alerts AnnotateDashboardUID string `toml:"grafana_annotate_dashboard_uid"` // Grafana dashboardUID to annotate start and end of the run CheckDashboardAlertsAfterRun string `toml:"grafana_check_alerts_after_run_on_dashboard_uid"` // Grafana dashboardUID to check for alerts after run }
type Gun ¶
Gun is basic interface for some synthetic load test implementation Call performs one request according to some RPS schedule
type HTTPMockServer ¶
func NewHTTPMockServer ¶
func NewHTTPMockServer(cfg *HTTPMockServerConfig) *HTTPMockServer
func (*HTTPMockServer) Run ¶
func (s *HTTPMockServer) Run()
func (*HTTPMockServer) URL ¶
func (s *HTTPMockServer) URL() string
type HTTPMockServerConfig ¶
type K8sClient ¶
type K8sClient struct { ClientSet *kubernetes.Clientset RESTConfig *rest.Config }
K8sClient high level k8s client
func NewK8sClient ¶
func NewK8sClient() *K8sClient
NewK8sClient creates a new k8s client with a REST config
type LokiClient ¶
type LokiClient struct { lokiClient.Client // contains filtered or unexported fields }
LokiClient is a Loki/Promtail client wrapper
func NewLokiClient ¶
func NewLokiClient(extCfg *LokiConfig) (*LokiClient, error)
NewLokiClient creates a new Promtail client
func (*LokiClient) HandleStruct ¶
HandleStruct handles adding a new label set and a message to the batch, marshalling JSON from struct
type LokiConfig ¶
type LokiConfig struct { // URL url to Loki endpoint URL string `yaml:"url"` // Token is Loki authorization token Token string `yaml:"token"` // BasicAuth is a basic login:password auth string BasicAuth string `yaml:"basic_auth"` // MaxErrors max amount of errors to ignore before exiting MaxErrors int // BatchWait max time to wait until sending a new batch BatchWait time.Duration // BatchSize size of a messages batch BatchSize int // Timeout is batch send timeout Timeout time.Duration // BackoffConfig backoff configuration BackoffConfig backoff.Config // Headers are additional request headers Headers map[string]string // The tenant ID to use when pushing logs to Loki (empty string means // single tenant mode) TenantID string // When enabled, Promtail will not retry batches that get a // 429 'Too Many Requests' response from the distributor. Helps // prevent HOL blocking in multitenant deployments. DropRateLimitedBatches bool // ExposePrometheusMetrics if enabled exposes Promtail Prometheus metrics ExposePrometheusMetrics bool MaxStreams int MaxLineSize int MaxLineSizeTruncate bool }
LokiConfig is simplified subset of a Promtail client configuration
func DefaultLokiConfig ¶
func DefaultLokiConfig() *LokiConfig
DefaultLokiConfig is reasonable common settings for Loki batches
func NewEnvLokiConfig ¶
func NewEnvLokiConfig() *LokiConfig
NewEnvLokiConfig creates new config from connection params as env vars
func NewLokiConfig ¶
func NewLokiConfig(endpoint *string, tenant *string, basicAuth *string, token *string) *LokiConfig
NewLokiConfig this is used when you have marshalled data from CTF
type LokiLogWrapper ¶
type LokiLogWrapper struct { MaxErrors int // contains filtered or unexported fields }
LokiLogWrapper wraps Loki errors received through logs, handles them
func NewLokiLogWrapper ¶
func NewLokiLogWrapper(maxErrors int) *LokiLogWrapper
func (*LokiLogWrapper) Log ¶
func (m *LokiLogWrapper) Log(kvars ...interface{}) error
func (*LokiLogWrapper) SetClient ¶
func (m *LokiLogWrapper) SetClient(c *LokiClient)
type MockGun ¶
type MockGun struct { Data []string // contains filtered or unexported fields }
MockGun is a mock gun
type MockGunConfig ¶
type MockGunConfig struct { // FailRatio in percentage, 0-100 FailRatio int // TimeoutRatio in percentage, 0-100 TimeoutRatio int // CallSleep time spent waiting inside a call CallSleep time.Duration // InternalStop break the test immediately InternalStop bool }
MockGunConfig configures a mock gun
type MockHTTPGun ¶
type MockHTTPGun struct { Data []string // contains filtered or unexported fields }
MockHTTPGun is a mock gun
func NewHTTPMockGun ¶
func NewHTTPMockGun(cfg *MockHTTPGunConfig) *MockHTTPGun
NewHTTPMockGun create an HTTP mock gun
func (*MockHTTPGun) Call ¶
func (m *MockHTTPGun) Call(l *Generator) *Response
Call implements example gun call, assertions on response bodies should be done here
type MockHTTPGunConfig ¶
type MockHTTPGunConfig struct {
TargetURL string
}
MockHTTPGunConfig configures a mock HTTP gun
type MockVirtualUser ¶
MockVirtualUser is a mock virtual user
func NewMockVU ¶
func NewMockVU(cfg *MockVirtualUserConfig) *MockVirtualUser
NewMockVU create a mock virtual user
func (*MockVirtualUser) Call ¶
func (m *MockVirtualUser) Call(l *Generator)
func (*MockVirtualUser) Clone ¶
func (m *MockVirtualUser) Clone(_ *Generator) VirtualUser
func (*MockVirtualUser) Setup ¶
func (m *MockVirtualUser) Setup(_ *Generator) error
func (*MockVirtualUser) Teardown ¶
func (m *MockVirtualUser) Teardown(_ *Generator) error
type MockVirtualUserConfig ¶
type MockVirtualUserConfig struct { // FailRatio in percentage, 0-100 FailRatio int // TimeoutRatio in percentage, 0-100 TimeoutRatio int // CallSleep time spent waiting inside a call CallSleep time.Duration SetupSleep time.Duration SetupFailure bool TeardownSleep time.Duration TeardownFailure bool }
MockVirtualUserConfig configures a mock virtual user
type MockWSServer ¶
type MockWSServer struct { // Logf controls where logs are sent. Logf func(f string, v ...interface{}) Sleep time.Duration }
func (MockWSServer) ServeHTTP ¶
func (s MockWSServer) ServeHTTP(w http.ResponseWriter, r *http.Request)
type Profile ¶
type Profile struct { ProfileID string // Unique identifier for the profile Generators []*Generator // contains filtered or unexported fields }
Profile is a set of concurrent generators forming some workload profile
func (*Profile) Wait ¶
func (m *Profile) Wait()
Wait waits until all generators have finished the workload
func (*Profile) WithGrafana ¶
func (m *Profile) WithGrafana(opts *GrafanaOpts) *Profile
type Response ¶
type Response struct { Failed bool `json:"failed,omitempty"` Timeout bool `json:"timeout,omitempty"` StatusCode string `json:"status_code,omitempty"` Path string `json:"path,omitempty"` Duration time.Duration `json:"duration"` StartedAt *time.Time `json:"started_at,omitempty"` FinishedAt *time.Time `json:"finished_at,omitempty"` Group string `json:"group"` Data interface{} `json:"data,omitempty"` Error string `json:"error,omitempty"` }
Response represents basic result info
type ResponseData ¶
type ResponseData struct { OKData *SliceBuffer[any] OKResponses *SliceBuffer[*Response] FailResponses *SliceBuffer[*Response] // contains filtered or unexported fields }
ResponseData includes any request/response data that a gun might store ok* slices usually contains successful responses and their verifications if their done async fail* slices contains CallResult with response data and an error
type Responses ¶
type Responses struct {
// contains filtered or unexported fields
}
func NewResponses ¶
type Sampler ¶
type Sampler struct {
// contains filtered or unexported fields
}
Sampler is a CallResult filter that stores a percentage of successful call results errored and timed out results are always stored
type SamplerConfig ¶
type SamplerConfig struct {
SuccessfulCallResultRecordRatio int
}
type ScheduleType ¶
type ScheduleType string
const ( RPS ScheduleType = "rps_schedule" VU ScheduleType = "vu_schedule" )
type Segment ¶
Segment load test schedule segment
func CombineAndRepeat ¶
CombineAndRepeat combines and repeats profile segments
type SliceBuffer ¶
SliceBuffer keeps Capacity of type T, after len => cap overrides old data
func NewSliceBuffer ¶
func NewSliceBuffer[T any](cap int) *SliceBuffer[T]
NewSliceBuffer creates new limited capacity slice
func (*SliceBuffer[T]) Append ¶
func (m *SliceBuffer[T]) Append(s T)
Append appends T if len <= cap, overrides old data otherwise
type Stats ¶
type Stats struct { // TODO: update json labels with dashboards on major release CurrentRPS atomic.Int64 `json:"currentRPS"` CurrentTimeUnit int64 `json:"current_time_unit"` CurrentVUs atomic.Int64 `json:"currentVUs"` LastSegment atomic.Int64 `json:"last_segment"` CurrentSegment atomic.Int64 `json:"current_schedule_segment"` SamplesRecorded atomic.Int64 `json:"samples_recorded"` SamplesSkipped atomic.Int64 `json:"samples_skipped"` RunPaused atomic.Bool `json:"runPaused"` RunStopped atomic.Bool `json:"runStopped"` RunFailed atomic.Bool `json:"runFailed"` Success atomic.Int64 `json:"success"` Failed atomic.Int64 `json:"failed"` CallTimeout atomic.Int64 `json:"callTimeout"` Duration int64 `json:"load_duration"` }
Stats basic generator load stats
type VUControl ¶
type VUControl struct {
// contains filtered or unexported fields
}
VUControl is a base VU that allows us to control the schedule and bring VUs up and down
func NewVUControl ¶
func NewVUControl() *VUControl
NewVUControl creates new base VU that allows us to control the schedule and bring VUs up and down
type VirtualUser ¶
type VirtualUser interface { Call(l *Generator) Clone(l *Generator) VirtualUser Setup(l *Generator) error Teardown(l *Generator) error Stop(l *Generator) StopChan() chan struct{} }
VirtualUser is basic interface to run virtual users load you should use it if: - your protocol is stateful, ex.: ws, grpc - you'd like to have some VirtualUser modelling, perform sequential requests
type WSMockVU ¶
WSMockVU ws mock virtual user
func NewWSMockVU ¶
func NewWSMockVU(cfg *WSMockVUConfig) *WSMockVU
NewWSMockVU create a ws mock virtual user
func (*WSMockVU) Clone ¶
func (m *WSMockVU) Clone(_ *Generator) VirtualUser