Files
grafana/pkg/services/featuremgmt/openfeature.go
T
Tania c9ab1142e1 Add OpenFeature providers (#101071)
* Add OpenFeature provider

* Simplify static provider

* Linting

* Apply review feedback

* Codeowner for deps

* Update pkg/services/featuremgmt/openfeature.go

Co-authored-by: Dave Henderson <dave.henderson@grafana.com>

* Apply review comments part2

* Remove from sample.ini for now

* fixup! Apply review comments part2

* Add example of context config

* Resolve conflict

* Run update workspaces

---------

Co-authored-by: Dave Henderson <dave.henderson@grafana.com>
2025-03-06 15:09:26 +01:00

72 lines
1.8 KiB
Go

package featuremgmt
import (
"fmt"
"github.com/grafana/grafana/pkg/setting"
"github.com/open-feature/go-sdk/openfeature"
)
const (
staticProviderType = "static"
goffProviderType = "goff"
configSectionName = "feature_toggles.openfeature"
contextSectionName = "feature_toggles.openfeature.context"
)
type OpenFeatureService struct {
provider openfeature.FeatureProvider
Client openfeature.IClient
}
func ProvideOpenFeatureService(cfg *setting.Cfg) (*OpenFeatureService, error) {
conf := cfg.Raw.Section(configSectionName)
provType := conf.Key("provider").MustString(staticProviderType)
url := conf.Key("url").MustString("")
key := conf.Key("targetingKey").MustString(cfg.AppURL)
var provider openfeature.FeatureProvider
var err error
if provType == goffProviderType {
provider, err = newGOFFProvider(url)
} else {
provider, err = newStaticProvider(cfg)
}
if err != nil {
return nil, fmt.Errorf("failed to create %s feature provider: %w", provType, err)
}
if err := openfeature.SetProviderAndWait(provider); err != nil {
return nil, fmt.Errorf("failed to set global %s feature provider: %w", provType, err)
}
attrs := ctxAttrs(cfg)
openfeature.SetEvaluationContext(openfeature.NewEvaluationContext(key, attrs))
client := openfeature.NewClient("grafana-openfeature-client")
return &OpenFeatureService{
provider: provider,
Client: client,
}, nil
}
// ctxAttrs uses config.ini [feature_toggles.openfeature.context] section to build the eval context attributes
func ctxAttrs(cfg *setting.Cfg) map[string]any {
ctxConf := cfg.Raw.Section(contextSectionName)
attrs := map[string]any{}
for _, key := range ctxConf.KeyStrings() {
attrs[key] = ctxConf.Key(key).String()
}
// Some default attributes
if _, ok := attrs["grafana_version"]; !ok {
attrs["grafana_version"] = setting.BuildVersion
}
return attrs
}