Documentation ¶
Overview ¶
Package experiments provides implementation of experiments config parsing and other experiments related features according to baseplate spec.
For a starting point, see Experiments type and NewExperiments function,
Package experiments has been deprecated in favor of reddit-go/decider internal package. Use Choose() in lieu of Variant(), which also enables optional auto-exposure.
Deprecated: baseplate.go/experiments is deprecated. Instead, use reddit-go/decider (internal).
Index ¶
- type AllNode
- type AnyNode
- type ComparisonNode
- type EqualNode
- type EventLogger
- type Experiment
- type ExperimentConfig
- type ExperimentEvent
- type Experiments
- type MissingBucketKeyError
- type MultiVariantSet
- type NotNode
- type OverrideNode
- type RangeVariantSet
- type RolloutVariantSet
- type SimpleExperiment
- type SingleVariantSet
- type Targeting
- type TargetingNodeError
- type UnknownExperimentError
- type UnknownTargetingOperatorError
- type Variant
- type VariantSet
- type VariantValidationError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AllNode ¶
type AllNode struct {
// contains filtered or unexported fields
}
AllNode evaluates to true if all child nodes returns true.
type AnyNode ¶
type AnyNode struct {
// contains filtered or unexported fields
}
AnyNode evaluates to true if at least one child node returns true.
type ComparisonNode ¶
type ComparisonNode struct {
// contains filtered or unexported fields
}
ComparisonNode is a non-equality comparison operators (gt, ge, lt, le).
Expects as input the input node as well as an operator (from the operator module). Operator must be one that expects two inputs ( ie: gt, ge, lt, le, eq, ne).
func NewComparisonNode ¶
func NewComparisonNode(inputs map[string]interface{}, comparer less) (*ComparisonNode, error)
NewComparisonNode parses the underlying input into an ComparisonNode.
func (*ComparisonNode) Evaluate ¶
func (n *ComparisonNode) Evaluate(inputs map[string]interface{}) bool
Evaluate returns true if the comparison holds true and false otherwise.
type EqualNode ¶
type EqualNode struct {
// contains filtered or unexported fields
}
EqualNode is used to determine whether an attribute equals a single value or a value in a list.
A full EqualNode in a targeting tree configuration looks like this:
{ EQ: { field: <field_name> value: <accepted_value> } }
The expected input to this constructor from the above example would be::
{ field: <field_name>, value: <accepted_value> }
type EventLogger ¶
type EventLogger interface {
Log(ctx context.Context, event ExperimentEvent) error
}
EventLogger provides an interface for experiment events to be logged.
type Experiment ¶
type Experiment struct { ExperimentVersion int `json:"experiment_version"` ShuffleVersion int `json:"shuffle_version"` BucketVal string `json:"bucket_val"` Variants []Variant `json:"variants"` BucketSeed string `json:"bucket_seed"` Targeting json.RawMessage `json:"targeting"` Overrides []map[string]json.RawMessage `json:"overrides"` }
Experiment represents the experiment and configures the available variants.
type ExperimentConfig ¶
type ExperimentConfig struct { // ID is the experiment identifier and should be unique for each experiment. ID int `json:"id"` // Name is the experiment name and should be unique for each experiment. Name string `json:"name"` // Owner is the group or individual that owns this experiment. Owner string `json:"owner"` // Enabled if set to false will disable the experiment and calls to Variant // will always returns an empty string. Enabled *bool `json:"enabled"` // Version is the string to identify the specific version of the // experiment. Version string `json:"version"` // Type specifies the type of experiment to run. If this value is not // recognized, the experiment will be considered disabled. Type string `json:"type"` // StartTimestamp is a float of seconds since the epoch of date and time // when you want the experiment to start. If an experiment has not been // started yet, it is considered disabled. StartTimestamp timebp.TimestampSecondF `json:"start_ts"` // StopTimestamp is a float of seconds since the epoch of date and time when // you want the experiment to stop. Once an experiment is stopped, it is // considered disabled. StopTimestamp timebp.TimestampSecondF `json:"stop_ts"` // Experiment is the specific experiment. Experiment Experiment `json:"experiment"` }
ExperimentConfig holds the information for the experiment plus additional data around the experiment.
type ExperimentEvent ¶
type ExperimentEvent struct { // ID uniquely identifies the experiment event. If you pass in uuid.Nil the // logger handling this event should generate a UUID v4 (optional). ID uuid.UUID // CorrelationID are used to track events across different services (optional). CorrelationID uuid.UUID // DeviceID unique identifies the device this experiment is being logged // from (optional). DeviceID uuid.UUID // Experiment is the experiment of the applied treatment (required). Experiment *ExperimentConfig // VariantName is the type of bucket that is being applied (required). VariantName string // UserID identifies the user who is being exposed to the experimental // treatment (optional). UserID string // LoggedIn indiciates whether the user is authenticated (optional). LoggedIn *bool // CookieCreatedAt is the timestamp when the cookie for the user has been // generated (optional). CookieCreatedAt time.Time // OAuthClientID is the id of the OAuth client (optional). OAuthClientID string // ClientTimestamp is the time when the experiment has been applied. If // this is not provided the logger should generate a timestamp (optional). ClientTimestamp time.Time // AppName if any specifies the application (optional). AppName string // SessionID is the id of the session (optional). SessionID string // IsOverride should be true if the variant shown was due to an override // rather than bucketing (required). IsOverride bool // EventType is the type of the experiment event. Will be set to EXPOSE // (optional). EventType string }
ExperimentEvent is the playload used by Expose to log whether a user has been exposed to an experimental treatment.
type Experiments ¶
type Experiments struct {
// contains filtered or unexported fields
}
Experiments offers access to the experiment framework with automatic refresh when there are change.
This experiments client allows access to the experiments cached on disk by the experiment configuration fetcher daemon. It will automatically reload the cache when changed.
func NewExperiments ¶
func NewExperiments(ctx context.Context, path string, eventLogger EventLogger, logger log.Wrapper) (*Experiments, error)
NewExperiments returns a new instance of the experiments clients. The path points to the experiments file that will be parsed.
Context should come with a timeout otherwise this might block forever, i.e. if the path never becomes available.
func (*Experiments) Expose ¶
func (e *Experiments) Expose(ctx context.Context, experimentName string, event ExperimentEvent) error
Expose logs an event to indicate that a user has been exposed to an experimental treatment.
func (*Experiments) Variant ¶
func (e *Experiments) Variant(name string, args map[string]interface{}, bucketingEventOverride bool) (string, error)
Variant determines the variant, if any, of this experiment is active.
All arguments needed for bucketing, targeting, and variant overrides should be passed in as arguments. The parameter names are determined by the specific implementation of the Experiment interface.
Returns the name of the enabled variant as a string if any variant is enabled. If no variant is enabled returns an empty string.
This function might return MissingBucketKeyError as the error. Caller usually want to check for that and handle it differently from other errors. See its documentation for more details.
type MissingBucketKeyError ¶ added in v0.3.1
MissingBucketKeyError is a special error returned by Variant functions, to indicate that the bucket key from the args map is missing.
This error is usually considered "normal", the caller might still want to log it, but usually don't need to send it to sentry.
func (MissingBucketKeyError) Error ¶ added in v0.3.1
func (e MissingBucketKeyError) Error() string
type MultiVariantSet ¶
type MultiVariantSet struct {
// contains filtered or unexported fields
}
MultiVariantSet is designed to handle more than two total treatments.
MultiVariantSets are not designed to support changes in variant sizes without rebucketing.
func NewMultiVariantSet ¶
func NewMultiVariantSet(variants []Variant, buckets int) (*MultiVariantSet, error)
NewMultiVariantSet returns a new instance of MultiVariantSet based on the given variants and number of buckets.
func (*MultiVariantSet) ChooseVariant ¶
func (v *MultiVariantSet) ChooseVariant(bucket int) string
ChooseVariant deterministically chooses a variant. Every call with the same bucket on one instance will result in the same answer.
type NotNode ¶
type NotNode struct {
// contains filtered or unexported fields
}
NotNode is a boolean 'not' operator and negates the child node.
func NewNotNode ¶
NewNotNode parses the underlying input into an NotNode.
type OverrideNode ¶
type OverrideNode struct {
ReturnValue bool
}
OverrideNode is an override to the targeting and can always return true or false.
func NewOverrideNode ¶
func NewOverrideNode(inputNode interface{}) *OverrideNode
NewOverrideNode parses the underlying input into an OverrideNode.
func (*OverrideNode) Evaluate ¶
func (n *OverrideNode) Evaluate(inputs map[string]interface{}) bool
Evaluate returns the configured boolean return value.
type RangeVariantSet ¶
type RangeVariantSet struct {
// contains filtered or unexported fields
}
RangeVariantSet is designed to take fixed bucket ranges.
This VariantSet allows manually setting bucketing ranges. It takes in a variant name, then the range of buckets in that should be assigned to that variant. This enables user-defined bucketing algorithms, as well as simplifies the ability to adjust range sizes in special circumstances.
func NewRangeVariantSet ¶
func NewRangeVariantSet(variants []Variant, buckets int) (*RangeVariantSet, error)
NewRangeVariantSet returns a new instance of RangeVariantSet based on the given variants and number of buckets.
func (*RangeVariantSet) ChooseVariant ¶
func (v *RangeVariantSet) ChooseVariant(bucket int) string
ChooseVariant deterministically choose a variant. Every call with the same bucket on one instance will result in the same answer
type RolloutVariantSet ¶
type RolloutVariantSet struct {
// contains filtered or unexported fields
}
RolloutVariantSet is designed for feature rollouts and takes a single variant.
Changing the size of the variant will minimize the treatment of bucketed users. Those users going from no treatment to the provided treatment (or vice versa) are limited to the change in the provided treatment size. For instance, going from 45% to 55% will result in only the new 10% of users changing treatments. The initial 45% will not change. Conversely, going from 55% to 45% will result in only 10% of users losing the treatment.
func NewRolloutVariantSet ¶
func NewRolloutVariantSet(variants []Variant, buckets int) (*RolloutVariantSet, error)
NewRolloutVariantSet returns a new instance of RolloutVariantSet based on the given variants and number of buckets.
func (*RolloutVariantSet) ChooseVariant ¶
func (v *RolloutVariantSet) ChooseVariant(bucket int) string
ChooseVariant deterministically choose a percentage-based variant. Every call with the same bucket and variants will result in the same answer.
type SimpleExperiment ¶
type SimpleExperiment struct {
// contains filtered or unexported fields
}
SimpleExperiment is a basic experiment choosing from a set of variants.
func NewSimpleExperiment ¶
func NewSimpleExperiment(experiment *ExperimentConfig) (*SimpleExperiment, error)
NewSimpleExperiment returns a new instance of SimpleExperiment. Default values if not otherwise provided by the ExperimentConfig will be assumed.
func (*SimpleExperiment) UniqueID ¶
func (e *SimpleExperiment) UniqueID(bucketVals map[string]string) string
UniqueID returns a unique ID for the experiment.
func (*SimpleExperiment) Variant ¶
func (e *SimpleExperiment) Variant(args map[string]interface{}) (string, error)
Variant determines the variant, if any, is active. Bucket calculation is determined based on the bucketVal.
This function might return MissingBucketKeyError as the error. Caller usually want to check for that and handle it differently from other errors. See its documentation for more details.
type SingleVariantSet ¶
type SingleVariantSet struct {
// contains filtered or unexported fields
}
SingleVariantSet Variant Set designed to handle two total treatments.
This variant set allows adjusting the sizes of variants without changing treatments, where possible. When not possible (eg: switching from a 60/40 distribution to a 40/60 distribution), this will minimize changing treatments (in the above case, only those buckets between the 40th and 60th percentile of the bucketing range will see a change in treatment).
func NewSingleVariantSet ¶
func NewSingleVariantSet(variants []Variant, buckets int) (*SingleVariantSet, error)
NewSingleVariantSet returns a new instance of SingleVariantSet based on the given variants and number of buckets.
func (*SingleVariantSet) ChooseVariant ¶
func (v *SingleVariantSet) ChooseVariant(bucket int) string
ChooseVariant deterministically chooses a variant. Every call with the same bucket on one instance will result in the same answer.
type Targeting ¶
Targeting is the common interface to implement experiment targeting. Evaluated whether the provided input matches the expected values.
func NewAllNode ¶
NewAllNode parses the underlying input into an AllNode.
func NewAnyNode ¶
NewAnyNode parses the underlying input into an AnyNode.
func NewEqualNode ¶
NewEqualNode parses the underlying input into an EqualNode.
func NewTargeting ¶
NewTargeting parses the given targeting configuration into a Targeting.
type TargetingNodeError ¶
type TargetingNodeError string
TargetingNodeError is returned when there was an inconsistency in the targeting due to operator mismatch or violation of their properties in the input.
func (TargetingNodeError) Error ¶
func (cause TargetingNodeError) Error() string
type UnknownExperimentError ¶
type UnknownExperimentError string
UnknownExperimentError is returned if the configured experiment is not known.
func (UnknownExperimentError) Error ¶
func (name UnknownExperimentError) Error() string
type UnknownTargetingOperatorError ¶
type UnknownTargetingOperatorError string
UnknownTargetingOperatorError is returned when the parsed operator is not known.
func (UnknownTargetingOperatorError) Error ¶
func (operator UnknownTargetingOperatorError) Error() string
type Variant ¶
type Variant struct { Name string `json:"name"` Size float64 `json:"size"` RangeStart float64 `json:"range_start"` RangeEnd float64 `json:"range_end"` }
Variant is a single variant that belongs to a set of variants and determines a bucket by name and size. Either size is set or range start and range end.
type VariantSet ¶
type VariantSet interface { ChooseVariant(bucket int) string // contains filtered or unexported methods }
VariantSet is the base interface for variant sets. A variant set contains a set of experimental variants, as well as their distributions. It is used by experiments to track which bucket a variant is assigned to.
func FromExperimentType ¶
func FromExperimentType(experimentType string, variants []Variant, buckets int) (VariantSet, error)
FromExperimentType maps the experimentType to a concrete type implementing VariantSet and returns an error for any unknown type.
type VariantValidationError ¶
type VariantValidationError string
VariantValidationError is used when the provided variants are not consistent with the chosen variant set.
func (VariantValidationError) Error ¶
func (cause VariantValidationError) Error() string