Documentation ¶
Index ¶
- type BeforeFunc
- type CandidateFunc
- type CandidatePanicError
- type CleanFunc
- type CompareFunc
- type Config
- type ConfigFunc
- type Experiment
- func (e *Experiment[C]) Before(fnc BeforeFunc)
- func (e *Experiment[C]) Candidate(name string, fnc CandidateFunc[C]) error
- func (e *Experiment[C]) Clean(fnc CleanFunc[C])
- func (e *Experiment[C]) Compare(fnc CompareFunc[C])
- func (e *Experiment[C]) Control(fnc CandidateFunc[C])
- func (e *Experiment[C]) Force(f bool)
- func (e *Experiment[C]) Ignore(i bool)
- func (e *Experiment[C]) Publish(ctx context.Context) error
- func (e *Experiment[C]) Run(ctx context.Context) (C, error)
- func (e *Experiment[C]) WithPublisher(pub Publisher[C]) *Experiment[C]
- type LogPublisher
- type Logger
- type Observation
- type PublishError
- type Publisher
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BeforeFunc ¶
BeforeFunc represents the function that gets run before the experiment starts. This function will only run if the experiment should run. The functionality should be defined by the user.
type CandidateFunc ¶
CandidateFunc represents a function that is implemented by a candidate. The value returned is the value that will be used to compare data.
type CandidatePanicError ¶
type CandidatePanicError struct { Name string Panic interface{} }
ErrCandidatePanic represents the error that a candidate panicked.
func (CandidatePanicError) Error ¶
func (e CandidatePanicError) Error() string
Error returns a simple error message. It does not include the panic information.
type CleanFunc ¶
type CleanFunc[C any] func(C) C
CleanFunc represents the function that cleans up the output data. This function will only be called for candidates that did not error.
type CompareFunc ¶
CompareFunc represents the function that takes two candidates and knows how to compare them. The functionality is implemented by the user. This function will only be called for candidates that did not error.
type ConfigFunc ¶
type ConfigFunc func(*Config)
ConfigFunc represents a function that knows how to set a configuration option.
func WithConcurrency ¶
func WithConcurrency() ConfigFunc
WithConcurrency forces the experiment to run concurrently
func WithDefaultConfig ¶
func WithDefaultConfig() ConfigFunc
WithDefaultConfig returns a new configuration with defaults.
func WithPercentage ¶
func WithPercentage(p int) ConfigFunc
WithPercentage returns a new func(*Config) that sets the percentage.
func WithTimeout ¶
func WithTimeout(t time.Duration) ConfigFunc
type Experiment ¶
type Experiment[C any] struct { // contains filtered or unexported fields }
Experiment represents a new refactoring experiment. This is where you'll define your control and candidates on and this will run the experiment according to the configuration.
func New ¶
func New[C any](cfgs ...ConfigFunc) *Experiment[C]
New creates a new Experiment with the given configuration options.
func (*Experiment[C]) Before ¶
func (e *Experiment[C]) Before(fnc BeforeFunc)
Before filter to do expensive setup only when the experiment is going to run. This will be skipped if the experiment doesn't need to run. A good use case would be to do a deep copy of a struct.
func (*Experiment[C]) Candidate ¶
func (e *Experiment[C]) Candidate(name string, fnc CandidateFunc[C]) error
Candidate represents a refactoring solution. The order of candidates is randomly determined. If the concurrent configuration is given, candidates will run concurrently. If a candidate panics, your application will not panic, but the candidate will be marked as failed. If the name is control, this will panic.
func (*Experiment[C]) Clean ¶
func (e *Experiment[C]) Clean(fnc CleanFunc[C])
Clean will cleanup the state of a candidate (control included). This is done so the state could be cleaned up before storing for later comparison.
func (*Experiment[C]) Compare ¶
func (e *Experiment[C]) Compare(fnc CompareFunc[C])
Compare represents the comparison functionality between a control and a candidate.
func (*Experiment[C]) Control ¶
func (e *Experiment[C]) Control(fnc CandidateFunc[C])
Control represents the control function, this resembles the old or current implementation. This function will always run, regardless of the configuration percentage or overwrites. If this function panics, the application will panic. The output of this function will be the base to what all the candidates will be compared to.
func (*Experiment[C]) Force ¶
func (e *Experiment[C]) Force(f bool)
Force lets you overwrite the percentage. If set to true, the candidates will definitely run.
func (*Experiment[C]) Ignore ¶
func (e *Experiment[C]) Ignore(i bool)
Ignore lets you decide if the experiment should be ignored this run or not. If set to true, the candidates will not run.
func (*Experiment[C]) Publish ¶
func (e *Experiment[C]) Publish(ctx context.Context) error
Publish will publish all observations of the experiment to the configured publisher. This will publish all observations, regardless if one errors or not. It returns a PublishError which contains all underlying errors.
func (*Experiment[C]) Run ¶
func (e *Experiment[C]) Run(ctx context.Context) (C, error)
Run runs all the candidates and control in a random order. The value of the control function will be returned. If the concurrency configuration is given, this will return as soon as the control has finished running.
func (*Experiment[C]) WithPublisher ¶
func (e *Experiment[C]) WithPublisher(pub Publisher[C]) *Experiment[C]
WithPublisher configures the publisher for the experiment. The publisher must have the same type associated as the experiment.
type LogPublisher ¶
LogPublisher is a publisher that writes out the observation values as a log line. If no Logger is provided, the standard library logger will be used.
Example ¶
package main import ( "context" "fmt" "github.com/jelmersnoeck/experiment/v3" ) func main() { exp := experiment.New[string](). WithPublisher(experiment.NewLogPublisher[string]("publisher", &fmtLogger{})) exp.Control(func(context.Context) (string, error) { return "Hello world!", nil }) result, err := exp.Run(context.Background()) if err != nil { panic(err) } else { fmt.Println(result) } } type fmtLogger struct{} func (l *fmtLogger) Printf(s string, a ...interface{}) { fmt.Printf(s, a...) }
Output: Hello world!
func NewLogPublisher ¶
func NewLogPublisher[C any](name string, logger Logger) *LogPublisher[C]
NewLogPublisher returns a new LogPublisher.
func (*LogPublisher[C]) Publish ¶
func (l *LogPublisher[C]) Publish(_ context.Context, o Observation[C]) error
Publish will publish all the Observation variables as a log line. It is in the following format: [Experiment Observation] name=%s duration=%s success=%t value=%v error=%v
type Logger ¶
type Logger interface {
Printf(string, ...interface{})
}
Logger represents the interface that experiment expects for a logger.
type Observation ¶
type Observation[C any] struct { Duration time.Duration Error error Success bool Name string Value C CleanValue C ControlValue C }
Observation represents the outcome of a candidate that has run.
type PublishError ¶
type PublishError struct {
// contains filtered or unexported fields
}
PublishError is an error used when the publisher returns an error. It combines all errors into a single error.
func (*PublishError) Error ¶
func (e *PublishError) Error() string
func (*PublishError) Unwrap ¶
func (e *PublishError) Unwrap() []error