ltt

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2020 License: MIT Imports: 20 Imported by: 0

README

Load Testing Tool

Largely based on the Python project Locust.

Sets up an HTTP API that provides the load test data in JSON.

Usage

Usage of ltt:
  -api-host string
        REST API port to bind to.
  -api-port int
        REST API port to bind to. (default 4141)
  -log-prefix string
        Logging prefix
  -max-sleep-time int
        Maximum sleep time between a user's tasks in seconds (default 10)
  -min-sleep-time int
        Minimum sleep time between a user's tasks in seconds (default 1)
  -num-spawn-per-sec int
        Number of user to spawn per second (default 1)
  -num-users int
        Number of users to spawn (default 5)
  -request-timeout int
        Request timeout in seconds (default 5)
  -spawn-on-startup
        If true, spawning will begin on startup
  -verbose
        Verbose logging

User-Interfaces

Terminal-UI https://github.com/Jahaja/ltt-tui

Documentation

Index

Constants

View Source
const RPSTimeWindow = 10

Variables

View Source
var ErrInvalidStorageValue = errors.New("invalid storage value")

Functions

func NewHTTPClientContext

func NewHTTPClientContext(ctx context.Context, client *HTTPClient) context.Context

func NewLoadTestContext

func NewLoadTestContext(ctx context.Context, lt *LoadTest) context.Context

func NewStorageContext

func NewStorageContext(ctx context.Context, s *Storage) context.Context

func NewUserContext

func NewUserContext(ctx context.Context, u User) context.Context

func RunAPIServer

func RunAPIServer(lt *LoadTest) error

Types

type Config

type Config struct {
	// Host to bind the REST API to. default all (empty string).
	APIHost string `json:"api_host"`
	// Port to bind the REST API to, default 4141
	APIPort  int `json:"api_port"`
	NumUsers int `json:"num_users"`
	// How many users to spawn each second
	NumSpawnPerSecond int `json:"num_spawn_per_second"`
	// Default 10 seconds
	RequestTimeout int `json:"request_timeout"`
	// Custom user type to override the DefaultUser
	UserType User `json:"-"`
	// Min sleep time between tasks in seconds
	MinSleepTime int `json:"min_sleep_time"`
	// Max sleep time between tasks in seconds
	MaxSleepTime int `json:"max_sleep_time"`
	// Verbose logging
	Verbose bool `json:"verbose"`
	// If we should start spawning users on startup
	SpawnOnStartup bool `json:"spawn_on_startup"`
	// Logging params
	LogOutput io.Writer `json:"-"`
	LogPrefix string    `json:"log_prefix"`
	LogFlags  int       `json:"log_flags"`
}

func NewConfigFromFlags

func NewConfigFromFlags() Config

type DefaultUser

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

func NewDefaultUser

func NewDefaultUser(task *Task) *DefaultUser

func (*DefaultUser) Context

func (du *DefaultUser) Context() context.Context

func (*DefaultUser) ID

func (du *DefaultUser) ID() int64

func (*DefaultUser) SetContext

func (du *DefaultUser) SetContext(ctx context.Context)

func (*DefaultUser) SetID

func (du *DefaultUser) SetID(id int64)

func (*DefaultUser) SetStatus

func (du *DefaultUser) SetStatus(us UserStatusType)

func (*DefaultUser) Sleep

func (du *DefaultUser) Sleep()

func (*DefaultUser) SleepSeconds

func (du *DefaultUser) SleepSeconds(seconds int)

func (*DefaultUser) Spawn

func (du *DefaultUser) Spawn()

func (*DefaultUser) Status

func (du *DefaultUser) Status() UserStatusType

func (*DefaultUser) Tick

func (du *DefaultUser) Tick()

type HTTPClient

type HTTPClient struct {

	// These headers will be set in all requests
	Headers http.Header
	// If true, 4xx-5xx status code will return an error, defaults to true
	ErrorOnErrorCode bool
	// contains filtered or unexported fields
}

func HTTPClientFromContext

func HTTPClientFromContext(ctx context.Context) *HTTPClient

func NewHTTPClient

func NewHTTPClient(ctx context.Context, baseURI string) *HTTPClient

func (*HTTPClient) Delete

func (c *HTTPClient) Delete(path string) (*HTTPResponse, error)

func (*HTTPClient) Get

func (c *HTTPClient) Get(path string) (*HTTPResponse, error)

func (*HTTPClient) Head

func (c *HTTPClient) Head(path string) (*HTTPResponse, error)

func (*HTTPClient) Options

func (c *HTTPClient) Options(path string) (*HTTPResponse, error)

func (*HTTPClient) Patch

func (c *HTTPClient) Patch(path string, body []byte) (*HTTPResponse, error)

func (*HTTPClient) Post

func (c *HTTPClient) Post(path string, body []byte) (*HTTPResponse, error)

func (*HTTPClient) PostForm

func (c *HTTPClient) PostForm(path string, data url.Values) (*HTTPResponse, error)

func (*HTTPClient) Put

func (c *HTTPClient) Put(path string, body []byte) (*HTTPResponse, error)

func (*HTTPClient) Request

func (c *HTTPClient) Request(method string, path string, body []byte) (*HTTPResponse, error)

type HTTPResponse

type HTTPResponse struct {
	StatusCode  int
	Body        []byte
	RawResponse *http.Response
}

func (*HTTPResponse) JSON

