Documentation ¶
Index ¶
- Variables
- func NewLogger(level slog.Level) (*slog.Logger, error)
- func NewOpts() newOpts
- func RootContext(logger StructuredLogger) (context.Context, func())
- type ConfigUpdate
- type DoRetryChecker
- type DoRetryer
- type Doer
- type Loadtest
- type LoadtestOption
- type RetryChecker
- type Retryer
- type StructuredLogger
- type TaskReader
Constants ¶
This section is empty.
Variables ¶
var ( ErrBadReadTasksImpl = errors.New("bad ReadTasks implementation: returned a value less than zero or larger than the input slice length") ErrRetriesFailedToFlush = errors.New("failed to flush all retries") )
Functions ¶
func NewLogger ¶
NewLogger should likely be followed by a call to slog.SetDefault with the logger returned by this function if called in the program's main context.
func RootContext ¶
func RootContext(logger StructuredLogger) (context.Context, func())
RootContext returns a context that is canceled when the system process receives an interrupt, sigint, or sigterm
Also returns a function that can be used to cancel the context.
Types ¶
type ConfigUpdate ¶
type ConfigUpdate struct {
// contains filtered or unexported fields
}
func (*ConfigUpdate) SetInterval ¶
func (cu *ConfigUpdate) SetInterval(d time.Duration)
func (*ConfigUpdate) SetNumIntervalTasks ¶
func (cu *ConfigUpdate) SetNumIntervalTasks(n int)
func (*ConfigUpdate) SetNumWorkers ¶
func (cu *ConfigUpdate) SetNumWorkers(n int)
type DoRetryChecker ¶
type DoRetryChecker interface { DoRetryer RetryChecker }
type DoRetryer ¶
DoRetryer interface is useful for tasks that have no retry count upper bound
If you need to have a retry upper bound, then have your task implement DoRetryChecker
type Doer ¶
Doer is a basic task unit
If your Doer also implements Retryer then note that Doer can be run again in a different thread if your worker size is greater than one.
If you want your task to have a retry upper bound then implement DoRetryChecker
type Loadtest ¶
type Loadtest struct {
// contains filtered or unexported fields
}
func NewLoadtest ¶
func NewLoadtest(options ...LoadtestOption) (*Loadtest, error)
func (*Loadtest) NewHttpTransport ¶
HttpTransport returns a new configured *http.Transport which implements http.RoundTripper that can be used in tasks which have http clients
Note, you may need to increase the value of MaxIdleConns if your tasks target multiple hosts. MaxIdleConnsPerHost does not override the limit established by MaxIdleConns and if the tasks are expected to communicate to multiple hosts you probably need to apply some scaling factor to it to let connections go idle for a time and still be reusable.
Note that if you are not connecting to a load balancer which preserves connections to a client much of the intent we're trying to establish here is not applicable.
Also if the load balancer does not have "max connection lifespan" behavior nor a "round robin" or "connection balancing" feature without forcing the loadtesting client to reconnect then as you increase load your established connections may prevent the spread of load to newly scaled-out recipients of that load.
By default golang's http standard lib does not expose a way for us to attempt to address this. The problem is also worse if your load balancer ( or number of exposed ips for a dns record ) increase.
Rectifying this issue requires a fix like/option like https://github.com/golang/go/pull/46714 to be accepted by the go maintainers.
func (*Loadtest) UpdateConfig ¶
func (lt *Loadtest) UpdateConfig(cu ConfigUpdate) (handled bool)
UpdateConfig only returns false if the loadtest's run method has exited
This call can potentially block the caller on loadtest shutdown phase.
type LoadtestOption ¶
type LoadtestOption func(*loadtestConfig)
type RetryChecker ¶
type StructuredLogger ¶
type StructuredLogger interface { Debug(msg string, keysAndValues ...any) DebugContext(ctx context.Context, msg string, keysAndValues ...any) Warn(msg string, keysAndValues ...any) WarnContext(ctx context.Context, msg string, keysAndValues ...any) Error(msg string, keysAndValues ...any) ErrorContext(ctx context.Context, msg string, keysAndValues ...any) Info(msg string, keysAndValues ...any) InfoContext(ctx context.Context, msg string, keysAndValues ...any) }
type TaskReader ¶
type TaskReader interface { // ReadTasks fills the provided slice up to slice length starting at index 0 and returns how many records have been inserted // // Failing to fill the whole slice will signal the end of the loadtest. // // Note in general you should not use this behavior to signal loadtests to stop // if your loadtest needs to be time-bound. For that case you should signal a stop // via the context. This stop on failure to fill behavior only exists for cases // where the author wants to exhaustively run a set of tasks and not bound the // loadtest to a timespan but rather completeness of the tasks space. // // Note that if you have only partially filled the slice, those filled task slots // will still be run before termination of the loadtest. // // It is important to remember that if your loadtest loops around and you keep a large slice of // tasks in memory just to place small chunks of that list into the passed in slice of this function // that you could have a task executed by two separate goroutines at the same time under the right circumstances. // Therefore, it's really important that the tasks either be stateless or concrete copies of the original task object are // created when saved to the passed in slice of this function. ReadTasks([]Doer) int }
TaskReader describes how to read tasks into a loadtest