Skip to content

Commit 3cececf

Browse files
FFM-11332 - Refactor evaluation logic to remove inefficiencies in the GetAttr(ibute) function (#155)
* Refactor to remove further inefficiencies in getAttr func
1 parent 47f888f commit 3cececf

8 files changed

+133
-79
lines changed

.harness/Build_ff_golang_server_sdk_1713530975185-pr-trigger-input-set-1713530976580.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.harness/Build_ff_golang_server_sdk_1713530975185-push-trigger-input-set-1713530978099.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.harness/Build_ff_golang_server_sdk_1713968153901-pr-trigger-input-set-1713968155094.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.harness/Build_ff_golang_server_sdk_1713968153901-push-trigger-input-set-1713968156768.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

evaluation/evaluator.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,13 @@ func NewEvaluator(query Query, postEvalCallback PostEvaluateCallback, logger log
8686

8787
func (e Evaluator) evaluateClause(clause *rest.Clause, target *Target) bool {
8888
if clause == nil || len(clause.Values) == 0 || clause.Op == "" {
89-
e.logger.Debugf("Clause cannot be evaluated because operator is either nil, has no values or operation: Clause (%v)", clause)
9089
return false
9190
}
9291

9392
value := clause.Values[0]
9493
attrValue := getAttrValue(target, clause.Attribute)
9594

9695
if clause.Op != segmentMatchOperator && attrValue == "" {
97-
e.logger.Debugf("Operator is not a segment match and attribute value is not valid: Operator (%s), attributeVal (%s)", clause.Op, attrValue)
9896
return false
9997
}
10098

evaluation/evaluator_test.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ func TestEvaluator_JSONVariation(t *testing.T) {
19881988

19891989
// BENCHMARK
19901990
func BenchmarkEvaluateClause_NilClause(b *testing.B) {
1991-
evaluator := Evaluator{}
1991+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
19921992
var clause *rest.Clause = nil
19931993
target := &Target{
19941994
Identifier: "harness",
@@ -1999,7 +1999,7 @@ func BenchmarkEvaluateClause_NilClause(b *testing.B) {
19991999
}
20002000

20012001
func BenchmarkEvaluateClause_EmptyOperator(b *testing.B) {
2002-
evaluator := Evaluator{}
2002+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20032003
clause := &rest.Clause{
20042004
Op: "",
20052005
Values: []string{"harness"},
@@ -2010,7 +2010,7 @@ func BenchmarkEvaluateClause_EmptyOperator(b *testing.B) {
20102010
}
20112011

20122012
func BenchmarkEvaluateClause_NilValues(b *testing.B) {
2013-
evaluator := Evaluator{}
2013+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20142014
clause := &rest.Clause{
20152015
Values: nil,
20162016
}
@@ -2020,7 +2020,7 @@ func BenchmarkEvaluateClause_NilValues(b *testing.B) {
20202020
}
20212021

20222022
func BenchmarkEvaluateClause_EmptyValues(b *testing.B) {
2023-
evaluator := Evaluator{}
2023+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20242024
clause := &rest.Clause{
20252025
Values: []string{},
20262026
}
@@ -2030,7 +2030,7 @@ func BenchmarkEvaluateClause_EmptyValues(b *testing.B) {
20302030
}
20312031

20322032
func BenchmarkEvaluateClause_WrongOperator(b *testing.B) {
2033-
evaluator := Evaluator{}
2033+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20342034
clause := &rest.Clause{
20352035
Attribute: "identifier",
20362036
Op: "greaterthan",
@@ -2045,7 +2045,7 @@ func BenchmarkEvaluateClause_WrongOperator(b *testing.B) {
20452045
}
20462046

20472047
func BenchmarkEvaluateClause_EmptyAttribute(b *testing.B) {
2048-
evaluator := Evaluator{}
2048+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20492049
clause := &rest.Clause{
20502050
Attribute: "",
20512051
Op: "equalOperator",
@@ -2060,7 +2060,7 @@ func BenchmarkEvaluateClause_EmptyAttribute(b *testing.B) {
20602060
}
20612061

20622062
func BenchmarkEvaluateClause_MatchOperator(b *testing.B) {
2063-
evaluator := Evaluator{}
2063+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20642064
clause := &rest.Clause{
20652065
Attribute: "identifier",
20662066
Op: "matchOperator",
@@ -2075,7 +2075,7 @@ func BenchmarkEvaluateClause_MatchOperator(b *testing.B) {
20752075
}
20762076

20772077
func BenchmarkEvaluateClause_MatchOperatorError(b *testing.B) {
2078-
evaluator := Evaluator{}
2078+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20792079
clause := &rest.Clause{
20802080
Attribute: "identifier",
20812081
Op: "matchOperator",
@@ -2090,7 +2090,7 @@ func BenchmarkEvaluateClause_MatchOperatorError(b *testing.B) {
20902090
}
20912091

20922092
func BenchmarkEvaluateClause_InOperator(b *testing.B) {
2093-
evaluator := Evaluator{}
2093+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
20942094
clause := &rest.Clause{
20952095
Attribute: "identifier",
20962096
Op: "inOperator",
@@ -2105,7 +2105,7 @@ func BenchmarkEvaluateClause_InOperator(b *testing.B) {
21052105
}
21062106

21072107
func BenchmarkEvaluateClause_InOperatorNotFound(b *testing.B) {
2108-
evaluator := Evaluator{}
2108+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21092109
clause := &rest.Clause{
21102110
Attribute: "identifier",
21112111
Op: "inOperator",
@@ -2120,7 +2120,7 @@ func BenchmarkEvaluateClause_InOperatorNotFound(b *testing.B) {
21202120
}
21212121

21222122
func BenchmarkEvaluateClause_EqualOperator(b *testing.B) {
2123-
evaluator := Evaluator{}
2123+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21242124
clause := &rest.Clause{
21252125
Attribute: "identifier",
21262126
Op: "equalOperator",
@@ -2135,7 +2135,7 @@ func BenchmarkEvaluateClause_EqualOperator(b *testing.B) {
21352135
}
21362136

21372137
func BenchmarkEvaluateClause_EqualSensitiveOperator(b *testing.B) {
2138-
evaluator := Evaluator{}
2138+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21392139
clause := &rest.Clause{
21402140
Attribute: "identifier",
21412141
Op: "equalSensitiveOperator",
@@ -2150,7 +2150,7 @@ func BenchmarkEvaluateClause_EqualSensitiveOperator(b *testing.B) {
21502150
}
21512151

21522152
func BenchmarkEvaluateClause_GTOperator(b *testing.B) {
2153-
evaluator := Evaluator{}
2153+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21542154
clause := &rest.Clause{
21552155
Attribute: "identifier",
21562156
Op: "gtOperator",
@@ -2165,7 +2165,7 @@ func BenchmarkEvaluateClause_GTOperator(b *testing.B) {
21652165
}
21662166

21672167
func BenchmarkEvaluateClause_GTOperatorNegative(b *testing.B) {
2168-
evaluator := Evaluator{}
2168+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21692169
clause := &rest.Clause{
21702170
Attribute: "identifier",
21712171
Op: "gtOperator",
@@ -2180,7 +2180,7 @@ func BenchmarkEvaluateClause_GTOperatorNegative(b *testing.B) {
21802180
}
21812181

21822182
func BenchmarkEvaluateClause_StartsWithOperator(b *testing.B) {
2183-
evaluator := Evaluator{}
2183+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21842184
clause := &rest.Clause{
21852185
Attribute: "identifier",
21862186
Op: "startsWithOperator",
@@ -2195,7 +2195,7 @@ func BenchmarkEvaluateClause_StartsWithOperator(b *testing.B) {
21952195
}
21962196

21972197
func BenchmarkEvaluateClause_EndsWithOperator(b *testing.B) {
2198-
evaluator := Evaluator{}
2198+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
21992199
clause := &rest.Clause{
22002200
Attribute: "identifier",
22012201
Op: "endsWithOperator",
@@ -2210,7 +2210,7 @@ func BenchmarkEvaluateClause_EndsWithOperator(b *testing.B) {
22102210
}
22112211

22122212
func BenchmarkEvaluateClause_ContainsOperator(b *testing.B) {
2213-
evaluator := Evaluator{}
2213+
evaluator := Evaluator{logger: logger.NoOpLogger{}}
22142214
clause := &rest.Clause{
22152215
Attribute: "identifier",
22162216
Op: "containsOperator",
@@ -2225,7 +2225,7 @@ func BenchmarkEvaluateClause_ContainsOperator(b *testing.B) {
22252225
}
22262226

22272227
func BenchmarkEvaluateClause_SegmentMatchOperator(b *testing.B) {
2228-
evaluator := Evaluator{query: testRepo}
2228+
evaluator := Evaluator{query: testRepo, logger: logger.NoOpLogger{}}
22292229
clause := &rest.Clause{
22302230
Op: "segmentMatchOperator",
22312231
Values: []string{"beta"},

evaluation/util.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package evaluation
22

33
import (
44
"fmt"
5+
"strconv"
56
"strings"
67

8+
jsoniter "github.com/json-iterator/go"
9+
710
"github.com/harness/ff-golang-server-sdk/sdk_codes"
811

912
"github.com/harness/ff-golang-server-sdk/log"
@@ -12,19 +15,36 @@ import (
1215
)
1316

1417
func getAttrValue(target *Target, attr string) string {
15-
if target == nil {
18+
if target == nil || attr == "" {
1619
return ""
1720
}
1821

19-
switch strings.ToLower(attr) {
22+
switch attr {
2023
case "identifier":
2124
return target.Identifier
2225
case "name":
2326
return target.Name
2427
default:
2528
if target.Attributes != nil {
2629
if val, ok := (*target.Attributes)[attr]; ok {
27-
return fmt.Sprint(val)
30+
switch v := val.(type) {
31+
case string:
32+
return v
33+
case int:
34+
return strconv.Itoa(v)
35+
case float64:
36+
return strconv.FormatFloat(v, 'f', -1, 64)
37+
case bool:
38+
return strconv.FormatBool(v)
39+
case map[string]interface{}:
40+
marshalledValue, err := jsoniter.MarshalToString(v)
41+
if err != nil {
42+
return fmt.Sprint(v)
43+
}
44+
return marshalledValue
45+
default:
46+
return fmt.Sprint(v)
47+
}
2848
}
2949
}
3050
}

evaluation/util_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,95 @@ func Test_isTargetInList(t *testing.T) {
437437
})
438438
}
439439
}
440+
441+
// Benchmark scenarios
442+
func BenchmarkGetAttrValueNilTarget(b *testing.B) {
443+
for i := 0; i < b.N; i++ {
444+
getAttrValue(nil, "identifier")
445+
}
446+
}
447+
448+
func BenchmarkGetAttrValueEmptyAttribute(b *testing.B) {
449+
var target Target
450+
for i := 0; i < b.N; i++ {
451+
getAttrValue(&target, "")
452+
}
453+
}
454+
455+
func BenchmarkGetAttrValueIdentifier(b *testing.B) {
456+
var target = Target{Identifier: "1234"}
457+
for i := 0; i < b.N; i++ {
458+
getAttrValue(&target, "identifier")
459+
}
460+
}
461+
462+
func BenchmarkGetAttrValueName(b *testing.B) {
463+
var target = Target{Name: "targetName"}
464+
for i := 0; i < b.N; i++ {
465+
getAttrValue(&target, "name")
466+
}
467+
}
468+
469+
func BenchmarkGetAttrValueUnmatched(b *testing.B) {
470+
var target = Target{}
471+
for i := 0; i < b.N; i++ {
472+
getAttrValue(&target, "unmatched")
473+
}
474+
}
475+
476+
func BenchmarkGetAttrValueStringAttr(b *testing.B) {
477+
attributes := map[string]interface{}{"city": "New York"}
478+
var target = Target{Attributes: &attributes}
479+
for i := 0; i < b.N; i++ {
480+
getAttrValue(&target, "city")
481+
}
482+
}
483+
484+
func BenchmarkGetAttrValueIntegerAttr(b *testing.B) {
485+
attributes := map[string]interface{}{"age": 30}
486+
var target = Target{Attributes: &attributes}
487+
for i := 0; i < b.N; i++ {
488+
getAttrValue(&target, "age")
489+
}
490+
}
491+
492+
func BenchmarkGetAttrValueFloatAttr(b *testing.B) {
493+
attributes := map[string]interface{}{"temperature": 98.6}
494+
var target = Target{Attributes: &attributes}
495+
for i := 0; i < b.N; i++ {
496+
getAttrValue(&target, "temperature")
497+
}
498+
}
499+
500+
func BenchmarkGetAttrValueBoolAttr(b *testing.B) {
501+
attributes := map[string]interface{}{"active": true}
502+
var target = Target{Attributes: &attributes}
503+
for i := 0; i < b.N; i++ {
504+
getAttrValue(&target, "active")
505+
}
506+
}
507+
508+
func BenchmarkGetAttrValueBasicJSON(b *testing.B) {
509+
basicJSON := map[string]interface{}{
510+
"myName": "Stephen",
511+
}
512+
attributes := map[string]interface{}{"basicJson": basicJSON}
513+
var target = Target{Attributes: &attributes}
514+
for i := 0; i < b.N; i++ {
515+
getAttrValue(&target, "basicJson")
516+
}
517+
}
518+
519+
func BenchmarkGetAttrValueComplexJSON(b *testing.B) {
520+
complexJSON := map[string]interface{}{
521+
"config": map[string]interface{}{
522+
"setting": "on",
523+
"level": 5,
524+
},
525+
}
526+
attributes := map[string]interface{}{"complexJSON": complexJSON}
527+
var target = Target{Attributes: &attributes}
528+
for i := 0; i < b.N; i++ {
529+
getAttrValue(&target, "complexJSON")
530+
}
531+
}

0 commit comments

Comments
 (0)