11package client
22
33import (
4+ "encoding/json"
45 "errors"
56 "fmt"
67 "runtime/debug"
@@ -22,14 +23,22 @@ import (
2223)
2324
2425const (
25- treatment = "Treatment"
26- treatments = "Treatments"
27- treatmentsByFlagSet = "TreatmentsByFlagSet"
28- treatmentsByFlagSets = "TreatmentsByFlagSets"
29- treatmentWithConfig = "TreatmentWithConfig"
30- treatmentsWithConfig = "TreatmentsWithConfig"
31- treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet"
32- treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets"
26+ treatment = "Treatment"
27+ treatments = "Treatments"
28+ treatmentsByFlagSet = "TreatmentsByFlagSet"
29+ treatmentsByFlagSets = "TreatmentsByFlagSets"
30+ treatmentWithConfig = "TreatmentWithConfig"
31+ treatmentsWithConfig = "TreatmentsWithConfig"
32+ treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet"
33+ treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets"
34+ treatmentWithEvaluationOptions = "TreatmentWithEvaluationOptions"
35+ treatmentsWithEvaluationOptions = "TreatmentsWithEvaluationOptions"
36+ treatmentsByFlagSetWithEvaluationOptions = "TreatmentsByFlagSetWithEvaluationOptions"
37+ treatmentsByFlagSetsWithEvaluationOptions = "TreatmentsByFlagSetsWithEvaluationOptions"
38+ treatmentWithConfigAndEvaluationOptions = "TreatmentWithConfigWithEvaluationOptions"
39+ treatmentsWithConfigAndEvaluationOptions = "TreatmentsWithConfigWithEvaluationOptions"
40+ treatmentsWithConfigByFlagSetAndEvaluationOptions = "TreatmentsWithConfigByFlagSetWithEvaluationOptions"
41+ treatmentsWithConfigByFlagSetsAndEvaluationOptions = "TreatmentsWithConfigByFlagSetsWithEvaluationOptions"
3342)
3443
3544// SplitClient is the entry-point of the split SDK.
@@ -95,7 +104,7 @@ func (c *SplitClient) getEvaluationsResult(matchingKey string, bucketingKey *str
95104}
96105
97106// createImpression creates impression to be stored and used by listener
98- func (c * SplitClient ) createImpression (featureFlag string , bucketingKey * string , evaluationLabel string , matchingKey string , treatment string , changeNumber int64 , disabled bool ) dtos.Impression {
107+ func (c * SplitClient ) createImpression (featureFlag string , bucketingKey * string , evaluationLabel string , matchingKey string , treatment string , changeNumber int64 , disabled bool , properties string ) dtos.Impression {
99108 var label string
100109 if c .factory .cfg .LabelsEnabled {
101110 label = evaluationLabel
@@ -115,6 +124,7 @@ func (c *SplitClient) createImpression(featureFlag string, bucketingKey *string,
115124 Treatment : treatment ,
116125 Time : time .Now ().UTC ().UnixNano () / int64 (time .Millisecond ), // Convert standard timestamp to java's ms timestamps
117126 Disabled : disabled ,
127+ Properties : properties ,
118128 }
119129}
120130
@@ -140,7 +150,7 @@ func (c *SplitClient) storeData(impressions []dtos.Impression, attributes map[st
140150}
141151
142152// doTreatmentCall retrieves treatments of an specific feature flag with configurations object if it is present for a certain key and set of attributes
143- func (c * SplitClient ) doTreatmentCall (key interface {}, featureFlag string , attributes map [string ]interface {}, operation string , metricsLabel string ) (t TreatmentResult ) {
153+ func (c * SplitClient ) doTreatmentCall (key interface {}, featureFlag string , attributes map [string ]interface {}, operation string , metricsLabel string , evaluationOptions * dtos. EvaluationOptions ) (t TreatmentResult ) {
144154 controlTreatment := TreatmentResult {
145155 Treatment : evaluator .Control ,
146156 Config : nil ,
@@ -184,7 +194,7 @@ func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attri
184194 }
185195
186196 c .storeData (
187- []dtos.Impression {c .createImpression (featureFlag , bucketingKey , evaluationResult .Label , matchingKey , evaluationResult .Treatment , evaluationResult .SplitChangeNumber , evaluationResult .ImpressionsDisabled )},
197+ []dtos.Impression {c .createImpression (featureFlag , bucketingKey , evaluationResult .Label , matchingKey , evaluationResult .Treatment , evaluationResult .SplitChangeNumber , evaluationResult .ImpressionsDisabled , serializeProperties ( evaluationOptions ) )},
188198 attributes ,
189199 metricsLabel ,
190200 evaluationResult .EvaluationTime ,
@@ -196,16 +206,44 @@ func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attri
196206 }
197207}
198208
209+ func serializeProperties (opts * dtos.EvaluationOptions ) string {
210+ if opts == nil {
211+ return ""
212+ }
213+ if len (opts .Properties ) == 0 {
214+ return ""
215+ }
216+
217+ properties , err := json .Marshal (opts .Properties )
218+ if err != nil {
219+ return ""
220+ }
221+
222+ return string (properties )
223+ }
224+
199225// Treatment implements the main functionality of split. Retrieve treatments of a specific feature flag
200226// for a certain key and set of attributes
201227func (c * SplitClient ) Treatment (key interface {}, featureFlagName string , attributes map [string ]interface {}) string {
202- return c .doTreatmentCall (key , featureFlagName , attributes , treatment , telemetry .Treatment ).Treatment
228+ return c .doTreatmentCall (key , featureFlagName , attributes , treatment , telemetry .Treatment , nil ).Treatment
203229}
204230
205231// TreatmentWithConfig implements the main functionality of split. Retrieves the treatment of a specific feature flag
206232// with the corresponding configuration if it is present
207233func (c * SplitClient ) TreatmentWithConfig (key interface {}, featureFlagName string , attributes map [string ]interface {}) TreatmentResult {
208- return c .doTreatmentCall (key , featureFlagName , attributes , treatmentWithConfig , telemetry .TreatmentWithConfig )
234+ return c .doTreatmentCall (key , featureFlagName , attributes , treatmentWithConfig , telemetry .TreatmentWithConfig , nil )
235+ }
236+
237+ // TreatmentWithEvaluationOptions implements the main functionality of split. Retrieve treatments of a specific feature flag
238+ // for a certain key and set of attributes
239+ func (c * SplitClient ) TreatmentWithEvaluationOptions (key interface {}, featureFlagName string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) string {
240+ return c .doTreatmentCall (key , featureFlagName , attributes , treatmentWithEvaluationOptions , telemetry .TreatmentWithEvaluationOptions , & evaluationOptions ).Treatment
241+ }
242+
243+ // TreatmentWithConfigAndEvaluationOptions implements the main functionality of split. Retrieves the treatment of a specific feature flag
244+ // with the corresponding configuration if it is present
245+ func (c * SplitClient ) TreatmentWithConfigAndEvaluationOptions (key interface {}, featureFlagName string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) TreatmentResult {
246+ return c .doTreatmentCall (key , featureFlagName , attributes , treatmentWithConfigAndEvaluationOptions , telemetry .TreatmentWithConfigAndEvaluationOptions , & evaluationOptions )
209247}
210248
211249// Generates control treatments
@@ -224,7 +262,7 @@ func (c *SplitClient) generateControlTreatments(featureFlagNames []string, opera
224262 return treatments
225263}
226264
227- func (c * SplitClient ) processResult (result evaluator.Results , operation string , bucketingKey * string , matchingKey string , attributes map [string ]interface {}, metricsLabel string ) (t map [string ]TreatmentResult ) {
265+ func (c * SplitClient ) processResult (result evaluator.Results , operation string , bucketingKey * string , matchingKey string , attributes map [string ]interface {}, metricsLabel string , evaluationOptions * dtos. EvaluationOptions ) (t map [string ]TreatmentResult ) {
228266 var bulkImpressions []dtos.Impression
229267 treatments := make (map [string ]TreatmentResult )
230268 for feature , evaluation := range result .Evaluations {
@@ -234,7 +272,8 @@ func (c *SplitClient) processResult(result evaluator.Results, operation string,
234272 Config : nil ,
235273 }
236274 } else {
237- bulkImpressions = append (bulkImpressions , c .createImpression (feature , bucketingKey , evaluation .Label , matchingKey , evaluation .Treatment , evaluation .SplitChangeNumber , evaluation .ImpressionsDisabled ))
275+ bulkImpressions = append (bulkImpressions , c .createImpression (feature , bucketingKey , evaluation .Label , matchingKey , evaluation .Treatment , evaluation .SplitChangeNumber , evaluation .ImpressionsDisabled , serializeProperties (evaluationOptions )))
276+ //bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled, ""))
238277
239278 treatments [feature ] = TreatmentResult {
240279 Treatment : evaluation .Treatment ,
@@ -247,7 +286,7 @@ func (c *SplitClient) processResult(result evaluator.Results, operation string,
247286}
248287
249288// doTreatmentsCall retrieves treatments of an specific array of feature flag names with configurations object if it is present for a certain key and set of attributes
250- func (c * SplitClient ) doTreatmentsCall (key interface {}, featureFlagNames []string , attributes map [string ]interface {}, operation string , metricsLabel string ) (t map [string ]TreatmentResult ) {
289+ func (c * SplitClient ) doTreatmentsCall (key interface {}, featureFlagNames []string , attributes map [string ]interface {}, operation string , metricsLabel string , evaluationOptions * dtos. EvaluationOptions ) (t map [string ]TreatmentResult ) {
251290 // Set up a guard deferred function to recover if the SDK starts panicking
252291 defer func () {
253292 if r := recover (); r != nil {
@@ -280,11 +319,11 @@ func (c *SplitClient) doTreatmentsCall(key interface{}, featureFlagNames []strin
280319
281320 evaluationsResult := c .getEvaluationsResult (matchingKey , bucketingKey , filteredFeatures , attributes , operation )
282321
283- return c .processResult (evaluationsResult , operation , bucketingKey , matchingKey , attributes , metricsLabel )
322+ return c .processResult (evaluationsResult , operation , bucketingKey , matchingKey , attributes , metricsLabel , evaluationOptions )
284323}
285324
286325// doTreatmentsCallByFlagSets retrieves treatments of a specific array of feature flag names, that belong to flag sets, with configurations object if it is present for a certain key and set of attributes
287- func (c * SplitClient ) doTreatmentsCallByFlagSets (key interface {}, flagSets []string , attributes map [string ]interface {}, operation string , metricsLabel string ) (t map [string ]TreatmentResult ) {
326+ func (c * SplitClient ) doTreatmentsCallByFlagSets (key interface {}, flagSets []string , attributes map [string ]interface {}, operation string , metricsLabel string , evaluationOptions * dtos. EvaluationOptions ) (t map [string ]TreatmentResult ) {
288327 treatments := make (map [string ]TreatmentResult )
289328
290329 // Set up a guard deferred function to recover if the SDK starts panicking
@@ -312,15 +351,25 @@ func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []str
312351
313352 if c .isReady () {
314353 evaluationsResult := c .evaluator .EvaluateFeatureByFlagSets (matchingKey , bucketingKey , flagSets , attributes )
315- treatments = c .processResult (evaluationsResult , operation , bucketingKey , matchingKey , attributes , metricsLabel )
354+ treatments = c .processResult (evaluationsResult , operation , bucketingKey , matchingKey , attributes , metricsLabel , evaluationOptions )
316355 }
317356 return treatments
318357}
319358
320359// Treatments evaluates multiple feature flag names for a single user and set of attributes at once
321360func (c * SplitClient ) Treatments (key interface {}, featureFlagNames []string , attributes map [string ]interface {}) map [string ]string {
322361 treatmentsResult := map [string ]string {}
323- result := c .doTreatmentsCall (key , featureFlagNames , attributes , treatments , telemetry .Treatments )
362+ result := c .doTreatmentsCall (key , featureFlagNames , attributes , treatments , telemetry .Treatments , nil )
363+ for feature , treatmentResult := range result {
364+ treatmentsResult [feature ] = treatmentResult .Treatment
365+ }
366+ return treatmentsResult
367+ }
368+
369+ // TreatmentsWithEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once
370+ func (c * SplitClient ) TreatmentsWithEvaluationOptions (key interface {}, featureFlagNames []string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]string {
371+ treatmentsResult := map [string ]string {}
372+ result := c .doTreatmentsCall (key , featureFlagNames , attributes , treatmentsWithEvaluationOptions , telemetry .TreatmentsWithEvaluationOptions , & evaluationOptions )
324373 for feature , treatmentResult := range result {
325374 treatmentsResult [feature ] = treatmentResult .Treatment
326375 }
@@ -354,7 +403,7 @@ func (c *SplitClient) TreatmentsByFlagSet(key interface{}, flagSet string, attri
354403 if sets == nil {
355404 return treatmentsResult
356405 }
357- result := c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsByFlagSet , telemetry .TreatmentsByFlagSet )
406+ result := c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsByFlagSet , telemetry .TreatmentsByFlagSet , nil )
358407 for feature , treatmentResult := range result {
359408 treatmentsResult [feature ] = treatmentResult .Treatment
360409 }
@@ -368,7 +417,35 @@ func (c *SplitClient) TreatmentsByFlagSets(key interface{}, flagSets []string, a
368417 if flagSets == nil {
369418 return treatmentsResult
370419 }
371- result := c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsByFlagSets , telemetry .TreatmentsByFlagSets )
420+ result := c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsByFlagSets , telemetry .TreatmentsByFlagSets , nil )
421+ for feature , treatmentResult := range result {
422+ treatmentsResult [feature ] = treatmentResult .Treatment
423+ }
424+ return treatmentsResult
425+ }
426+
427+ // TreatmentsByFlagSetWithEvaluationOptions evaluate multiple feature flag names belonging to a flag set for a single user and a set of attributes at once
428+ func (c * SplitClient ) TreatmentsByFlagSetWithEvaluationOptions (key interface {}, flagSet string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]string {
429+ treatmentsResult := map [string ]string {}
430+ sets := c .validateSets ([]string {flagSet })
431+ if sets == nil {
432+ return treatmentsResult
433+ }
434+ result := c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsByFlagSetWithEvaluationOptions , telemetry .TreatmentsByFlagSetWithEvaluationOptions , & evaluationOptions )
435+ for feature , treatmentResult := range result {
436+ treatmentsResult [feature ] = treatmentResult .Treatment
437+ }
438+ return treatmentsResult
439+ }
440+
441+ // TreatmentsByFlagSetsWithEvaluationOptions evaluate multiple feature flag names belonging to flag sets for a single user and a set of attributes at once
442+ func (c * SplitClient ) TreatmentsByFlagSetsWithEvaluationOptions (key interface {}, flagSets []string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]string {
443+ treatmentsResult := map [string ]string {}
444+ flagSets = c .validateSets (flagSets )
445+ if flagSets == nil {
446+ return treatmentsResult
447+ }
448+ result := c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsByFlagSetsWithEvaluationOptions , telemetry .TreatmentsByFlagSetsWithEvaluationOptions , & evaluationOptions )
372449 for feature , treatmentResult := range result {
373450 treatmentsResult [feature ] = treatmentResult .Treatment
374451 }
@@ -389,7 +466,12 @@ func (c *SplitClient) filterSetsAreInConfig(flagSets []string) []string {
389466
390467// TreatmentsWithConfig evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations
391468func (c * SplitClient ) TreatmentsWithConfig (key interface {}, featureFlagNames []string , attributes map [string ]interface {}) map [string ]TreatmentResult {
392- return c .doTreatmentsCall (key , featureFlagNames , attributes , treatmentsWithConfig , telemetry .TreatmentsWithConfig )
469+ return c .doTreatmentsCall (key , featureFlagNames , attributes , treatmentsWithConfig , telemetry .TreatmentsWithConfig , nil )
470+ }
471+
472+ // TreatmentsWithConfigAndEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations
473+ func (c * SplitClient ) TreatmentsWithConfigAndEvaluationOptions (key interface {}, featureFlagNames []string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]TreatmentResult {
474+ return c .doTreatmentsCall (key , featureFlagNames , attributes , treatmentsWithConfigAndEvaluationOptions , telemetry .TreatmentsWithConfigByFlagSetAndEvaluationOptions , & evaluationOptions )
393475}
394476
395477// TreatmentsWithConfigByFlagSet evaluates multiple feature flag names belonging to a flag set for a single user and set of attributes at once and returns configurations
@@ -399,7 +481,17 @@ func (c *SplitClient) TreatmentsWithConfigByFlagSet(key interface{}, flagSet str
399481 if sets == nil {
400482 return treatmentsResult
401483 }
402- return c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsWithConfigByFlagSet , telemetry .TreatmentsWithConfigByFlagSet )
484+ return c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsWithConfigByFlagSet , telemetry .TreatmentsWithConfigByFlagSet , nil )
485+ }
486+
487+ // TreatmentsWithConfigByFlagSetAndEvaluationOptions evaluates multiple feature flag names belonging to a flag set for a single user and set of attributes at once and returns configurations
488+ func (c * SplitClient ) TreatmentsWithConfigByFlagSetAndEvaluationOptions (key interface {}, flagSet string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]TreatmentResult {
489+ treatmentsResult := make (map [string ]TreatmentResult )
490+ sets := c .validateSets ([]string {flagSet })
491+ if sets == nil {
492+ return treatmentsResult
493+ }
494+ return c .doTreatmentsCallByFlagSets (key , sets , attributes , treatmentsWithConfigByFlagSetAndEvaluationOptions , telemetry .TreatmentsWithConfigByFlagSetAndEvaluationOptions , & evaluationOptions )
403495}
404496
405497// TreatmentsWithConfigByFlagSet evaluates multiple feature flag names belonging to a flag sets for a single user and set of attributes at once and returns configurations
@@ -409,7 +501,17 @@ func (c *SplitClient) TreatmentsWithConfigByFlagSets(key interface{}, flagSets [
409501 if flagSets == nil {
410502 return treatmentsResult
411503 }
412- return c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsWithConfigByFlagSets , telemetry .TreatmentsWithConfigByFlagSets )
504+ return c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsWithConfigByFlagSets , telemetry .TreatmentsWithConfigByFlagSets , nil )
505+ }
506+
507+ // TreatmentsWithConfigByFlagSetsAndEvaluationOptions evaluates multiple feature flag names belonging to a flag sets for a single user and set of attributes at once and returns configurations
508+ func (c * SplitClient ) TreatmentsWithConfigByFlagSetsAndEvaluationOptions (key interface {}, flagSets []string , attributes map [string ]interface {}, evaluationOptions dtos.EvaluationOptions ) map [string ]TreatmentResult {
509+ treatmentsResult := make (map [string ]TreatmentResult )
510+ flagSets = c .validateSets (flagSets )
511+ if flagSets == nil {
512+ return treatmentsResult
513+ }
514+ return c .doTreatmentsCallByFlagSets (key , flagSets , attributes , treatmentsWithConfigByFlagSetsAndEvaluationOptions , telemetry .TreatmentsWithConfigByFlagSetsAndEvaluationOptions , & evaluationOptions )
413515}
414516
415517// isDestroyed returns true if the client has been destroyed
0 commit comments