* initial commit * add support of integerts * finialise the static provider * minor refactoring * the rest * revert: the rest * add new thiongs * more tests added * add ff parsing tests to check if types are handled correctly * update tests according to recent changes * address golint issues * Update pkg/setting/setting_feature_toggles.go Co-authored-by: Dave Henderson <dave.henderson@grafana.com> * fix rebase issues * addressing review comments * add test cases for enterprise * handle enterprise cases * minor refactoring to make api a bit easier to debug * make test names a bit more precise * fix linter * add openfeature sdk to goleak ignore in testutil * Remove only boolean check in ff gen tests * add non-boolean types top the doc in default.ini and doc string in FeatureFlag type * apply remarks, add docs to sample.ini * reflect changes in feature flags in the public grafana configuration doc * fix doc formatting * apply suggestions to the doc file --------- Co-authored-by: Dave Henderson <dave.henderson@grafana.com>
76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package featuremgmt
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
"golang.org/x/exp/maps"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
var (
|
|
// The values are updated each time
|
|
featureToggleInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
|
Name: "feature_toggles_info",
|
|
Help: "info metric that exposes what feature toggles are enabled or not",
|
|
Namespace: "grafana",
|
|
}, []string{"name"})
|
|
)
|
|
|
|
func ProvideManagerService(cfg *setting.Cfg) (*FeatureManager, error) {
|
|
mgmt := &FeatureManager{
|
|
isDevMod: cfg.Env != setting.Prod,
|
|
flags: make(map[string]*FeatureFlag, 30),
|
|
enabled: make(map[string]bool),
|
|
startup: make(map[string]bool),
|
|
warnings: make(map[string]string),
|
|
log: log.New("featuremgmt"),
|
|
}
|
|
|
|
// Register the standard flags
|
|
mgmt.registerFlags(standardFeatureFlags...)
|
|
|
|
// Load the flags from `custom.ini` files
|
|
flags, err := setting.ReadFeatureTogglesFromInitFile(cfg.Raw.Section("feature_toggles"))
|
|
if err != nil {
|
|
return mgmt, err
|
|
}
|
|
for key, val := range flags {
|
|
_, ok := mgmt.flags[key]
|
|
if !ok {
|
|
mgmt.flags[key] = &FeatureFlag{
|
|
Name: key,
|
|
Stage: FeatureStageUnknown,
|
|
}
|
|
mgmt.warnings[key] = "unknown flag in config"
|
|
}
|
|
|
|
mgmt.startup[key] = val.Variants[val.DefaultVariant] == true
|
|
}
|
|
|
|
// update the values
|
|
mgmt.update()
|
|
|
|
// Log the enabled feature toggles at startup
|
|
enabled := sort.StringSlice(maps.Keys(mgmt.enabled))
|
|
logctx := make([]any, len(enabled)*2)
|
|
for i, k := range enabled {
|
|
logctx[(i * 2)] = k
|
|
logctx[(i*2)+1] = true
|
|
}
|
|
mgmt.log.Info("FeatureToggles", logctx...)
|
|
|
|
// Minimum approach to avoid circular dependency
|
|
// nolint:staticcheck
|
|
cfg.IsFeatureToggleEnabled = mgmt.IsEnabledGlobally
|
|
return mgmt, nil
|
|
}
|
|
|
|
// ProvideToggles allows read-only access to the feature state
|
|
func ProvideToggles(mgmt *FeatureManager) FeatureToggles {
|
|
return mgmt
|
|
}
|