From a70de54cc14d154b54cce9f350ba9178aed76603 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 3 Dec 2025 10:10:45 -0300 Subject: [PATCH 1/7] Added evaluation options for treatments --- go.mod | 2 +- go.sum | 4 +- splitio/client/client.go | 152 +++++++++-- splitio/client/client_test.go | 462 +++++++++++++++++++++++++--------- 4 files changed, 480 insertions(+), 140 deletions(-) diff --git a/go.mod b/go.mod index b77c829..27e26fa 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/splitio/go-client/v6 go 1.18 require ( - github.com/splitio/go-split-commons/v9 v9.0.0 + github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150 github.com/splitio/go-toolkit/v5 v5.4.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 85200b0..c04a131 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/splitio/go-split-commons/v9 v9.0.0 h1:6uHEkBMUUZNhIiop9dyN04gXQUrMXp+X/0uXSytbp+Q= -github.com/splitio/go-split-commons/v9 v9.0.0/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150 h1:rfNMXpXAKXzqM76WNuh+IKNGZ1LBwlyYXAx84tZMw80= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= github.com/splitio/go-toolkit/v5 v5.4.1 h1:srTyvDBJZMUcJ/KiiQDMyjCuELVgTBh2TGRVn0sOXEE= github.com/splitio/go-toolkit/v5 v5.4.1/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/splitio/client/client.go b/splitio/client/client.go index 659a1f7..e7ecda4 100644 --- a/splitio/client/client.go +++ b/splitio/client/client.go @@ -1,6 +1,7 @@ package client import ( + "encoding/json" "errors" "fmt" "runtime/debug" @@ -22,14 +23,22 @@ import ( ) const ( - treatment = "Treatment" - treatments = "Treatments" - treatmentsByFlagSet = "TreatmentsByFlagSet" - treatmentsByFlagSets = "TreatmentsByFlagSets" - treatmentWithConfig = "TreatmentWithConfig" - treatmentsWithConfig = "TreatmentsWithConfig" - treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet" - treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets" + treatment = "Treatment" + treatments = "Treatments" + treatmentsByFlagSet = "TreatmentsByFlagSet" + treatmentsByFlagSets = "TreatmentsByFlagSets" + treatmentWithConfig = "TreatmentWithConfig" + treatmentsWithConfig = "TreatmentsWithConfig" + treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet" + treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets" + treatmentWithEvaluationOptions = "TreatmentWithEvaluationOptions" + treatmentsWithEvaluationOptions = "TreatmentsWithEvaluationOptions" + treatmentsByFlagSetWithEvaluationOptions = "TreatmentsByFlagSetWithEvaluationOptions" + treatmentsByFlagSetsWithEvaluationOptions = "TreatmentsByFlagSetsWithEvaluationOptions" + treatmentWithConfigAndEvaluationOptions = "TreatmentWithConfigWithEvaluationOptions" + treatmentsWithConfigAndEvaluationOptions = "TreatmentsWithConfigWithEvaluationOptions" + treatmentsWithConfigByFlagSetAndEvaluationOptions = "TreatmentsWithConfigByFlagSetWithEvaluationOptions" + treatmentsWithConfigByFlagSetsAndEvaluationOptions = "TreatmentsWithConfigByFlagSetsWithEvaluationOptions" ) // SplitClient is the entry-point of the split SDK. @@ -95,7 +104,7 @@ func (c *SplitClient) getEvaluationsResult(matchingKey string, bucketingKey *str } // createImpression creates impression to be stored and used by listener -func (c *SplitClient) createImpression(featureFlag string, bucketingKey *string, evaluationLabel string, matchingKey string, treatment string, changeNumber int64, disabled bool) dtos.Impression { +func (c *SplitClient) createImpression(featureFlag string, bucketingKey *string, evaluationLabel string, matchingKey string, treatment string, changeNumber int64, disabled bool, properties string) dtos.Impression { var label string if c.factory.cfg.LabelsEnabled { label = evaluationLabel @@ -115,6 +124,7 @@ func (c *SplitClient) createImpression(featureFlag string, bucketingKey *string, Treatment: treatment, Time: time.Now().UTC().UnixNano() / int64(time.Millisecond), // Convert standard timestamp to java's ms timestamps Disabled: disabled, + Properties: properties, } } @@ -140,7 +150,7 @@ func (c *SplitClient) storeData(impressions []dtos.Impression, attributes map[st } // doTreatmentCall retrieves treatments of an specific feature flag with configurations object if it is present for a certain key and set of attributes -func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attributes map[string]interface{}, operation string, metricsLabel string) (t TreatmentResult) { +func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attributes map[string]interface{}, operation string, metricsLabel string, evaluationOptions *dtos.EvaluationOptions) (t TreatmentResult) { controlTreatment := TreatmentResult{ Treatment: evaluator.Control, Config: nil, @@ -184,7 +194,7 @@ func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attri } c.storeData( - []dtos.Impression{c.createImpression(featureFlag, bucketingKey, evaluationResult.Label, matchingKey, evaluationResult.Treatment, evaluationResult.SplitChangeNumber, evaluationResult.ImpressionsDisabled)}, + []dtos.Impression{c.createImpression(featureFlag, bucketingKey, evaluationResult.Label, matchingKey, evaluationResult.Treatment, evaluationResult.SplitChangeNumber, evaluationResult.ImpressionsDisabled, serializeProperties(evaluationOptions))}, attributes, metricsLabel, evaluationResult.EvaluationTime, @@ -196,16 +206,44 @@ func (c *SplitClient) doTreatmentCall(key interface{}, featureFlag string, attri } } +func serializeProperties(opts *dtos.EvaluationOptions) string { + if opts == nil { + return "" + } + if len(opts.Properties) == 0 { + return "" + } + + properties, err := json.Marshal(opts.Properties) + if err != nil { + return "" + } + + return string(properties) +} + // Treatment implements the main functionality of split. Retrieve treatments of a specific feature flag // for a certain key and set of attributes func (c *SplitClient) Treatment(key interface{}, featureFlagName string, attributes map[string]interface{}) string { - return c.doTreatmentCall(key, featureFlagName, attributes, treatment, telemetry.Treatment).Treatment + return c.doTreatmentCall(key, featureFlagName, attributes, treatment, telemetry.Treatment, nil).Treatment } // TreatmentWithConfig implements the main functionality of split. Retrieves the treatment of a specific feature flag // with the corresponding configuration if it is present func (c *SplitClient) TreatmentWithConfig(key interface{}, featureFlagName string, attributes map[string]interface{}) TreatmentResult { - return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfig, telemetry.TreatmentWithConfig) + return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfig, telemetry.TreatmentWithConfig, nil) +} + +// TreatmentWithEvaluationOptions implements the main functionality of split. Retrieve treatments of a specific feature flag +// for a certain key and set of attributes +func (c *SplitClient) TreatmentWithEvaluationOptions(key interface{}, featureFlagName string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) string { + return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithEvaluationOptions, telemetry.TreatmentWithEvaluationOptions, &evaluationOptions).Treatment +} + +// TreatmentWithConfigAndEvaluationOptions implements the main functionality of split. Retrieves the treatment of a specific feature flag +// with the corresponding configuration if it is present +func (c *SplitClient) TreatmentWithConfigAndEvaluationOptions(key interface{}, featureFlagName string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) TreatmentResult { + return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfigAndEvaluationOptions, telemetry.TreatmentWithConfigAndEvaluationOptions, &evaluationOptions) } // Generates control treatments @@ -224,7 +262,7 @@ func (c *SplitClient) generateControlTreatments(featureFlagNames []string, opera return treatments } -func (c *SplitClient) processResult(result evaluator.Results, operation string, bucketingKey *string, matchingKey string, attributes map[string]interface{}, metricsLabel string) (t map[string]TreatmentResult) { +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) { var bulkImpressions []dtos.Impression treatments := make(map[string]TreatmentResult) for feature, evaluation := range result.Evaluations { @@ -234,7 +272,8 @@ func (c *SplitClient) processResult(result evaluator.Results, operation string, Config: nil, } } else { - bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled)) + bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled, serializeProperties(evaluationOptions))) + //bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled, "")) treatments[feature] = TreatmentResult{ Treatment: evaluation.Treatment, @@ -247,7 +286,7 @@ func (c *SplitClient) processResult(result evaluator.Results, operation string, } // 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 -func (c *SplitClient) doTreatmentsCall(key interface{}, featureFlagNames []string, attributes map[string]interface{}, operation string, metricsLabel string) (t map[string]TreatmentResult) { +func (c *SplitClient) doTreatmentsCall(key interface{}, featureFlagNames []string, attributes map[string]interface{}, operation string, metricsLabel string, evaluationOptions *dtos.EvaluationOptions) (t map[string]TreatmentResult) { // Set up a guard deferred function to recover if the SDK starts panicking defer func() { if r := recover(); r != nil { @@ -280,11 +319,11 @@ func (c *SplitClient) doTreatmentsCall(key interface{}, featureFlagNames []strin evaluationsResult := c.getEvaluationsResult(matchingKey, bucketingKey, filteredFeatures, attributes, operation) - return c.processResult(evaluationsResult, operation, bucketingKey, matchingKey, attributes, metricsLabel) + return c.processResult(evaluationsResult, operation, bucketingKey, matchingKey, attributes, metricsLabel, evaluationOptions) } // 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 -func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}, operation string, metricsLabel string) (t map[string]TreatmentResult) { +func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}, operation string, metricsLabel string, evaluationOptions *dtos.EvaluationOptions) (t map[string]TreatmentResult) { treatments := make(map[string]TreatmentResult) // Set up a guard deferred function to recover if the SDK starts panicking @@ -312,7 +351,7 @@ func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []str if c.isReady() { evaluationsResult := c.evaluator.EvaluateFeatureByFlagSets(matchingKey, bucketingKey, flagSets, attributes) - treatments = c.processResult(evaluationsResult, operation, bucketingKey, matchingKey, attributes, metricsLabel) + treatments = c.processResult(evaluationsResult, operation, bucketingKey, matchingKey, attributes, metricsLabel, evaluationOptions) } return treatments } @@ -320,7 +359,17 @@ func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []str // Treatments evaluates multiple feature flag names for a single user and set of attributes at once func (c *SplitClient) Treatments(key interface{}, featureFlagNames []string, attributes map[string]interface{}) map[string]string { treatmentsResult := map[string]string{} - result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatments, telemetry.Treatments) + result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatments, telemetry.Treatments, nil) + for feature, treatmentResult := range result { + treatmentsResult[feature] = treatmentResult.Treatment + } + return treatmentsResult +} + +// TreatmentsWithEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once +func (c *SplitClient) TreatmentsWithEvaluationOptions(key interface{}, featureFlagNames []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { + treatmentsResult := map[string]string{} + result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithEvaluationOptions, telemetry.TreatmentsWithEvaluationOptions, &evaluationOptions) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -354,7 +403,7 @@ func (c *SplitClient) TreatmentsByFlagSet(key interface{}, flagSet string, attri if sets == nil { return treatmentsResult } - result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSet, telemetry.TreatmentsByFlagSet) + result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSet, telemetry.TreatmentsByFlagSet, nil) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -368,7 +417,35 @@ func (c *SplitClient) TreatmentsByFlagSets(key interface{}, flagSets []string, a if flagSets == nil { return treatmentsResult } - result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSets, telemetry.TreatmentsByFlagSets) + result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSets, telemetry.TreatmentsByFlagSets, nil) + for feature, treatmentResult := range result { + treatmentsResult[feature] = treatmentResult.Treatment + } + return treatmentsResult +} + +// TreatmentsByFlagSetWithEvaluationOptions evaluate multiple feature flag names belonging to a flag set for a single user and a set of attributes at once +func (c *SplitClient) TreatmentsByFlagSetWithEvaluationOptions(key interface{}, flagSet string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { + treatmentsResult := map[string]string{} + sets := c.validateSets([]string{flagSet}) + if sets == nil { + return treatmentsResult + } + result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSetWithEvaluationOptions, telemetry.TreatmentsByFlagSetWithEvaluationOptions, &evaluationOptions) + for feature, treatmentResult := range result { + treatmentsResult[feature] = treatmentResult.Treatment + } + return treatmentsResult +} + +// TreatmentsByFlagSetsWithEvaluationOptions evaluate multiple feature flag names belonging to flag sets for a single user and a set of attributes at once +func (c *SplitClient) TreatmentsByFlagSetsWithEvaluationOptions(key interface{}, flagSets []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { + treatmentsResult := map[string]string{} + flagSets = c.validateSets(flagSets) + if flagSets == nil { + return treatmentsResult + } + result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSetsWithEvaluationOptions, telemetry.TreatmentsByFlagSetsWithEvaluationOptions, &evaluationOptions) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -389,7 +466,12 @@ func (c *SplitClient) filterSetsAreInConfig(flagSets []string) []string { // TreatmentsWithConfig evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations func (c *SplitClient) TreatmentsWithConfig(key interface{}, featureFlagNames []string, attributes map[string]interface{}) map[string]TreatmentResult { - return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfig, telemetry.TreatmentsWithConfig) + return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfig, telemetry.TreatmentsWithConfig, nil) +} + +// TreatmentsWithConfigAndEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations +func (c *SplitClient) TreatmentsWithConfigAndEvaluationOptions(key interface{}, featureFlagNames []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { + return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfigAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetAndEvaluationOptions, &evaluationOptions) } // 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 if sets == nil { return treatmentsResult } - return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSet, telemetry.TreatmentsWithConfigByFlagSet) + return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSet, telemetry.TreatmentsWithConfigByFlagSet, nil) +} + +// TreatmentsWithConfigByFlagSetAndEvaluationOptions evaluates multiple feature flag names belonging to a flag set for a single user and set of attributes at once and returns configurations +func (c *SplitClient) TreatmentsWithConfigByFlagSetAndEvaluationOptions(key interface{}, flagSet string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { + treatmentsResult := make(map[string]TreatmentResult) + sets := c.validateSets([]string{flagSet}) + if sets == nil { + return treatmentsResult + } + return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSetAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetAndEvaluationOptions, &evaluationOptions) } // 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 [ if flagSets == nil { return treatmentsResult } - return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSets, telemetry.TreatmentsWithConfigByFlagSets) + return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSets, telemetry.TreatmentsWithConfigByFlagSets, nil) +} + +// TreatmentsWithConfigByFlagSetsAndEvaluationOptions evaluates multiple feature flag names belonging to a flag sets for a single user and set of attributes at once and returns configurations +func (c *SplitClient) TreatmentsWithConfigByFlagSetsAndEvaluationOptions(key interface{}, flagSets []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { + treatmentsResult := make(map[string]TreatmentResult) + flagSets = c.validateSets(flagSets) + if flagSets == nil { + return treatmentsResult + } + return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSetsAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetsAndEvaluationOptions, &evaluationOptions) } // isDestroyed returns true if the client has been destroyed diff --git a/splitio/client/client_test.go b/splitio/client/client_test.go index 7cfaf06..adfe919 100644 --- a/splitio/client/client_test.go +++ b/splitio/client/client_test.go @@ -18,6 +18,7 @@ import ( "github.com/splitio/go-client/v6/splitio/conf" impressionlistener "github.com/splitio/go-client/v6/splitio/impressionListener" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" commonsCfg "github.com/splitio/go-split-commons/v9/conf" "github.com/splitio/go-split-commons/v9/dtos" @@ -229,31 +230,52 @@ func TestClientGetTreatment(t *testing.T) { } } +func TestClientGetTreatmentWithEvaluationProperties(t *testing.T) { + factory := getFactory() + client := factory.Client() + client.evaluator = &mockEvaluator{} + factory.status.Store(sdkStatusReady) + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, + }, + } + expectedTreatment(client.TreatmentWithEvaluationOptions("key", "feature", nil, opts), "TreatmentA", t) + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + impression := impressions[0] + + assert.Equal(t, "aLabel", impression.Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impression.Properties, "Should have properties") + + client.factory.cfg.LabelsEnabled = false + expectedTreatment(client.Treatment("key", "feature2", nil), "TreatmentB", t) + + impressions, _ = impressionsQueue.PopN(5000) + impression = impressions[0] + assert.Equal(t, "", impression.Label, "Impression should have label when labelsEnabled is true") +} + func TestClientGetTreatmentByFlagSet(t *testing.T) { factory := getFactoryByFlagSets() client := factory.Client() - client.evaluator = evaluatorMock.MockEvaluator{ - EvaluateFeatureByFlagSetsCall: func(key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}) evaluator.Results { - results := evaluator.Results{ - Evaluations: make(map[string]evaluator.Result), - EvaluationTime: 0, - } - for _, flagSet := range flagSets { - switch flagSet { - case "set1": - results.Evaluations["feature"] = evaluator.Result{ - EvaluationTime: 0, - Label: "aLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentA", - } - default: - t.Error("Should be set1 or set2") - } - } - return results - }, + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock + factory.status.Store(sdkStatusReady) res := client.TreatmentsByFlagSet("user1", "set1", nil) @@ -261,38 +283,68 @@ func TestClientGetTreatmentByFlagSet(t *testing.T) { expectedTreatment(res["feature"], "TreatmentA", t) } +func TestClientGetTreatmentByFlagSetWithEvaluationProperties(t *testing.T) { + factory := getFactoryByFlagSets() + client := factory.Client() + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock + + factory.status.Store(sdkStatusReady) + + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, + }, + } + + res := client.TreatmentsByFlagSetWithEvaluationOptions("user1", "set1", nil, opts) + + expectedTreatment(res["feature"], "TreatmentA", t) + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + impression := impressions[0] + + assert.Equal(t, "aLabel", impression.Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impression.Properties, "Should have properties") +} + func TestClientGetTreatmentByFlagSets(t *testing.T) { factory := getFactory() client := factory.Client() - client.evaluator = evaluatorMock.MockEvaluator{ - EvaluateFeatureByFlagSetsCall: func(key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}) evaluator.Results { - results := evaluator.Results{ - Evaluations: make(map[string]evaluator.Result), - EvaluationTime: 0, - } - for _, flagSet := range flagSets { - switch flagSet { - case "set1": - results.Evaluations["feature"] = evaluator.Result{ - EvaluationTime: 0, - Label: "aLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentA", - } - case "set2": - results.Evaluations["feature2"] = evaluator.Result{ - EvaluationTime: 0, - Label: "bLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentB", - } - default: - t.Error("Should be set1 or set2") - } - } - return results - }, + evaluatorMock := evaluatorMock.MockEvaluator{} + + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + results.Evaluations["feature2"] = evaluator.Result{ + EvaluationTime: 0, + Label: "bLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentB", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock factory.status.Store(sdkStatusReady) res := client.TreatmentsByFlagSets("user1", []string{"set1", "set2"}, nil) @@ -301,31 +353,71 @@ func TestClientGetTreatmentByFlagSets(t *testing.T) { expectedTreatment(res["feature2"], "TreatmentB", t) } -func TestClientGetTreatmentWithConfigByFlagSet(t *testing.T) { +func TestClientGetTreatmentByFlagSetsWithEvaluationProperties(t *testing.T) { factory := getFactory() client := factory.Client() - client.evaluator = evaluatorMock.MockEvaluator{ - EvaluateFeatureByFlagSetsCall: func(key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}) evaluator.Results { - results := evaluator.Results{ - Evaluations: make(map[string]evaluator.Result), - EvaluationTime: 0, - } - for _, flagSet := range flagSets { - switch flagSet { - case "set1": - results.Evaluations["feature"] = evaluator.Result{ - EvaluationTime: 0, - Label: "aLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentA", - } - default: - t.Error("Should be set1 or set2") - } - } - return results + evaluatorMock := evaluatorMock.MockEvaluator{} + + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + results.Evaluations["feature2"] = evaluator.Result{ + EvaluationTime: 0, + Label: "bLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentB", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock + factory.status.Store(sdkStatusReady) + + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, }, } + + res := client.TreatmentsByFlagSetsWithEvaluationOptions("user1", []string{"set1", "set2"}, nil, opts) + + expectedTreatment(res["feature"], "TreatmentA", t) + expectedTreatment(res["feature2"], "TreatmentB", t) + + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + for i := range impressions { + if impressions[i].FeatureName == "feature" { + assert.Equal(t, "aLabel", impressions[i].Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impressions[i].Properties, "Should have properties") + } + } +} + +func TestClientGetTreatmentWithConfigByFlagSet(t *testing.T) { + factory := getFactory() + client := factory.Client() + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock factory.status.Store(sdkStatusReady) res := client.TreatmentsWithConfigByFlagSet("user1", "set1", nil) @@ -333,38 +425,67 @@ func TestClientGetTreatmentWithConfigByFlagSet(t *testing.T) { expectedTreatment(res["feature"].Treatment, "TreatmentA", t) } -func TestClientGetTreatmentWithConfigByFlagSets(t *testing.T) { +func TestClientGetTreatmentWithConfigByFlagSetAndEvaluationProperties(t *testing.T) { factory := getFactory() client := factory.Client() - client.evaluator = evaluatorMock.MockEvaluator{ - EvaluateFeatureByFlagSetsCall: func(key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}) evaluator.Results { - results := evaluator.Results{ - Evaluations: make(map[string]evaluator.Result), - EvaluationTime: 0, - } - for _, flagSet := range flagSets { - switch flagSet { - case "set1": - results.Evaluations["feature"] = evaluator.Result{ - EvaluationTime: 0, - Label: "aLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentA", - } - case "set2": - results.Evaluations["feature2"] = evaluator.Result{ - EvaluationTime: 0, - Label: "bLabel", - SplitChangeNumber: 123, - Treatment: "TreatmentB", - } - default: - t.Error("Should be set1 or set2") - } - } - return results + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock + factory.status.Store(sdkStatusReady) + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, }, } + + res := client.TreatmentsWithConfigByFlagSetAndEvaluationOptions("user1", "set1", nil, opts) + + expectedTreatment(res["feature"].Treatment, "TreatmentA", t) + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + for i := range impressions { + if impressions[i].FeatureName == "feature" { + assert.Equal(t, "aLabel", impressions[i].Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impressions[i].Properties, "Should have properties") + } + } +} + +func TestClientGetTreatmentWithConfigByFlagSets(t *testing.T) { + factory := getFactory() + client := factory.Client() + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + results.Evaluations["feature2"] = evaluator.Result{ + EvaluationTime: 0, + Label: "bLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentB", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock factory.status.Store(sdkStatusReady) res := client.TreatmentsWithConfigByFlagSets("user1", []string{"set1", "set2"}, nil) @@ -373,6 +494,52 @@ func TestClientGetTreatmentWithConfigByFlagSets(t *testing.T) { expectedTreatment(res["feature2"].Treatment, "TreatmentB", t) } +func TestClientGetTreatmentWithConfigByFlagSetsAndEvaluationOptions(t *testing.T) { + factory := getFactory() + client := factory.Client() + evaluatorMock := evaluatorMock.MockEvaluator{} + results := evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + } + results.Evaluations["feature"] = evaluator.Result{ + EvaluationTime: 0, + Label: "aLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentA", + } + results.Evaluations["feature2"] = evaluator.Result{ + EvaluationTime: 0, + Label: "bLabel", + SplitChangeNumber: 123, + Treatment: "TreatmentB", + } + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(results) + client.evaluator = evaluatorMock + factory.status.Store(sdkStatusReady) + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, + }, + } + + res := client.TreatmentsWithConfigByFlagSetsAndEvaluationOptions("user1", []string{"set1", "set2"}, nil, opts) + + expectedTreatment(res["feature"].Treatment, "TreatmentA", t) + expectedTreatment(res["feature2"].Treatment, "TreatmentB", t) + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + for i := range impressions { + if impressions[i].FeatureName == "feature" { + assert.Equal(t, "aLabel", impressions[i].Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impressions[i].Properties, "Should have properties") + } + } +} + func TestTreatments(t *testing.T) { factory := getFactory() client := factory.Client() @@ -385,6 +552,36 @@ func TestTreatments(t *testing.T) { expectedTreatment(res["notFeature"], evaluator.Control, t) } +func TestTreatmentsWithEvaluationOptions(t *testing.T) { + factory := getFactory() + client := factory.Client() + client.evaluator = &mockEvaluator{} + factory.status.Store(sdkStatusReady) + + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, + }, + } + + res := client.TreatmentsWithEvaluationOptions("user1", []string{"feature", "notFeature"}, nil, opts) + + expectedTreatment(res["feature"], "TreatmentA", t) + expectedTreatment(res["notFeature"], evaluator.Control, t) + + impressionsQueue := client.impressions.(storage.ImpressionStorage) + impressions, _ := impressionsQueue.PopN(5000) + for i := range impressions { + if impressions[i].FeatureName == "feature" { + assert.Equal(t, "aLabel", impressions[i].Label, "Impression should have label when labelsEnabled is true") + assert.Equal(t, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}", impressions[i].Properties, "Should have properties") + } + } +} + func TestLocalhostMode(t *testing.T) { file, err := ioutil.TempFile("", "splitio_tests") if err != nil { @@ -490,14 +687,12 @@ func TestClientPanicking(t *testing.T) { } client := factory.Client() - client.evaluator = evaluatorMock.MockEvaluator{ - EvaluateFeatureCall: func(key string, bucketingKey *string, feature string, attributes map[string]interface{}) *evaluator.Result { - panic("Testing panicking") - }, - EvaluateFeaturesCall: func(key string, bucketingKey *string, features []string, attributes map[string]interface{}) evaluator.Results { - panic("Testing panicking") - }, - } + evaluatorMock := evaluatorMock.MockEvaluator{} + evaluatorMock.On("EvaluateFeatureByFlagSets", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Once().Return(evaluator.Results{ + Evaluations: make(map[string]evaluator.Result), + EvaluationTime: 0, + }) + client.evaluator = evaluatorMock factory.status.Store(sdkStatusReady) expectedTreatment(client.Treatment("key", "some", nil), evaluator.Control, t) @@ -612,11 +807,12 @@ func (i *ImpressionListenerTest) LogImpression(data impressionlistener.ILObject) ilTest["Version"] = data.SDKLanguageVersion ilTest["InstanceName"] = data.InstanceID ilTest["Pt"] = data.Impression.Pt + ilTest["Properties"] = data.Impression.Properties ilResult[data.Impression.FeatureName] = ilTest } -func compareListener(ilTest map[string]interface{}, f string, k string, l string, t string, c int64, b string, a string, i string, v string) bool { +func compareListener(ilTest map[string]interface{}, f string, k string, l string, t string, c int64, b string, a string, i string, v string, p string) bool { if ilTest["FeatureName"] != f || ilTest["KeyName"] != k || ilTest["Label"] != l || ilTest["Treatment"] != t || ilTest["ChangeNumber"] != c || ilTest["BucketingKey"] != b { return false } @@ -626,6 +822,9 @@ func compareListener(ilTest map[string]interface{}, f string, k string, l string if ilTest["InstanceName"] != i { return false } + if ilTest["Properties"] != p { + return false + } attr1, _ := ilTest["Attributes"].(map[string]interface{}) return attr1["One"] == a } @@ -690,7 +889,7 @@ func TestImpressionListener(t *testing.T) { expectedTreatment(client.Treatment("user1", "feature", attributes), "TreatmentA", t) expectedVersion := "go-" + splitio.Version - if !compareListener(ilResult["feature"].(map[string]interface{}), "feature", "user1", "aLabel", "TreatmentA", int64(123), "", "test", "ip-123-123-123-123", expectedVersion) { + if !compareListener(ilResult["feature"].(map[string]interface{}), "feature", "user1", "aLabel", "TreatmentA", int64(123), "", "test", "ip-123-123-123-123", expectedVersion, "") { t.Error("Impression should match") } ilResult = make(map[string]interface{}) @@ -715,11 +914,49 @@ func TestImpressionListenerForTreatments(t *testing.T) { expectedVersion := "go-" + splitio.Version - if !compareListener(ilResult["feature"].(map[string]interface{}), "feature", "user1", "aLabel", "TreatmentA", int64(123), "", "test", "ip-123-123-123-123", expectedVersion) { + if !compareListener(ilResult["feature"].(map[string]interface{}), "feature", "user1", "aLabel", "TreatmentA", int64(123), "", "test", "ip-123-123-123-123", expectedVersion, "") { t.Error("Impression should match") } - if !compareListener(ilResult["feature2"].(map[string]interface{}), "feature2", "user1", "bLabel", "TreatmentB", int64(123), "", "test", "ip-123-123-123-123", expectedVersion) { + if !compareListener(ilResult["feature2"].(map[string]interface{}), "feature2", "user1", "bLabel", "TreatmentB", int64(123), "", "test", "ip-123-123-123-123", expectedVersion, "") { + t.Error("Impression should match") + } + ilResult = make(map[string]interface{}) + + delete(ilResult, "feature") + delete(ilResult, "feature2") +} + +func TestImpressionListenerForTreatmentsWithEvaluationOptions(t *testing.T) { + client := getClientForListener() + + attributes := make(map[string]interface{}) + attributes["One"] = "test" + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "userId": "123", + "age": 30, + "premium": true, + "balance": 99.5, + }, + } + + res := client.TreatmentsWithEvaluationOptions("user1", []string{"feature", "feature2"}, attributes, opts) + + expectedTreatment(res["feature"], "TreatmentA", t) + expectedTreatment(res["feature2"], "TreatmentB", t) + + if len(ilResult) != 2 { + t.Error("Error on ImpressionListener") + } + + expectedVersion := "go-" + splitio.Version + + if !compareListener(ilResult["feature"].(map[string]interface{}), "feature", "user1", "aLabel", "TreatmentA", int64(123), "", "test", "ip-123-123-123-123", expectedVersion, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}") { + t.Error("Impression should match") + } + + if !compareListener(ilResult["feature2"].(map[string]interface{}), "feature2", "user1", "bLabel", "TreatmentB", int64(123), "", "test", "ip-123-123-123-123", expectedVersion, "{\"age\":30,\"balance\":99.5,\"premium\":true,\"userId\":\"123\"}") { t.Error("Impression should match") } ilResult = make(map[string]interface{}) @@ -946,6 +1183,7 @@ func TestBlockUntilReadyInMemoryError(t *testing.T) { "", "test", sdkConf.InstanceName, expectedVersion, + "", ) { t.Error("Impression should match") } @@ -1108,13 +1346,13 @@ func TestBlockUntilReadyInMemoryOk(t *testing.T) { } expectedTreatment(client.Treatment("not_ready2", "not_ready2", attributes), evaluator.Control, t) - if !compareListener(ilResult["not_ready2"].(map[string]interface{}), "not_ready2", "not_ready2", "not ready", "control", int64(0), "", "test", sdkConf.InstanceName, expectedVersion) { + if !compareListener(ilResult["not_ready2"].(map[string]interface{}), "not_ready2", "not_ready2", "not ready", "control", int64(0), "", "test", sdkConf.InstanceName, expectedVersion, "") { t.Error("Impression should match") } result := client.Treatments("not_ready3", []string{"not_ready3"}, attributes) expectedTreatment(result["not_ready3"], evaluator.Control, t) - if !compareListener(ilResult["not_ready3"].(map[string]interface{}), "not_ready3", "not_ready3", "not ready", "control", int64(0), "", "test", sdkConf.InstanceName, expectedVersion) { + if !compareListener(ilResult["not_ready3"].(map[string]interface{}), "not_ready3", "not_ready3", "not ready", "control", int64(0), "", "test", sdkConf.InstanceName, expectedVersion, "") { t.Error("Impression should match") } ilResult = make(map[string]interface{}) From dd17f1c3ba8e1fd094ba0f63a13afd0a229b52e6 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 5 Dec 2025 11:38:14 -0300 Subject: [PATCH 2/7] Updated treatments functions --- splitio/client/client.go | 161 ++++++++++++---------------------- splitio/client/client_test.go | 14 +-- 2 files changed, 62 insertions(+), 113 deletions(-) diff --git a/splitio/client/client.go b/splitio/client/client.go index e7ecda4..880d160 100644 --- a/splitio/client/client.go +++ b/splitio/client/client.go @@ -23,22 +23,14 @@ import ( ) const ( - treatment = "Treatment" - treatments = "Treatments" - treatmentsByFlagSet = "TreatmentsByFlagSet" - treatmentsByFlagSets = "TreatmentsByFlagSets" - treatmentWithConfig = "TreatmentWithConfig" - treatmentsWithConfig = "TreatmentsWithConfig" - treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet" - treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets" - treatmentWithEvaluationOptions = "TreatmentWithEvaluationOptions" - treatmentsWithEvaluationOptions = "TreatmentsWithEvaluationOptions" - treatmentsByFlagSetWithEvaluationOptions = "TreatmentsByFlagSetWithEvaluationOptions" - treatmentsByFlagSetsWithEvaluationOptions = "TreatmentsByFlagSetsWithEvaluationOptions" - treatmentWithConfigAndEvaluationOptions = "TreatmentWithConfigWithEvaluationOptions" - treatmentsWithConfigAndEvaluationOptions = "TreatmentsWithConfigWithEvaluationOptions" - treatmentsWithConfigByFlagSetAndEvaluationOptions = "TreatmentsWithConfigByFlagSetWithEvaluationOptions" - treatmentsWithConfigByFlagSetsAndEvaluationOptions = "TreatmentsWithConfigByFlagSetsWithEvaluationOptions" + treatment = "Treatment" + treatments = "Treatments" + treatmentsByFlagSet = "TreatmentsByFlagSet" + treatmentsByFlagSets = "TreatmentsByFlagSets" + treatmentWithConfig = "TreatmentWithConfig" + treatmentsWithConfig = "TreatmentsWithConfig" + treatmentsWithConfigByFlagSet = "TreatmentsWithConfigByFlagSet" + treatmentsWithConfigByFlagSets = "TreatmentsWithConfigByFlagSets" ) // SplitClient is the entry-point of the split SDK. @@ -63,6 +55,22 @@ type TreatmentResult struct { Config *string `json:"config"` } +type options struct { + evaluationOptions *dtos.EvaluationOptions +} + +type OptFn = func(o *options) + +func (c *SplitClient) WithEvaluationOptions(e *dtos.EvaluationOptions) OptFn { + return func(o *options) { o.evaluationOptions = e } +} + +func defaultOpts() options { + return options{ + evaluationOptions: nil, + } +} + // getEvaluationResult calls evaluation for one particular feature flag func (c *SplitClient) getEvaluationResult(matchingKey string, bucketingKey *string, featureFlag string, attributes map[string]interface{}, operation string) *evaluator.Result { if c.isReady() { @@ -224,26 +232,24 @@ func serializeProperties(opts *dtos.EvaluationOptions) string { // Treatment implements the main functionality of split. Retrieve treatments of a specific feature flag // for a certain key and set of attributes -func (c *SplitClient) Treatment(key interface{}, featureFlagName string, attributes map[string]interface{}) string { - return c.doTreatmentCall(key, featureFlagName, attributes, treatment, telemetry.Treatment, nil).Treatment +func (c *SplitClient) Treatment(key interface{}, featureFlagName string, attributes map[string]interface{}, optFns ...OptFn) string { + options := getOptions(optFns...) + return c.doTreatmentCall(key, featureFlagName, attributes, treatment, telemetry.Treatment, options.evaluationOptions).Treatment } -// TreatmentWithConfig implements the main functionality of split. Retrieves the treatment of a specific feature flag -// with the corresponding configuration if it is present -func (c *SplitClient) TreatmentWithConfig(key interface{}, featureFlagName string, attributes map[string]interface{}) TreatmentResult { - return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfig, telemetry.TreatmentWithConfig, nil) -} - -// TreatmentWithEvaluationOptions implements the main functionality of split. Retrieve treatments of a specific feature flag -// for a certain key and set of attributes -func (c *SplitClient) TreatmentWithEvaluationOptions(key interface{}, featureFlagName string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) string { - return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithEvaluationOptions, telemetry.TreatmentWithEvaluationOptions, &evaluationOptions).Treatment +func getOptions(optFns ...OptFn) options { + options := defaultOpts() + for _, optFn := range optFns { + optFn(&options) + } + return options } -// TreatmentWithConfigAndEvaluationOptions implements the main functionality of split. Retrieves the treatment of a specific feature flag +// TreatmentWithConfig implements the main functionality of split. Retrieves the treatment of a specific feature flag // with the corresponding configuration if it is present -func (c *SplitClient) TreatmentWithConfigAndEvaluationOptions(key interface{}, featureFlagName string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) TreatmentResult { - return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfigAndEvaluationOptions, telemetry.TreatmentWithConfigAndEvaluationOptions, &evaluationOptions) +func (c *SplitClient) TreatmentWithConfig(key interface{}, featureFlagName string, attributes map[string]interface{}, optFns ...OptFn) TreatmentResult { + options := getOptions(optFns...) + return c.doTreatmentCall(key, featureFlagName, attributes, treatmentWithConfig, telemetry.TreatmentWithConfig, options.evaluationOptions) } // Generates control treatments @@ -357,19 +363,10 @@ func (c *SplitClient) doTreatmentsCallByFlagSets(key interface{}, flagSets []str } // Treatments evaluates multiple feature flag names for a single user and set of attributes at once -func (c *SplitClient) Treatments(key interface{}, featureFlagNames []string, attributes map[string]interface{}) map[string]string { +func (c *SplitClient) Treatments(key interface{}, featureFlagNames []string, attributes map[string]interface{}, optFns ...OptFn) map[string]string { + options := getOptions(optFns...) treatmentsResult := map[string]string{} - result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatments, telemetry.Treatments, nil) - for feature, treatmentResult := range result { - treatmentsResult[feature] = treatmentResult.Treatment - } - return treatmentsResult -} - -// TreatmentsWithEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once -func (c *SplitClient) TreatmentsWithEvaluationOptions(key interface{}, featureFlagNames []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { - treatmentsResult := map[string]string{} - result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithEvaluationOptions, telemetry.TreatmentsWithEvaluationOptions, &evaluationOptions) + result := c.doTreatmentsCall(key, featureFlagNames, attributes, treatments, telemetry.Treatments, options.evaluationOptions) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -397,13 +394,14 @@ func (c *SplitClient) validateSets(flagSets []string) []string { } // Treatments evaluate multiple feature flag names belonging to a flag set for a single user and a set of attributes at once -func (c *SplitClient) TreatmentsByFlagSet(key interface{}, flagSet string, attributes map[string]interface{}) map[string]string { +func (c *SplitClient) TreatmentsByFlagSet(key interface{}, flagSet string, attributes map[string]interface{}, optFns ...OptFn) map[string]string { + options := getOptions(optFns...) treatmentsResult := map[string]string{} sets := c.validateSets([]string{flagSet}) if sets == nil { return treatmentsResult } - result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSet, telemetry.TreatmentsByFlagSet, nil) + result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSet, telemetry.TreatmentsByFlagSet, options.evaluationOptions) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -411,41 +409,14 @@ func (c *SplitClient) TreatmentsByFlagSet(key interface{}, flagSet string, attri } // Treatments evaluate multiple feature flag names belonging to flag sets for a single user and a set of attributes at once -func (c *SplitClient) TreatmentsByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}) map[string]string { - treatmentsResult := map[string]string{} - flagSets = c.validateSets(flagSets) - if flagSets == nil { - return treatmentsResult - } - result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSets, telemetry.TreatmentsByFlagSets, nil) - for feature, treatmentResult := range result { - treatmentsResult[feature] = treatmentResult.Treatment - } - return treatmentsResult -} - -// TreatmentsByFlagSetWithEvaluationOptions evaluate multiple feature flag names belonging to a flag set for a single user and a set of attributes at once -func (c *SplitClient) TreatmentsByFlagSetWithEvaluationOptions(key interface{}, flagSet string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { - treatmentsResult := map[string]string{} - sets := c.validateSets([]string{flagSet}) - if sets == nil { - return treatmentsResult - } - result := c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsByFlagSetWithEvaluationOptions, telemetry.TreatmentsByFlagSetWithEvaluationOptions, &evaluationOptions) - for feature, treatmentResult := range result { - treatmentsResult[feature] = treatmentResult.Treatment - } - return treatmentsResult -} - -// TreatmentsByFlagSetsWithEvaluationOptions evaluate multiple feature flag names belonging to flag sets for a single user and a set of attributes at once -func (c *SplitClient) TreatmentsByFlagSetsWithEvaluationOptions(key interface{}, flagSets []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]string { +func (c *SplitClient) TreatmentsByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}, optFns ...OptFn) map[string]string { + options := getOptions(optFns...) treatmentsResult := map[string]string{} flagSets = c.validateSets(flagSets) if flagSets == nil { return treatmentsResult } - result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSetsWithEvaluationOptions, telemetry.TreatmentsByFlagSetsWithEvaluationOptions, &evaluationOptions) + result := c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsByFlagSets, telemetry.TreatmentsByFlagSets, options.evaluationOptions) for feature, treatmentResult := range result { treatmentsResult[feature] = treatmentResult.Treatment } @@ -465,53 +436,31 @@ func (c *SplitClient) filterSetsAreInConfig(flagSets []string) []string { } // TreatmentsWithConfig evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfig(key interface{}, featureFlagNames []string, attributes map[string]interface{}) map[string]TreatmentResult { - return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfig, telemetry.TreatmentsWithConfig, nil) -} - -// TreatmentsWithConfigAndEvaluationOptions evaluates multiple feature flag names for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfigAndEvaluationOptions(key interface{}, featureFlagNames []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { - return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfigAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetAndEvaluationOptions, &evaluationOptions) +func (c *SplitClient) TreatmentsWithConfig(key interface{}, featureFlagNames []string, attributes map[string]interface{}, optFns ...OptFn) map[string]TreatmentResult { + options := getOptions(optFns...) + return c.doTreatmentsCall(key, featureFlagNames, attributes, treatmentsWithConfig, telemetry.TreatmentsWithConfig, options.evaluationOptions) } // TreatmentsWithConfigByFlagSet evaluates multiple feature flag names belonging to a flag set for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfigByFlagSet(key interface{}, flagSet string, attributes map[string]interface{}) map[string]TreatmentResult { - treatmentsResult := make(map[string]TreatmentResult) - sets := c.validateSets([]string{flagSet}) - if sets == nil { - return treatmentsResult - } - return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSet, telemetry.TreatmentsWithConfigByFlagSet, nil) -} - -// TreatmentsWithConfigByFlagSetAndEvaluationOptions evaluates multiple feature flag names belonging to a flag set for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfigByFlagSetAndEvaluationOptions(key interface{}, flagSet string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { +func (c *SplitClient) TreatmentsWithConfigByFlagSet(key interface{}, flagSet string, attributes map[string]interface{}, optFns ...OptFn) map[string]TreatmentResult { + options := getOptions(optFns...) treatmentsResult := make(map[string]TreatmentResult) sets := c.validateSets([]string{flagSet}) if sets == nil { return treatmentsResult } - return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSetAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetAndEvaluationOptions, &evaluationOptions) + return c.doTreatmentsCallByFlagSets(key, sets, attributes, treatmentsWithConfigByFlagSet, telemetry.TreatmentsWithConfigByFlagSet, options.evaluationOptions) } // TreatmentsWithConfigByFlagSet evaluates multiple feature flag names belonging to a flag sets for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfigByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}) map[string]TreatmentResult { - treatmentsResult := make(map[string]TreatmentResult) - flagSets = c.validateSets(flagSets) - if flagSets == nil { - return treatmentsResult - } - return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSets, telemetry.TreatmentsWithConfigByFlagSets, nil) -} - -// TreatmentsWithConfigByFlagSetsAndEvaluationOptions evaluates multiple feature flag names belonging to a flag sets for a single user and set of attributes at once and returns configurations -func (c *SplitClient) TreatmentsWithConfigByFlagSetsAndEvaluationOptions(key interface{}, flagSets []string, attributes map[string]interface{}, evaluationOptions dtos.EvaluationOptions) map[string]TreatmentResult { +func (c *SplitClient) TreatmentsWithConfigByFlagSets(key interface{}, flagSets []string, attributes map[string]interface{}, optFns ...OptFn) map[string]TreatmentResult { + options := getOptions(optFns...) treatmentsResult := make(map[string]TreatmentResult) flagSets = c.validateSets(flagSets) if flagSets == nil { return treatmentsResult } - return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSetsAndEvaluationOptions, telemetry.TreatmentsWithConfigByFlagSetsAndEvaluationOptions, &evaluationOptions) + return c.doTreatmentsCallByFlagSets(key, flagSets, attributes, treatmentsWithConfigByFlagSets, telemetry.TreatmentsWithConfigByFlagSets, options.evaluationOptions) } // isDestroyed returns true if the client has been destroyed diff --git a/splitio/client/client_test.go b/splitio/client/client_test.go index adfe919..13c6eb0 100644 --- a/splitio/client/client_test.go +++ b/splitio/client/client_test.go @@ -243,7 +243,7 @@ func TestClientGetTreatmentWithEvaluationProperties(t *testing.T) { "balance": 99.5, }, } - expectedTreatment(client.TreatmentWithEvaluationOptions("key", "feature", nil, opts), "TreatmentA", t) + expectedTreatment(client.Treatment("key", "feature", nil, client.WithEvaluationOptions(&opts)), "TreatmentA", t) impressionsQueue := client.impressions.(storage.ImpressionStorage) impressions, _ := impressionsQueue.PopN(5000) impression := impressions[0] @@ -311,7 +311,7 @@ func TestClientGetTreatmentByFlagSetWithEvaluationProperties(t *testing.T) { }, } - res := client.TreatmentsByFlagSetWithEvaluationOptions("user1", "set1", nil, opts) + res := client.TreatmentsByFlagSet("user1", "set1", nil, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"], "TreatmentA", t) impressionsQueue := client.impressions.(storage.ImpressionStorage) @@ -387,7 +387,7 @@ func TestClientGetTreatmentByFlagSetsWithEvaluationProperties(t *testing.T) { }, } - res := client.TreatmentsByFlagSetsWithEvaluationOptions("user1", []string{"set1", "set2"}, nil, opts) + res := client.TreatmentsByFlagSets("user1", []string{"set1", "set2"}, nil, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"], "TreatmentA", t) expectedTreatment(res["feature2"], "TreatmentB", t) @@ -451,7 +451,7 @@ func TestClientGetTreatmentWithConfigByFlagSetAndEvaluationProperties(t *testing }, } - res := client.TreatmentsWithConfigByFlagSetAndEvaluationOptions("user1", "set1", nil, opts) + res := client.TreatmentsWithConfigByFlagSet("user1", "set1", nil, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"].Treatment, "TreatmentA", t) impressionsQueue := client.impressions.(storage.ImpressionStorage) @@ -526,7 +526,7 @@ func TestClientGetTreatmentWithConfigByFlagSetsAndEvaluationOptions(t *testing.T }, } - res := client.TreatmentsWithConfigByFlagSetsAndEvaluationOptions("user1", []string{"set1", "set2"}, nil, opts) + res := client.TreatmentsWithConfigByFlagSets("user1", []string{"set1", "set2"}, nil, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"].Treatment, "TreatmentA", t) expectedTreatment(res["feature2"].Treatment, "TreatmentB", t) @@ -567,7 +567,7 @@ func TestTreatmentsWithEvaluationOptions(t *testing.T) { }, } - res := client.TreatmentsWithEvaluationOptions("user1", []string{"feature", "notFeature"}, nil, opts) + res := client.Treatments("user1", []string{"feature", "notFeature"}, nil, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"], "TreatmentA", t) expectedTreatment(res["notFeature"], evaluator.Control, t) @@ -941,7 +941,7 @@ func TestImpressionListenerForTreatmentsWithEvaluationOptions(t *testing.T) { }, } - res := client.TreatmentsWithEvaluationOptions("user1", []string{"feature", "feature2"}, attributes, opts) + res := client.Treatments("user1", []string{"feature", "feature2"}, attributes, client.WithEvaluationOptions(&opts)) expectedTreatment(res["feature"], "TreatmentA", t) expectedTreatment(res["feature2"], "TreatmentB", t) From 8e08b04782cbe409544dddc74ae58149eaa4ca5a Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 5 Dec 2025 16:22:36 -0300 Subject: [PATCH 3/7] Updated commons --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 27e26fa..fb3cbff 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/splitio/go-client/v6 go 1.18 require ( - github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150 + github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b github.com/splitio/go-toolkit/v5 v5.4.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index c04a131..62be8aa 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150 h1:rfNMXpXAKXzqM76WNuh+IKNGZ1LBwlyYXAx84tZMw80= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251202184315-69a1a4a8c150/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b h1:D07WBjcOVJxJc+LrALQ2lCJE2FqLNYXLSyV4FgevA2U= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= github.com/splitio/go-toolkit/v5 v5.4.1 h1:srTyvDBJZMUcJ/KiiQDMyjCuELVgTBh2TGRVn0sOXEE= github.com/splitio/go-toolkit/v5 v5.4.1/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= From 67d19e4b0318d95cd278ca4ff31e09c73b938454 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 5 Dec 2025 16:25:31 -0300 Subject: [PATCH 4/7] Updated version --- splitio/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/splitio/version.go b/splitio/version.go index cc3782f..f7c018e 100644 --- a/splitio/version.go +++ b/splitio/version.go @@ -1,4 +1,4 @@ package splitio // Version contains a string with the split sdk version -const Version = "6.9.0" +const Version = "6.10.0-rc" From 014676b41802982c6892d87fad29faa7ac1df482 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 11 Dec 2025 10:57:36 -0300 Subject: [PATCH 5/7] Updated commons --- go.mod | 2 +- go.sum | 4 ++-- splitio/version.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index fb3cbff..c870eb8 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/splitio/go-client/v6 go 1.18 require ( - github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b + github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df github.com/splitio/go-toolkit/v5 v5.4.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 62be8aa..4af83b5 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b h1:D07WBjcOVJxJc+LrALQ2lCJE2FqLNYXLSyV4FgevA2U= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251205143533-558205cace3b/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df h1:bu4aUJI8E8pfXy72aPakbbI1zYx168n8wHoJm4eWQdk= +github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= github.com/splitio/go-toolkit/v5 v5.4.1 h1:srTyvDBJZMUcJ/KiiQDMyjCuELVgTBh2TGRVn0sOXEE= github.com/splitio/go-toolkit/v5 v5.4.1/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/splitio/version.go b/splitio/version.go index f7c018e..df1d2c6 100644 --- a/splitio/version.go +++ b/splitio/version.go @@ -1,4 +1,4 @@ package splitio // Version contains a string with the split sdk version -const Version = "6.10.0-rc" +const Version = "6.10.0-rc1" From b2b7c55c3569657eec74902ffd6e2759b2e2fd5e Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 17 Dec 2025 12:06:50 -0300 Subject: [PATCH 6/7] Updated commons to v9.1.0 --- go.mod | 2 +- go.sum | 4 ++-- splitio/client/client.go | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index c870eb8..d04fdf6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/splitio/go-client/v6 go 1.18 require ( - github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df + github.com/splitio/go-split-commons/v9 v9.1.0 github.com/splitio/go-toolkit/v5 v5.4.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 4af83b5..ef7242b 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df h1:bu4aUJI8E8pfXy72aPakbbI1zYx168n8wHoJm4eWQdk= -github.com/splitio/go-split-commons/v9 v9.0.1-0.20251211135450-36cc589587df/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= +github.com/splitio/go-split-commons/v9 v9.1.0 h1:sfmPMuEDTtbIOJ+MeWNbfYl2/xKB/25d4/J95OUD+X0= +github.com/splitio/go-split-commons/v9 v9.1.0/go.mod h1:gJuaKo04Swlh4w9C1b2jBAqAdFxEd/Vpd8jnFINOeDY= github.com/splitio/go-toolkit/v5 v5.4.1 h1:srTyvDBJZMUcJ/KiiQDMyjCuELVgTBh2TGRVn0sOXEE= github.com/splitio/go-toolkit/v5 v5.4.1/go.mod h1:SifzysrOVDbzMcOE8zjX02+FG5az4FrR3Us/i5SeStw= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= diff --git a/splitio/client/client.go b/splitio/client/client.go index 880d160..84bf4c7 100644 --- a/splitio/client/client.go +++ b/splitio/client/client.go @@ -279,8 +279,6 @@ func (c *SplitClient) processResult(result evaluator.Results, operation string, } } else { bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled, serializeProperties(evaluationOptions))) - //bulkImpressions = append(bulkImpressions, c.createImpression(feature, bucketingKey, evaluation.Label, matchingKey, evaluation.Treatment, evaluation.SplitChangeNumber, evaluation.ImpressionsDisabled, "")) - treatments[feature] = TreatmentResult{ Treatment: evaluation.Treatment, Config: evaluation.Config, From f224c9258beb16bc26911390ce95ced7efa573db Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 17 Dec 2025 12:17:24 -0300 Subject: [PATCH 7/7] Updated changelogs and version --- CHANGES.txt | 3 +++ splitio/version.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index c2e18cf..84ab00e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +6.10.0 (Nov 26, 2025) +- Added a new optional argument to the client `getTreatment` methods to allow passing additional evaluation options, such as a map of properties to append to the generated impressions sent to Split backend. Read more in our docs. + 6.9.0 (Nov 26, 2025) - Added new configuration for Fallback Treatments, which allows setting a treatment value and optional config to be returned in place of "control", either globally or by flag. Read more in our docs. diff --git a/splitio/version.go b/splitio/version.go index df1d2c6..5527fcc 100644 --- a/splitio/version.go +++ b/splitio/version.go @@ -1,4 +1,4 @@ package splitio // Version contains a string with the split sdk version -const Version = "6.10.0-rc1" +const Version = "6.10.0"