Documentation
¶
Overview ¶
Package flag is feature flags for smolanalytics — boolean and multivariate, with property targeting and percentage rollouts, evaluated deterministically so the same user always lands in the same bucket. What makes it deeper than a plain flag console (a later increment): a flag flip is auto-recorded as a deploy marker, so the existing deploy-impact engine answers "did flag X move activation?" from your editor, provably. This file is the pure engine — types + evaluation — with no I/O, so it's trivially testable and shared verbatim with any SDK that copies the bucketing.
Index ¶
Constants ¶
const ( ExposureEvent = "$feature_flag_called" PropFlag = "$feature_flag" PropVariant = "$feature_flag_response" )
Exposure/response property keys, mirroring PostHog's $feature_flag_called convention. The "$" prefix means the tracking-plan drift gate treats these as system events, not unplanned ones.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Flag ¶
type Flag struct {
Key string `json:"key"`
Description string `json:"description,omitempty"`
Enabled bool `json:"enabled"`
Variants []Variant `json:"variants,omitempty"`
Rules []Rule `json:"rules,omitempty"`
Measured bool `json:"measured,omitempty"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
Flag is a saved feature flag. Variants empty = a boolean flag (served variant is "on"). Rules empty = on for everyone when Enabled. Measured opts this flag into exposure logging (a later increment) so it can be A/B-analysed without every flag inflating the event count.
func (Flag) Evaluate ¶
Evaluate resolves the flag for one user, given their context properties. Returns the served variant ("on" for a boolean flag, "" when off) and whether the flag is on. Deterministic: the same key + distinct_id always yields the same result, computed only from a stable hash — no randomness, no state — so a client SDK that copies this bucketing agrees byte-for-byte.
type Report ¶ added in v0.9.7
type Report struct {
Flag string `json:"flag"`
Goal string `json:"goal"`
Days int `json:"days"`
Control string `json:"control"`
Variants []VariantResult `json:"variants"`
Note string `json:"note"`
}
Report is the A/B read for one measured flag: for each variant, how many exposed users converted on the goal event AFTER their first exposure, and whether the lift over the control arm is statistically significant. Pure + deterministic (same events → same report), so it is pinnable MCP==API by an agreement test, the same contract as every other report.
func Measure ¶ added in v0.9.7
Measure computes the report from raw events. An exposure is a $feature_flag_called event tagging the user's variant for this flag; a conversion is the user doing `goal` at or after their first exposure (so we never credit behavior that predates the experiment). Only events within the last `days` (0 = all) are considered.
type Rule ¶
type Rule struct {
Filters []query.Filter `json:"filters,omitempty"`
RolloutPct int `json:"rollout_pct"`
}
Rule is one ordered targeting clause: the user's context must pass all Filters (empty = every user), and RolloutPct (0..100) is the deterministic share of matched users served. Rules are evaluated in order, first match wins.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists flags to a JSON file (atomic tmp+rename), same discipline as the cohort and deploy stores. Flags are keyed by their stable Key (e.g. "checkout_v2"), so Save is an upsert: creating or updating the flag with that key. Empty path = in-memory only.
func (*Store) Delete ¶
Delete removes a flag by key. found is true only when a flag actually went away, so callers can report "nothing was deleted" instead of implying a removal that never happened. Deleting a key that isn't there is not an error (retries are fine).
type Variant ¶
Variant is one arm of a multivariate flag; Weight is its relative share (need not sum to 100).
type VariantResult ¶ added in v0.9.7
type VariantResult struct {
Key string `json:"key"`
Exposed int `json:"exposed"`
Converted int `json:"converted"`
RatePct float64 `json:"rate_pct"`
DeltaPct float64 `json:"delta_pct"` // conversion-rate lift vs the control arm (0 for control)
Significant bool `json:"significant"` // 95% two-proportion z-test vs control
SmallSample bool `json:"small_sample"` // too few exposed to trust the rate
}
VariantResult is one arm of a measured flag's A/B read.