func (resp *HTTPResponse) JSON(out interface{}) error

type LoadTest

type LoadTest struct {
	Config Config     `json:"config"`
	Status StatusType `json:"status"`
	// Map of created users
	UserMap     map[int64]User `json:"-"`
	UserMapLock sync.Mutex     `json:"-"`
	TaskRunChan chan *TaskRun  `json:"-"`
	Stats       *Statistics    `json:"stats"`
	Log         *log.Logger    `json:"-"`
	// Target number of user to spawn
	TargetUserNum int `json:"target_user_num"`
}

func FromContext

func FromContext(ctx context.Context) *LoadTest

func NewLoadTest

func NewLoadTest(config Config) *LoadTest

func (*LoadTest) Run

func (lt *LoadTest) Run(entryTask *Task)

type Statistics

type Statistics struct {
	sync.Mutex
	StartTime     time.Time `json:"start_time"`
	EndTime       time.Time `json:"end_time"`
	NumTotal      int64     `json:"num_total"`
	RunningUsers  int       `json:"num_users"`
	NumSuccessful int64     `json:"num_successful"`
	NumFailed     int64     `json:"num_failed"`
	TotalDuration int64     `json:"total_duration"`
	// unix-timestamp -> count map to calculate a current RPS value
	RPSMap map[int64]int64 `json:"-"`

	Tasks           map[string]*TaskStats `json:"tasks"`
	CurrentRPS      float32               `json:"current_rps"`
	AverageDuration float32               `json:"average_duration"`
}

func NewStatistics

func NewStatistics() *Statistics

func (*Statistics) Calculate

func (ts *Statistics) Calculate()

func (*Statistics) CleanRPSMap

func (ts *Statistics) CleanRPSMap()

func (*Statistics) Reset

func (ts *Statistics) Reset()

type StatusType

type StatusType int
const (
	StatusStopped StatusType = iota
	StatusSpawning
	StatusRunning
	StatusStopping
)

func (StatusType) MarshalJSON

func (s StatusType) MarshalJSON() ([]byte, error)

func (StatusType) String

func (s StatusType) String() string

func (*StatusType) UnmarshalJSON

func (s *StatusType) UnmarshalJSON(bytes []byte) error

type Storage

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

Local storage for each user instance

func NewStorage

func NewStorage() *Storage

func StorageFromContext

func StorageFromContext(ctx context.Context) *Storage

func (*Storage) Get

func (s *Storage) Get(key string) interface{}

func (*Storage) GetInt

func (s *Storage) GetInt(key string) (int, error)

func (*Storage) GetInt64

func (s *Storage) GetInt64(key string) (int64, error)

func (*Storage) GetString

func (s *Storage) GetString(key string) (string, error)

func (*Storage) Set

func (s *Storage) Set(key string, value interface{})

type Task

type Task struct {
	Name     string
	Parent   *Task
	SubTasks []*Task
	RunFunc  TaskFunc
	Options  TaskOptions
}

func NewEntryTask

func NewEntryTask(name string, f TaskFunc, opts TaskOptions) *Task

The entry task is the first task each User run, and only once

func NewTask

func NewTask(name string, parent *Task, f TaskFunc, opts TaskOptions) *Task

func (*Task) AddSection

func (t *Task) AddSection(name string, setup func(*Task), opts TaskOptions) *Task

Adds and returns an empty section Task and passes it to the callback The TaskOptions will be set on the new section task.

func (*Task) AddSubTask

func (t *Task) AddSubTask(name string, f TaskFunc, opts TaskOptions) *Task

func (*Task) FullName

func (t *Task) FullName() string

type TaskFunc

type TaskFunc func(context.Context) error

type TaskOptions

type TaskOptions struct {
	SelectionStrategy TaskSelectionStrategyType
	StepOutWeight     int
	Weight            int
}

type TaskRun

type TaskRun struct {
	Task     *Task
	Duration time.Duration
	Error    error
}

type TaskSelectionStrategyType

type TaskSelectionStrategyType int
const (
	TaskSelectionStrategyRandom TaskSelectionStrategyType = iota
	TaskSelectionStrategyInOrder
)

type TaskStats

type TaskStats struct {
	sync.Mutex
	Name            string           `json:"name"`
	TotalRuns       int64            `json:"total_runs"`
	NumSuccessful   int64            `json:"num_successful"`
	NumFailed       int64            `json:"num_failed"`
	TotalDuration   int64            `json:"total_duration"`
	Metrics         map[int64]int64  `json:"-"`
	Percentiles     map[int]int64    `json:"percentiles"`
	AverageDuration float32          `json:"average_duration"`
	Errors          map[string]int64 `json:"errors"`
}

func NewTaskStat

func NewTaskStat(name string) *TaskStats

func (*TaskStats) Calculate

func (ts *TaskStats) Calculate()

type User

type User interface {
	ID() int64
	SetID(int64)
	SetStatus(UserStatusType)
	Status() UserStatusType

	SetContext(ctx context.Context)
	Context() context.Context

	Spawn()
	Tick()
	Sleep()
	SleepSeconds(seconds int)
}

func UserFromContext

func UserFromContext(ctx context.Context) User

type UserStatusType

type UserStatusType int
const (
	UserStatusStopped UserStatusType = iota
	UserStatusStopping
	UserStatusSpawning
	UserStatusRunning
)

func (UserStatusType) String

func (ust UserStatusType) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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