Skip to content

Commit

Permalink
feature: allow specifying custom featureflag atributes (#264)
Browse files Browse the repository at this point in the history
* featureflag: allow passing custom user attributes

* Specify default attrs via config

* Clearer name
  • Loading branch information
mrdg authored Nov 15, 2021
1 parent fe31619 commit d8d58fa
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 14 deletions.
4 changes: 4 additions & 0 deletions featureflag/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ type Config struct {

// Set when using the Launch Darkly Relay proxy
RelayHost string `json:"relay_host" yaml:"relay_host" mapstructure:"relay_host" split_words:"true"`

// DefaultUserAttrs are custom LaunchDarkly user attributes that are added to every
// feature flag check
DefaultUserAttrs map[string]string `json:"default_user_attrs" yaml:"default_user_attrs"`
}
43 changes: 35 additions & 8 deletions featureflag/featureflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import (

"github.com/sirupsen/logrus"

"gopkg.in/launchdarkly/go-sdk-common.v1/ldvalue"
ld "gopkg.in/launchdarkly/go-server-sdk.v4"
"gopkg.in/launchdarkly/go-server-sdk.v4/ldlog"
)

type Client interface {
Enabled(key, userID string) bool
Enabled(key, userID string, attrs ...Attr) bool
EnabledUser(key string, user ld.User) bool

Variation(key, defaultVal, userID string) string
Variation(key, defaultVal, userID string, attrs ...Attr) string
VariationUser(key string, defaultVal string, user ld.User) string

AllEnabledFlags(key string) []string
Expand All @@ -22,7 +23,8 @@ type Client interface {

type ldClient struct {
*ld.LDClient
log logrus.FieldLogger
log logrus.FieldLogger
defaultAttrs []Attr
}

var _ Client = &ldClient{}
Expand Down Expand Up @@ -55,11 +57,16 @@ func NewClient(cfg *Config, logger logrus.FieldLogger) (Client, error) {
if err != nil {
logger.WithError(err).Error("Unable to construct LD client")
}
return &ldClient{inner, logger}, err

var defaultAttrs []Attr
for k, v := range cfg.DefaultUserAttrs {
defaultAttrs = append(defaultAttrs, StringAttr(k, v))
}
return &ldClient{inner, logger, defaultAttrs}, err
}

func (c *ldClient) Enabled(key string, userID string) bool {
return c.EnabledUser(key, ld.NewUser(userID))
func (c *ldClient) Enabled(key string, userID string, attrs ...Attr) bool {
return c.EnabledUser(key, c.userWithAttrs(userID, attrs))
}

func (c *ldClient) EnabledUser(key string, user ld.User) bool {
Expand All @@ -70,8 +77,8 @@ func (c *ldClient) EnabledUser(key string, user ld.User) bool {
return res
}

func (c *ldClient) Variation(key, defaultVal, userID string) string {
return c.VariationUser(key, defaultVal, ld.NewUser(userID))
func (c *ldClient) Variation(key, defaultVal, userID string, attrs ...Attr) string {
return c.VariationUser(key, defaultVal, c.userWithAttrs(userID, attrs))
}

func (c *ldClient) VariationUser(key string, defaultVal string, user ld.User) string {
Expand Down Expand Up @@ -103,6 +110,26 @@ func (c *ldClient) AllEnabledFlagsUser(key string, user ld.User) []string {
return flags
}

func (c *ldClient) userWithAttrs(id string, attrs []Attr) ld.User {
b := ld.NewUserBuilder(id)
for _, attr := range c.defaultAttrs {
b.Custom(attr.Name, attr.Value)
}
for _, attr := range attrs {
b.Custom(attr.Name, attr.Value)
}
return b.Build()
}

type Attr struct {
Name string
Value ldvalue.Value
}

func StringAttr(name, value string) Attr {
return Attr{Name: name, Value: ldvalue.String(value)}
}

func configureLogger(ldLogger *ldlog.Loggers, log logrus.FieldLogger) {
if log == nil {
l := logrus.New()
Expand Down
8 changes: 4 additions & 4 deletions featureflag/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ func Init(conf Config, log logrus.FieldLogger) error {
return nil
}

func Enabled(key, userID string) bool {
return GetGlobalClient().Enabled(key, userID)
func Enabled(key, userID string, attrs ...Attr) bool {
return GetGlobalClient().Enabled(key, userID, attrs...)
}

func Variation(key, defaultVal, userID string) string {
return GetGlobalClient().Variation(key, defaultVal, userID)
func Variation(key, defaultVal, userID string, attrs ...Attr) string {
return GetGlobalClient().Variation(key, defaultVal, userID, attrs...)
}
4 changes: 2 additions & 2 deletions featureflag/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ type MockClient struct {

var _ Client = MockClient{}

func (c MockClient) Enabled(key, userID string) bool {
func (c MockClient) Enabled(key, userID string, _ ...Attr) bool {
return c.EnabledUser(key, ld.NewUser(userID))
}

func (c MockClient) EnabledUser(key string, _ ld.User) bool {
return c.BoolVars[key]
}

func (c MockClient) Variation(key string, defaultVal string, userID string) string {
func (c MockClient) Variation(key string, defaultVal string, userID string, _ ...Attr) string {
return c.VariationUser(key, defaultVal, ld.NewUser(userID))
}

Expand Down

0 comments on commit d8d58fa

Please sign in to comment.