diff --git a/client/client.go b/client/client.go index 1dfedcbf..63c1a80b 100644 --- a/client/client.go +++ b/client/client.go @@ -91,7 +91,7 @@ func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) { return nil, err } client.repository = repository.New(lruCache) - client.evaluator, err = evaluation.NewEvaluator(client.repository, client) + client.evaluator, err = evaluation.NewEvaluator(client.repository, client, config.Logger) if err != nil { return nil, err } diff --git a/evaluation/evaluator.go b/evaluation/evaluator.go index d307dbca..d1f53819 100644 --- a/evaluation/evaluator.go +++ b/evaluation/evaluator.go @@ -9,7 +9,8 @@ import ( "strconv" "strings" - "github.com/harness/ff-golang-server-sdk/log" + "github.com/harness/ff-golang-server-sdk/logger" + "github.com/harness/ff-golang-server-sdk/rest" ) @@ -50,14 +51,16 @@ type PostEvaluateCallback interface { type Evaluator struct { query Query postEvalCallback PostEvaluateCallback + logger logger.Logger } // NewEvaluator constructs evaluator with query instance -func NewEvaluator(query Query, postEvalCallback PostEvaluateCallback) (*Evaluator, error) { +func NewEvaluator(query Query, postEvalCallback PostEvaluateCallback, logger logger.Logger) (*Evaluator, error) { if query == nil { return nil, ErrQueryProviderMissing } return &Evaluator{ + logger: logger, query: query, postEvalCallback: postEvalCallback, }, nil @@ -233,13 +236,13 @@ func (e Evaluator) isTargetIncludedOrExcludedInSegment(segmentList []string, tar } // Should Target be excluded - if in excluded list we return false if segment.Excluded != nil && isTargetInList(target, *segment.Excluded) { - log.Debugf("Target %s excluded from segment %s via exclude list", target.Name, segment.Name) + e.logger.Debugf("Target %s excluded from segment %s via exclude list", target.Name, segment.Name) return false } // Should Target be included - if in included list we return true if segment.Included != nil && isTargetInList(target, *segment.Included) { - log.Debugf( + e.logger.Debugf( "Target %s included in segment %s via include list", target.Name, segment.Name) @@ -249,7 +252,7 @@ func (e Evaluator) isTargetIncludedOrExcludedInSegment(segmentList []string, tar // Should Target be included via segment rules rules := segment.Rules if rules != nil && e.evaluateClauses(*rules, target) { - log.Debugf( + e.logger.Debugf( "Target %s included in segment %s via rules", target.Name, segment.Name) return true } @@ -259,12 +262,12 @@ func (e Evaluator) isTargetIncludedOrExcludedInSegment(segmentList []string, tar func (e Evaluator) checkPreRequisite(fc *rest.FeatureConfig, target *Target) (bool, error) { if e.query == nil { - log.Errorf(ErrQueryProviderMissing.Error()) + e.logger.Errorf(ErrQueryProviderMissing.Error()) return true, ErrQueryProviderMissing } prerequisites := fc.Prerequisites if prerequisites != nil { - log.Infof( + e.logger.Debugf( "Checking pre requisites %v of parent feature %v", prerequisites, fc.Feature) @@ -272,19 +275,19 @@ func (e Evaluator) checkPreRequisite(fc *rest.FeatureConfig, target *Target) (bo prereqFeature := pre.Feature prereqFeatureConfig, err := e.query.GetFlag(prereqFeature) if err != nil { - log.Errorf( + e.logger.Errorf( "Could not retrieve the pre requisite details of feature flag : %v", prereqFeature) return true, nil } prereqEvaluatedVariation, err := e.evaluateFlag(prereqFeatureConfig, target) if err != nil { - log.Errorf( + e.logger.Errorf( "Could not evaluate the prerequisite details of feature flag : %v", prereqFeature) return true, nil } - log.Infof( + e.logger.Debugf( "Pre requisite flag %v has variation %v for target %v", prereqFeatureConfig.Feature, prereqEvaluatedVariation, @@ -293,7 +296,7 @@ func (e Evaluator) checkPreRequisite(fc *rest.FeatureConfig, target *Target) (bo // Compare if the pre requisite variation is a possible valid value of // the pre requisite FF validPrereqVariations := pre.Variations - log.Infof( + e.logger.Debugf( "Pre requisite flag %v should have the variations %v", prereqFeatureConfig.Feature, validPrereqVariations) @@ -311,7 +314,7 @@ func (e Evaluator) checkPreRequisite(fc *rest.FeatureConfig, target *Target) (bo func (e Evaluator) evaluate(identifier string, target *Target, kind string) (rest.Variation, error) { if e.query == nil { - log.Errorf(ErrQueryProviderMissing.Error()) + e.logger.Errorf(ErrQueryProviderMissing.Error()) return rest.Variation{}, ErrQueryProviderMissing } flag, err := e.query.GetFlag(identifier) @@ -349,7 +352,7 @@ func (e Evaluator) evaluate(identifier string, target *Target, kind string) (res func (e Evaluator) BoolVariation(identifier string, target *Target, defaultValue bool) bool { variation, err := e.evaluate(identifier, target, "boolean") if err != nil { - log.Errorf("Error while evaluating boolean flag '%s', err: %v", identifier, err) + e.logger.Errorf("Error while evaluating boolean flag '%s', err: %v", identifier, err) return defaultValue } return strings.ToLower(variation.Value) == "true" @@ -360,7 +363,7 @@ func (e Evaluator) StringVariation(identifier string, target *Target, defaultVal variation, err := e.evaluate(identifier, target, "string") if err != nil { - log.Errorf("Error while evaluating string flag '%s', err: %v", identifier, err) + e.logger.Errorf("Error while evaluating string flag '%s', err: %v", identifier, err) return defaultValue } return variation.Value @@ -371,7 +374,7 @@ func (e Evaluator) IntVariation(identifier string, target *Target, defaultValue variation, err := e.evaluate(identifier, target, "int") if err != nil { - log.Errorf("Error while evaluating int flag '%s', err: %v", identifier, err) + e.logger.Errorf("Error while evaluating int flag '%s', err: %v", identifier, err) return defaultValue } val, err := strconv.Atoi(variation.Value) @@ -386,7 +389,7 @@ func (e Evaluator) NumberVariation(identifier string, target *Target, defaultVal variation, err := e.evaluate(identifier, target, "number") if err != nil { - log.Errorf("Error while evaluating number flag '%s', err: %v", identifier, err) + e.logger.Errorf("Error while evaluating number flag '%s', err: %v", identifier, err) return defaultValue } val, err := strconv.ParseFloat(variation.Value, 64) @@ -402,7 +405,7 @@ func (e Evaluator) JSONVariation(identifier string, target *Target, variation, err := e.evaluate(identifier, target, "json") if err != nil { - log.Errorf("Error while evaluating json flag '%s', err: %v", identifier, err) + e.logger.Errorf("Error while evaluating json flag '%s', err: %v", identifier, err) return defaultValue } val := make(map[string]interface{}) diff --git a/evaluation/evaluator_test.go b/evaluation/evaluator_test.go index b84a3145..ce20d945 100644 --- a/evaluation/evaluator_test.go +++ b/evaluation/evaluator_test.go @@ -5,6 +5,8 @@ import ( "reflect" "testing" + "github.com/harness/ff-golang-server-sdk/logger" + "github.com/harness/ff-golang-server-sdk/rest" ) @@ -303,9 +305,11 @@ func (m TestRepository) GetFlag(identifier string) (rest.FeatureConfig, error) { } func TestNewEvaluator(t *testing.T) { - eval, _ := NewEvaluator(testRepo, nil) + noOpLogger := logger.NewNoOpLogger() + eval, _ := NewEvaluator(testRepo, nil, noOpLogger) type args struct { - query Query + query Query + logger logger.Logger } tests := []struct { name string @@ -322,7 +326,8 @@ func TestNewEvaluator(t *testing.T) { { name: "should return test repo", args: args{ - query: testRepo, + query: testRepo, + logger: noOpLogger, }, want: eval, wantErr: false, @@ -330,7 +335,7 @@ func TestNewEvaluator(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewEvaluator(tt.args.query, nil) + got, err := NewEvaluator(tt.args.query, nil, noOpLogger) if (err != nil) != tt.wantErr { t.Errorf("NewEvaluator() error = %v, wantErr %v", err, tt.wantErr) return @@ -616,7 +621,8 @@ func TestEvaluator_evaluateClause(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.evaluateClause(tt.args.clause, tt.args.target); got != tt.want { t.Errorf("Evaluator.evaluateClause() = %v, want %v", got, tt.want) @@ -797,7 +803,8 @@ func TestEvaluator_evaluateRules(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.evaluateRules(tt.args.servingRules, tt.args.target); got != tt.want { t.Errorf("Evaluator.evaluateRules() = %v, want %v", got, tt.want) @@ -915,7 +922,8 @@ func TestEvaluator_evaluateVariationMap(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.evaluateVariationMap(tt.args.variationsMap, tt.args.target); got != tt.want { t.Errorf("Evaluator.evaluateVariationMap() = %v, want %v", got, tt.want) @@ -1080,7 +1088,8 @@ func TestEvaluator_evaluateFlag(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } got, err := e.evaluateFlag(tt.args.fc, tt.args.target) if (err != nil) != tt.wantErr { @@ -1181,7 +1190,8 @@ func TestEvaluator_isTargetIncludedOrExcludedInSegment(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.isTargetIncludedOrExcludedInSegment(tt.args.segmentList, tt.args.target); got != tt.want { t.Errorf("Evaluator.isTargetIncludedOrExcludedInSegment() = %v, want %v", got, tt.want) @@ -1263,7 +1273,8 @@ func TestEvaluator_checkPreRequisite(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } got, err := e.checkPreRequisite(tt.args.parent, tt.args.target) if (err != nil) != tt.wantErr { @@ -1380,7 +1391,8 @@ func TestEvaluator_evaluate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } got, err := e.evaluate(tt.args.identifier, tt.args.target, tt.args.kind) if (err != nil) != tt.wantErr { @@ -1451,7 +1463,8 @@ func TestEvaluator_BoolVariation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.BoolVariation(tt.args.identifier, tt.args.target, tt.args.defaultValue); got != tt.want { t.Errorf("Evaluator.BoolVariation() = %v, want %v", got, tt.want) @@ -1517,7 +1530,8 @@ func TestEvaluator_StringVariation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.StringVariation(tt.args.identifier, tt.args.target, tt.args.defaultValue); got != tt.want { t.Errorf("Evaluator.StringVariation() = %v, want %v", got, tt.want) @@ -1595,7 +1609,8 @@ func TestEvaluator_IntVariation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.IntVariation(tt.args.identifier, tt.args.target, tt.args.defaultValue); got != tt.want { t.Errorf("Evaluator.IntVariation() = %v, want %v", got, tt.want) @@ -1673,7 +1688,8 @@ func TestEvaluator_NumberVariation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.NumberVariation(tt.args.identifier, tt.args.target, tt.args.defaultValue); got != tt.want { t.Errorf("Evaluator.NumberVariation() = %v, want %v", got, tt.want) @@ -1758,7 +1774,8 @@ func TestEvaluator_JSONVariation(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { e := Evaluator{ - query: tt.fields.query, + query: tt.fields.query, + logger: logger.NewNoOpLogger(), } if got := e.JSONVariation(tt.args.identifier, tt.args.target, tt.args.defaultValue); !reflect.DeepEqual(got, tt.want) { t.Errorf("Evaluator.JSONVariation() = %v, want %v", got, tt.want) diff --git a/logger/nooplogger.go b/logger/nooplogger.go new file mode 100644 index 00000000..e0dc3fa1 --- /dev/null +++ b/logger/nooplogger.go @@ -0,0 +1,46 @@ +package logger + +// NoOpLogger is a type that implements the Logger interface but does nothing +// when it's methods are called +type NoOpLogger struct{} + +// NewNoOpLogger returns a NoOpLogger +func NewNoOpLogger() NoOpLogger { + return NoOpLogger{} +} + +// Debug does nothing on a NoOpLogger +func (m NoOpLogger) Debug(args ...interface{}) {} + +// Debugf does nothing on a NoOpLogger +func (m NoOpLogger) Debugf(template string, args ...interface{}) {} + +// Info does nothing on a NoOpLogger +func (m NoOpLogger) Info(args ...interface{}) {} + +// Infof does nothing on a NoOpLogger +func (m NoOpLogger) Infof(template string, args ...interface{}) {} + +// Warn does nothing on a NoOpLogger +func (m NoOpLogger) Warn(args ...interface{}) {} + +// Warnf does nothing on a NoOpLogger +func (m NoOpLogger) Warnf(template string, args ...interface{}) {} + +// Error does nothing on a NoOpLogger +func (m NoOpLogger) Error(args ...interface{}) {} + +// Errorf does nothing on a NoOpLogger +func (m NoOpLogger) Errorf(template string, args ...interface{}) {} + +// Panic does nothing on a NoOpLogger +func (m NoOpLogger) Panic(args ...interface{}) {} + +// Panicf does nothing on a NoOpLogger +func (m NoOpLogger) Panicf(template string, args ...interface{}) {} + +// Fatal does nothing on a NoOpLogger +func (m NoOpLogger) Fatal(args ...interface{}) {} + +// Fatalf does nothing on a NoOpLogger +func (m NoOpLogger) Fatalf(template string, args ...interface{}) {} diff --git a/tests/evaluator_test.go b/tests/evaluator_test.go index 6b5b2a27..68161750 100644 --- a/tests/evaluator_test.go +++ b/tests/evaluator_test.go @@ -8,6 +8,8 @@ import ( "reflect" "testing" + "github.com/harness/ff-golang-server-sdk/logger" + "github.com/harness/ff-golang-server-sdk/evaluation" "github.com/harness/ff-golang-server-sdk/log" @@ -77,7 +79,7 @@ func TestEvaluator(t *testing.T) { t.Error(err) } repo := repository.New(lruCache) - evaluator, err := evaluation.NewEvaluator(repo, nil) + evaluator, err := evaluation.NewEvaluator(repo, nil, logger.NewNoOpLogger()) if err != nil { t.Error(err) }