From d41fa88996d4f541282ccd984ecbdc8c8f46d6c7 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 22 Jan 2026 15:48:37 -0300 Subject: [PATCH 1/6] [FME-12564] Added impression properties in link package --- splitio/link/client/types/interfaces.go | 14 +++++--- splitio/link/client/v1/impl.go | 44 +++++++++++++++++++------ splitio/link/client/v1/impl_test.go | 9 ++++- splitio/sdk/sdk.go | 10 +++--- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/splitio/link/client/types/interfaces.go b/splitio/link/client/types/interfaces.go index 4e11855..a3da0bc 100644 --- a/splitio/link/client/types/interfaces.go +++ b/splitio/link/client/types/interfaces.go @@ -6,10 +6,10 @@ import ( ) type ClientInterface interface { - Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*Result, error) - Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}) (Results, error) - TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*Result, error) - TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}) (Results, error) + Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...OptFn) (*Result, error) + Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...OptFn) (Results, error) + TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...OptFn) (*Result, error) + TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...OptFn) (Results, error) Track(key string, trafficType string, eventType string, value *float64, properties map[string]interface{}) error SplitNames() ([]string, error) Split(name string) (*sdk.SplitView, error) @@ -24,3 +24,9 @@ type Result struct { } type Results = map[string]Result + +type Options struct { + EvaluationOptions *dtos.EvaluationOptions +} + +type OptFn = func(o *Options) diff --git a/splitio/link/client/v1/impl.go b/splitio/link/client/v1/impl.go index fba91ce..e33d070 100644 --- a/splitio/link/client/v1/impl.go +++ b/splitio/link/client/v1/impl.go @@ -26,6 +26,16 @@ type Impl struct { listenerFeedback bool } +func (c *Impl) WithEvaluationOptions(e *dtos.EvaluationOptions) types.OptFn { + return func(o *types.Options) { o.EvaluationOptions = e } +} + +func defaultOpts() types.Options { + return types.Options{ + EvaluationOptions: nil, + } +} + func New(id string, logger logging.LoggerInterface, conn transfer.RawConn, serializer serializer.Interface, listenerFeedback bool) (*Impl, error) { i := &Impl{ logger: logger, @@ -43,23 +53,27 @@ func New(id string, logger logging.LoggerInterface, conn transfer.RawConn, seria } // Treatment implements Interface -func (c *Impl) Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*types.Result, error) { - return c.treatment(key, bucketingKey, feature, attrs, false) +func (c *Impl) Treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...types.OptFn) (*types.Result, error) { + options := getOptions(optFns...) + return c.treatment(key, bucketingKey, feature, attrs, false, options.EvaluationOptions) } // TreatmentWithConfig implements types.ClientInterface -func (c *Impl) TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}) (*types.Result, error) { - return c.treatment(key, bucketingKey, feature, attrs, true) +func (c *Impl) TreatmentWithConfig(key string, bucketingKey string, feature string, attrs map[string]interface{}, optFns ...types.OptFn) (*types.Result, error) { + options := getOptions(optFns...) + return c.treatment(key, bucketingKey, feature, attrs, true, options.EvaluationOptions) } // Treatment implements Interface -func (c *Impl) Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}) (types.Results, error) { - return c.treatments(key, bucketingKey, features, attrs, false) +func (c *Impl) Treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...types.OptFn) (types.Results, error) { + options := getOptions(optFns...) + return c.treatments(key, bucketingKey, features, attrs, false, options.EvaluationOptions) } // TreatmentsWithConfig implements types.ClientInterface -func (c *Impl) TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}) (types.Results, error) { - return c.treatments(key, bucketingKey, features, attrs, true) +func (c *Impl) TreatmentsWithConfig(key string, bucketingKey string, features []string, attrs map[string]interface{}, optFns ...types.OptFn) (types.Results, error) { + options := getOptions(optFns...) + return c.treatments(key, bucketingKey, features, attrs, true, options.EvaluationOptions) } // Track implements types.ClientInterface @@ -139,7 +153,7 @@ func (c *Impl) Splits() ([]sdk.SplitView, error) { return views, nil } -func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, withConfig bool) (*types.Result, error) { +func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs map[string]interface{}, withConfig bool, evaluationOptions *dtos.EvaluationOptions) (*types.Result, error) { var bkp *string if bucketingKey != "" { bkp = &bucketingKey @@ -174,6 +188,7 @@ func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs ChangeNumber: resp.Payload.ListenerData.ChangeNumber, Label: resp.Payload.ListenerData.Label, BucketingKey: bucketingKey, + Properties: sdk.SerializeProperties(evaluationOptions), } } @@ -185,7 +200,7 @@ func (c *Impl) treatment(key string, bucketingKey string, feature string, attrs return toRet, nil } -func (c *Impl) treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, withConfig bool) (types.Results, error) { +func (c *Impl) treatments(key string, bucketingKey string, features []string, attrs map[string]interface{}, withConfig bool, evaluationOptions *dtos.EvaluationOptions) (types.Results, error) { var bkp *string if bucketingKey != "" { bkp = &bucketingKey @@ -221,6 +236,7 @@ func (c *Impl) treatments(key string, bucketingKey string, features []string, at ChangeNumber: resp.Payload.Results[idx].ListenerData.ChangeNumber, Label: resp.Payload.Results[idx].ListenerData.Label, BucketingKey: bucketingKey, + Properties: sdk.SerializeProperties(evaluationOptions), } } @@ -286,4 +302,12 @@ func (c *Impl) Shutdown() error { return c.conn.Shutdown() } +func getOptions(optFns ...types.OptFn) types.Options { + options := defaultOpts() + for _, optFn := range optFns { + optFn(&options) + } + return options +} + var _ types.ClientInterface = (*Impl)(nil) diff --git a/splitio/link/client/v1/impl_test.go b/splitio/link/client/v1/impl_test.go index 2bdbee6..d9460af 100644 --- a/splitio/link/client/v1/impl_test.go +++ b/splitio/link/client/v1/impl_test.go @@ -144,7 +144,12 @@ func TestClientGetTreatmentWithImpression(t *testing.T) { assert.NotNil(t, client) assert.Nil(t, err) - res, err := client.Treatment("key1", "buck1", "feat1", map[string]interface{}{"a": 1}) + opts := dtos.EvaluationOptions{ + Properties: map[string]interface{}{ + "pleassssse": "holaaaaa", + }, + } + res, err := client.Treatment("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, client.WithEvaluationOptions(&opts)) assert.Nil(t, err) assert.Equal(t, "on", res.Treatment) validateImpression(t, &dtos.Impression{ @@ -155,6 +160,7 @@ func TestClientGetTreatmentWithImpression(t *testing.T) { Label: "l1", ChangeNumber: 1234, Time: 123, + Properties: "{\"pleassssse\":\"holaaaaa\"}", }, res.Impression) } @@ -435,5 +441,6 @@ func validateImpression(t *testing.T, expected *dtos.Impression, actual *dtos.Im assert.Equal(t, expected.Time, actual.Time) assert.Equal(t, expected.Treatment, actual.Treatment) assert.Equal(t, expected.Label, actual.Label) + assert.Equal(t, expected.Properties, actual.Properties) } diff --git a/splitio/sdk/sdk.go b/splitio/sdk/sdk.go index 64febce..af8e6bb 100644 --- a/splitio/sdk/sdk.go +++ b/splitio/sdk/sdk.go @@ -156,7 +156,7 @@ func (i *Impl) Treatment(cfg *types.ClientConfig, key string, bk *string, featur return nil, fmt.Errorf("nil result") } - imp := i.handleImpression(key, bk, feature, res, cfg.Metadata, serializeProperties(options.evaluationOptions)) + imp := i.handleImpression(key, bk, feature, res, cfg.Metadata, SerializeProperties(options.evaluationOptions)) return &EvaluationResult{ Treatment: res.Treatment, Impression: imp, @@ -188,7 +188,7 @@ func (i *Impl) Treatments(cfg *types.ClientConfig, key string, bk *string, featu var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, serializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } @@ -205,7 +205,7 @@ func (i *Impl) TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bk *stri for feature, curr := range res.Evaluations { var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, serializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } @@ -222,7 +222,7 @@ func (i *Impl) TreatmentsByFlagSets(cfg *types.ClientConfig, key string, bk *str for feature, curr := range res.Evaluations { var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, serializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } @@ -367,7 +367,7 @@ func createFallbackTreatmentCalculator(fallbackTreatmentConfig *dtos.FallbackTre return dtos.NewFallbackTreatmentCalculatorImp(&fallbackTreatmentConf) } -func serializeProperties(opts *dtos.EvaluationOptions) string { +func SerializeProperties(opts *dtos.EvaluationOptions) string { if opts == nil { return "" } From 0050c336f68e71abe3c6c3785c39fed772d85b3b Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 26 Jan 2026 10:51:42 -0300 Subject: [PATCH 2/6] Updated sdk and link --- splitio/link/client/v1/impl_test.go | 6 +- splitio/link/protocol/v1/mocks/mocks.go | 4 +- splitio/link/protocol/v1/rpcs.go | 106 ++++++++++++++++-------- splitio/link/service/v1/clientmgr.go | 9 +- splitio/sdk/integration_test.go | 10 +-- splitio/sdk/mocks/sdk.go | 9 +- splitio/sdk/sdk.go | 52 +++--------- splitio/sdk/sdk_test.go | 20 ++--- 8 files changed, 115 insertions(+), 101 deletions(-) diff --git a/splitio/link/client/v1/impl_test.go b/splitio/link/client/v1/impl_test.go index d9460af..8801c14 100644 --- a/splitio/link/client/v1/impl_test.go +++ b/splitio/link/client/v1/impl_test.go @@ -31,7 +31,7 @@ func TestClientGetTreatmentNoImpression(t *testing.T) { *args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk} }).Once() - serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, false)). + serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, false)). Return([]byte("treatmentMessage"), nil).Once() serializerMock.On("Parse", []byte("treatmentResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) { *args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{ @@ -65,7 +65,7 @@ func TestClientGetTreatmentWithConfig(t *testing.T) { *args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk} }).Once() - serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, true)). + serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, true)). Return([]byte("treatmentWithConfigMessage"), nil).Once() serializerMock.On("Parse", []byte("treatmentWithConfigResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) { *args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{ @@ -129,7 +129,7 @@ func TestClientGetTreatmentWithImpression(t *testing.T) { *args.Get(1).(*v1.ResponseWrapper[v1.RegisterPayload]) = v1.ResponseWrapper[v1.RegisterPayload]{Status: v1.ResultOk} }).Once() - serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, false)). + serializerMock.On("Serialize", proto1Mocks.NewTreatmentRPC("key1", "buck1", "feat1", map[string]interface{}{"a": 1}, nil, false)). Return([]byte("treatmentMessage"), nil).Once() serializerMock.On("Parse", []byte("treatmentResult"), mock.Anything).Return(nil).Run(func(args mock.Arguments) { *args.Get(1).(*v1.ResponseWrapper[v1.TreatmentPayload]) = v1.ResponseWrapper[v1.TreatmentPayload]{ diff --git a/splitio/link/protocol/v1/mocks/mocks.go b/splitio/link/protocol/v1/mocks/mocks.go index cf56663..1473e99 100644 --- a/splitio/link/protocol/v1/mocks/mocks.go +++ b/splitio/link/protocol/v1/mocks/mocks.go @@ -22,11 +22,11 @@ func NewRegisterRPC(id string, listener bool) *v1.RPC { } } -func NewTreatmentRPC(key string, bucketing string, feature string, attrs map[string]interface{}, withConfig bool) *v1.RPC { +func NewTreatmentRPC(key string, bucketing string, feature string, attrs map[string]interface{}, impressionProperties map[string]interface{}, withConfig bool) *v1.RPC { rpc := &v1.RPC{ RPCBase: protocol.RPCBase{Version: protocol.V1}, OpCode: v1.OCTreatment, - Args: []interface{}{key, bucketing, feature, attrs}, + Args: []interface{}{key, bucketing, feature, attrs, impressionProperties}, } if withConfig { rpc.OpCode = v1.OCTreatmentWithConfig diff --git a/splitio/link/protocol/v1/rpcs.go b/splitio/link/protocol/v1/rpcs.go index 2a8a741..1c2ab23 100644 --- a/splitio/link/protocol/v1/rpcs.go +++ b/splitio/link/protocol/v1/rpcs.go @@ -123,17 +123,19 @@ func (r *RegisterArgs) PopulateFromRPC(rpc *RPC) error { } const ( - TreatmentArgKeyIdx int = 0 - TreatmentArgBucketingKeyIdx int = 1 - TreatmentArgFeatureIdx int = 2 - TreatmentArgAttributesIdx int = 3 + TreatmentArgKeyIdx int = 0 + TreatmentArgBucketingKeyIdx int = 1 + TreatmentArgFeatureIdx int = 2 + TreatmentArgAttributesIdx int = 3 + TreatmentArgImpressionPropertiesIdx int = 4 ) type TreatmentArgs struct { - Key string `msgpack:"k"` - BucketingKey *string `msgpack:"b"` - Feature string `msgpack:"f"` - Attributes map[string]interface{} `msgpack:"a"` + Key string `msgpack:"k"` + BucketingKey *string `msgpack:"b"` + Feature string `msgpack:"f"` + Attributes map[string]interface{} `msgpack:"a"` + ImpressionProperties map[string]interface{} `msgpack:"i"` } func (r TreatmentArgs) Encode() []interface{} { @@ -141,7 +143,7 @@ func (r TreatmentArgs) Encode() []interface{} { if r.BucketingKey != nil { bk = *r.BucketingKey } - return []interface{}{r.Key, bk, r.Feature, r.Attributes} + return []interface{}{r.Key, bk, r.Feature, r.Attributes, r.ImpressionProperties} } func (t *TreatmentArgs) PopulateFromRPC(rpc *RPC) error { @@ -177,21 +179,31 @@ func (t *TreatmentArgs) PopulateFromRPC(rpc *RPC) error { t.Attributes = sanitizeAttributes(rawAttrs) } + if len(rpc.Args) == 5 && rpc.Args[TreatmentArgImpressionPropertiesIdx] != nil { + rawAttrs, err := getOptional[map[string]interface{}](rpc.Args[TreatmentArgImpressionPropertiesIdx]) + if err != nil { + return RPCParseError{Code: PECInvalidArgType, Data: int64(TreatmentArgImpressionPropertiesIdx)} + } + t.ImpressionProperties = rawAttrs + } + return nil } const ( - TreatmentsArgKeyIdx int = 0 - TreatmentsArgBucketingKeyIdx int = 1 - TreatmentsArgFeaturesIdx int = 2 - TreatmentsArgAttributesIdx int = 3 + TreatmentsArgKeyIdx int = 0 + TreatmentsArgBucketingKeyIdx int = 1 + TreatmentsArgFeaturesIdx int = 2 + TreatmentsArgAttributesIdx int = 3 + TreatmentsArgImpressionPropertiesIdx int = 4 ) type TreatmentsArgs struct { - Key string `msgpack:"k"` - BucketingKey *string `msgpack:"b"` - Features []string `msgpack:"f"` - Attributes map[string]interface{} `msgpack:"a"` + Key string `msgpack:"k"` + BucketingKey *string `msgpack:"b"` + Features []string `msgpack:"f"` + Attributes map[string]interface{} `msgpack:"a"` + ImpressionProperties map[string]interface{} `msgpack:"i"` } func (r TreatmentsArgs) Encode() []interface{} { @@ -238,21 +250,31 @@ func (t *TreatmentsArgs) PopulateFromRPC(rpc *RPC) error { } t.Attributes = sanitizeAttributes(rawAttrs) + if len(rpc.Args) == 5 && rpc.Args[TreatmentsArgImpressionPropertiesIdx] != nil { + rawAttrs, err := getOptional[map[string]interface{}](rpc.Args[TreatmentsArgImpressionPropertiesIdx]) + if err != nil { + return RPCParseError{Code: PECInvalidArgType, Data: int64(TreatmentsArgImpressionPropertiesIdx)} + } + t.ImpressionProperties = rawAttrs + } + return nil } const ( - TreatmentsByFlagSetArgKeyIdx int = 0 - TreatmentsByFlagSetArgBucketingKeyIdx int = 1 - TreatmentsByFlagSetArgFlagSetIdx int = 2 - TreatmentsByFlagSetArgAttributesIdx int = 3 + TreatmentsByFlagSetArgKeyIdx int = 0 + TreatmentsByFlagSetArgBucketingKeyIdx int = 1 + TreatmentsByFlagSetArgFlagSetIdx int = 2 + TreatmentsByFlagSetArgAttributesIdx int = 3 + TreatmentsByFlagSetArgImpressionPropertiesIdx int = 4 ) type TreatmentsByFlagSetArgs struct { - Key string `msgpack:"k"` - BucketingKey *string `msgpack:"b"` - FlagSet string `msgpack:"f"` - Attributes map[string]interface{} `msgpack:"a"` + Key string `msgpack:"k"` + BucketingKey *string `msgpack:"b"` + FlagSet string `msgpack:"f"` + Attributes map[string]interface{} `msgpack:"a"` + ImpressionProperties map[string]interface{} `msgpack:"i"` } func (r TreatmentsByFlagSetArgs) Encode() []interface{} { @@ -292,21 +314,31 @@ func (t *TreatmentsByFlagSetArgs) PopulateFromRPC(rpc *RPC) error { } t.Attributes = sanitizeAttributes(rawAttrs) + if len(rpc.Args) == 5 && rpc.Args[TreatmentsByFlagSetArgImpressionPropertiesIdx] != nil { + rawAttrs, err := getOptional[map[string]interface{}](rpc.Args[TreatmentsByFlagSetArgImpressionPropertiesIdx]) + if err != nil { + return RPCParseError{Code: PECInvalidArgType, Data: int64(TreatmentsByFlagSetArgImpressionPropertiesIdx)} + } + t.ImpressionProperties = rawAttrs + } + return nil } const ( - TreatmentsByFlagSetsArgKeyIdx int = 0 - TreatmentsByFlagSetsArgBucketingKeyIdx int = 1 - TreatmentsByFlagSetsArgFlagSetsIdx int = 2 - TreatmentsByFlagSetsArgAttributesIdx int = 3 + TreatmentsByFlagSetsArgKeyIdx int = 0 + TreatmentsByFlagSetsArgBucketingKeyIdx int = 1 + TreatmentsByFlagSetsArgFlagSetsIdx int = 2 + TreatmentsByFlagSetsArgAttributesIdx int = 3 + TreatmentsByFlagSetsArgImpressionPropertiesIdx int = 4 ) type TreatmentsByFlagSetsArgs struct { - Key string `msgpack:"k"` - BucketingKey *string `msgpack:"b"` - FlagSets []string `msgpack:"f"` - Attributes map[string]interface{} `msgpack:"a"` + Key string `msgpack:"k"` + BucketingKey *string `msgpack:"b"` + FlagSets []string `msgpack:"f"` + Attributes map[string]interface{} `msgpack:"a"` + ImpressionProperties map[string]interface{} `msgpack:"i"` } func (r TreatmentsByFlagSetsArgs) Encode() []interface{} { @@ -352,6 +384,14 @@ func (t *TreatmentsByFlagSetsArgs) PopulateFromRPC(rpc *RPC) error { } t.Attributes = sanitizeAttributes(rawAttrs) + if len(rpc.Args) == 5 && rpc.Args[TreatmentsByFlagSetsArgImpressionPropertiesIdx] != nil { + rawAttrs, err := getOptional[map[string]interface{}](rpc.Args[TreatmentsByFlagSetsArgImpressionPropertiesIdx]) + if err != nil { + return RPCParseError{Code: PECInvalidArgType, Data: int64(TreatmentsByFlagSetsArgImpressionPropertiesIdx)} + } + t.ImpressionProperties = rawAttrs + } + return nil } diff --git a/splitio/link/service/v1/clientmgr.go b/splitio/link/service/v1/clientmgr.go index 6c74f4f..eb2388b 100644 --- a/splitio/link/service/v1/clientmgr.go +++ b/splitio/link/service/v1/clientmgr.go @@ -7,6 +7,7 @@ import ( "os" "runtime/debug" + "github.com/splitio/go-split-commons/v9/dtos" "github.com/splitio/go-toolkit/v5/logging" protov1 "github.com/splitio/splitd/splitio/link/protocol/v1" @@ -169,7 +170,7 @@ func (m *ClientManager) handleGetTreatment(rpc *protov1.RPC, withConfig bool) (i return nil, fmt.Errorf("error parsing treatment arguments: %w", err) } - res, err := m.splitSDK.Treatment(m.clientConfig, args.Key, args.BucketingKey, args.Feature, args.Attributes) + res, err := m.splitSDK.Treatment(m.clientConfig, args.Key, args.BucketingKey, args.Feature, args.Attributes, &dtos.EvaluationOptions{Properties: args.ImpressionProperties}) if err != nil { return &protov1.ResponseWrapper[protov1.TreatmentPayload]{Status: protov1.ResultInternalError}, err } @@ -201,7 +202,7 @@ func (m *ClientManager) handleGetTreatments(rpc *protov1.RPC, withConfig bool) ( return nil, fmt.Errorf("error parsing treatments arguments: %w", err) } - res, err := m.splitSDK.Treatments(m.clientConfig, args.Key, args.BucketingKey, args.Features, args.Attributes) + res, err := m.splitSDK.Treatments(m.clientConfig, args.Key, args.BucketingKey, args.Features, args.Attributes, &dtos.EvaluationOptions{Properties: args.ImpressionProperties}) if err != nil { return &protov1.ResponseWrapper[protov1.TreatmentsPayload]{Status: protov1.ResultInternalError}, err } @@ -243,7 +244,7 @@ func (m *ClientManager) handleGetTreatmentsByFlagSet(rpc *protov1.RPC, withConfi return nil, fmt.Errorf("error parsing treatmentsByFlagSet arguments: %w", err) } - res, err := m.splitSDK.TreatmentsByFlagSet(m.clientConfig, args.Key, args.BucketingKey, args.FlagSet, args.Attributes) + res, err := m.splitSDK.TreatmentsByFlagSet(m.clientConfig, args.Key, args.BucketingKey, args.FlagSet, args.Attributes, &dtos.EvaluationOptions{Properties: args.ImpressionProperties}) if err != nil { return &protov1.ResponseWrapper[protov1.TreatmentsWithFeaturePayload]{Status: protov1.ResultInternalError}, err } @@ -284,7 +285,7 @@ func (m *ClientManager) handleGetTreatmentsByFlagSets(rpc *protov1.RPC, withConf return nil, fmt.Errorf("error parsing treatmentsByFlagSets arguments: %w", err) } - res, err := m.splitSDK.TreatmentsByFlagSets(m.clientConfig, args.Key, args.BucketingKey, args.FlagSets, args.Attributes) + res, err := m.splitSDK.TreatmentsByFlagSets(m.clientConfig, args.Key, args.BucketingKey, args.FlagSets, args.Attributes, &dtos.EvaluationOptions{Properties: args.ImpressionProperties}) if err != nil { return &protov1.ResponseWrapper[protov1.TreatmentsWithFeaturePayload]{Status: protov1.ResultInternalError}, err } diff --git a/splitio/sdk/integration_test.go b/splitio/sdk/integration_test.go index 97ccdaf..7a39227 100644 --- a/splitio/sdk/integration_test.go +++ b/splitio/sdk/integration_test.go @@ -123,7 +123,7 @@ func TestInstantiationAndGetTreatmentE2E(t *testing.T) { client, err := New(logger, "someApikey", sdkConf) assert.Nil(t, err) - res, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil) + res, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil, nil) assert.Equal(t, "on", res.Treatment) assert.Nil(t, client.Shutdown()) @@ -241,7 +241,7 @@ func TestInstantiationAndGetTreatmentE2EWithFallbackTreatment(t *testing.T) { }, } - res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "not_exist", nil, client.WithEvaluationOptions(&opts)) + res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "not_exist", nil, &opts) assert.Equal(t, "global_treatment", res1.Treatment) assert.Equal(t, "{\"pleassssse\":\"holaaaaa\"}", res1.Impression.Properties) @@ -370,7 +370,7 @@ func TestInstantiationAndGetTreatmentE2EWithPrerequistesNotAchive(t *testing.T) client, err := New(logger, "someApikey", sdkConf) assert.Nil(t, err) - res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil) + res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil, nil) assert.Equal(t, "default", res1.Treatment) assert.Nil(t, client.Shutdown()) @@ -498,7 +498,7 @@ func TestInstantiationAndGetTreatmentE2EWithPrerequistesAchive(t *testing.T) { client, err := New(logger, "someApikey", sdkConf) assert.Nil(t, err) - res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil) + res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", nil, nil) assert.Equal(t, "on", res1.Treatment) assert.Nil(t, client.Shutdown()) @@ -649,7 +649,7 @@ func TestInstantiationAndGetTreatmentE2EWithRBS(t *testing.T) { attributes := make(map[string]interface{}) attributes["version"] = "3.4.5" - res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", attributes) + res1, _ := client.Treatment(&types.ClientConfig{}, "aaaaaaklmnbv", nil, "split", attributes, nil) assert.Equal(t, "on", res1.Treatment) assert.Nil(t, client.Shutdown()) diff --git a/splitio/sdk/mocks/sdk.go b/splitio/sdk/mocks/sdk.go index dd6abb6..1d349f4 100644 --- a/splitio/sdk/mocks/sdk.go +++ b/splitio/sdk/mocks/sdk.go @@ -1,6 +1,7 @@ package mocks import ( + "github.com/splitio/go-split-commons/v9/dtos" "github.com/splitio/splitd/splitio/sdk" "github.com/splitio/splitd/splitio/sdk/types" "github.com/stretchr/testify/mock" @@ -17,7 +18,7 @@ func (m *SDKMock) Treatment( bucketingKey *string, feature string, attributes map[string]interface{}, - optFns ...sdk.OptFn, + evaluationOptions *dtos.EvaluationOptions, ) (*sdk.EvaluationResult, error) { args := m.Called(md, key, bucketingKey, feature, attributes) return args.Get(0).(*sdk.EvaluationResult), args.Error(1) @@ -30,7 +31,7 @@ func (m *SDKMock) Treatments( bucketingKey *string, features []string, attributes map[string]interface{}, - optFns ...sdk.OptFn, + evaluationOptions *dtos.EvaluationOptions, ) (map[string]sdk.EvaluationResult, error) { args := m.Called(md, key, bucketingKey, features, attributes) return args.Get(0).(map[string]sdk.EvaluationResult), args.Error(1) @@ -43,7 +44,7 @@ func (m *SDKMock) TreatmentsByFlagSet( bucketingKey *string, flagSet string, attributes map[string]interface{}, - optFns ...sdk.OptFn, + evaluationOptions *dtos.EvaluationOptions, ) (map[string]sdk.EvaluationResult, error) { args := m.Called(md, key, bucketingKey, flagSet, attributes) return args.Get(0).(map[string]sdk.EvaluationResult), args.Error(1) @@ -56,7 +57,7 @@ func (m *SDKMock) TreatmentsByFlagSets( bucketingKey *string, flagSets []string, attributes map[string]interface{}, - optFns ...sdk.OptFn, + evaluationOptions *dtos.EvaluationOptions, ) (map[string]sdk.EvaluationResult, error) { args := m.Called(md, key, bucketingKey, flagSets, attributes) return args.Get(0).(map[string]sdk.EvaluationResult), args.Error(1) diff --git a/splitio/sdk/sdk.go b/splitio/sdk/sdk.go index af8e6bb..7ec5b01 100644 --- a/splitio/sdk/sdk.go +++ b/splitio/sdk/sdk.go @@ -49,10 +49,10 @@ var ruleBasedSegmentRules = []string{constants.MatcherTypeAllKeys, constants.Mat type Attributes = map[string]interface{} type Interface interface { - Treatment(cfg *types.ClientConfig, key string, bucketingKey *string, feature string, attributes map[string]interface{}, optFns ...OptFn) (*EvaluationResult, error) - Treatments(cfg *types.ClientConfig, key string, bucketingKey *string, features []string, attributes map[string]interface{}, optFns ...OptFn) (map[string]EvaluationResult, error) - TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bucketingKey *string, flagSet string, attributes map[string]interface{}, optFns ...OptFn) (map[string]EvaluationResult, error) - TreatmentsByFlagSets(cfg *types.ClientConfig, key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}, optFns ...OptFn) (map[string]EvaluationResult, error) + Treatment(cfg *types.ClientConfig, key string, bucketingKey *string, feature string, attributes map[string]interface{}, evaluationOptions *dtos.EvaluationOptions) (*EvaluationResult, error) + Treatments(cfg *types.ClientConfig, key string, bucketingKey *string, features []string, attributes map[string]interface{}, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) + TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bucketingKey *string, flagSet string, attributes map[string]interface{}, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) + TreatmentsByFlagSets(cfg *types.ClientConfig, key string, bucketingKey *string, flagSets []string, attributes map[string]interface{}, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) Track(cfg *types.ClientConfig, key string, trafficType string, eventType string, value *float64, properties map[string]interface{}) error SplitNames() ([]string, error) Splits() ([]SplitView, error) @@ -74,22 +74,6 @@ type Impl struct { validator Validator } -type options struct { - evaluationOptions *dtos.EvaluationOptions -} - -type OptFn = func(o *options) - -func (c *Impl) WithEvaluationOptions(e *dtos.EvaluationOptions) OptFn { - return func(o *options) { o.evaluationOptions = e } -} - -func defaultOpts() options { - return options{ - evaluationOptions: nil, - } -} - func New(logger logging.LoggerInterface, apikey string, c *conf.Config) (*Impl, error) { if warnings := c.Normalize(); len(warnings) > 0 { @@ -149,14 +133,13 @@ func New(logger logging.LoggerInterface, apikey string, c *conf.Config) (*Impl, } // Treatment implements Interface -func (i *Impl) Treatment(cfg *types.ClientConfig, key string, bk *string, feature string, attributes Attributes, optFns ...OptFn) (*EvaluationResult, error) { - options := getOptions(optFns...) +func (i *Impl) Treatment(cfg *types.ClientConfig, key string, bk *string, feature string, attributes Attributes, evaluationOptions *dtos.EvaluationOptions) (*EvaluationResult, error) { res := i.ev.EvaluateFeature(key, bk, feature, attributes) if res == nil { return nil, fmt.Errorf("nil result") } - imp := i.handleImpression(key, bk, feature, res, cfg.Metadata, SerializeProperties(options.evaluationOptions)) + imp := i.handleImpression(key, bk, feature, res, cfg.Metadata, SerializeProperties(evaluationOptions)) return &EvaluationResult{ Treatment: res.Treatment, Impression: imp, @@ -164,18 +147,9 @@ func (i *Impl) Treatment(cfg *types.ClientConfig, key string, bk *string, featur }, nil } -func getOptions(optFns ...OptFn) options { - options := defaultOpts() - for _, optFn := range optFns { - optFn(&options) - } - return options -} - // Treatment implements Interface -func (i *Impl) Treatments(cfg *types.ClientConfig, key string, bk *string, features []string, attributes Attributes, optFns ...OptFn) (map[string]EvaluationResult, error) { +func (i *Impl) Treatments(cfg *types.ClientConfig, key string, bk *string, features []string, attributes Attributes, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) { - options := getOptions(optFns...) res := i.ev.EvaluateFeatures(key, bk, features, attributes) toRet := make(map[string]EvaluationResult, len(res.Evaluations)) for _, feature := range features { @@ -188,7 +162,7 @@ func (i *Impl) Treatments(cfg *types.ClientConfig, key string, bk *string, featu var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } @@ -197,15 +171,14 @@ func (i *Impl) Treatments(cfg *types.ClientConfig, key string, bk *string, featu } // TreatmentsByFlagSet implements Interface -func (i *Impl) TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bk *string, flagSet string, attributes Attributes, optFns ...OptFn) (map[string]EvaluationResult, error) { +func (i *Impl) TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bk *string, flagSet string, attributes Attributes, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) { - options := getOptions(optFns...) res := i.ev.EvaluateFeatureByFlagSets(key, bk, []string{flagSet}, attributes) toRet := make(map[string]EvaluationResult, len(res.Evaluations)) for feature, curr := range res.Evaluations { var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } @@ -214,15 +187,14 @@ func (i *Impl) TreatmentsByFlagSet(cfg *types.ClientConfig, key string, bk *stri } // TreatmentsByFlagSets implements Interface -func (i *Impl) TreatmentsByFlagSets(cfg *types.ClientConfig, key string, bk *string, flagSets []string, attributes Attributes, optFns ...OptFn) (map[string]EvaluationResult, error) { +func (i *Impl) TreatmentsByFlagSets(cfg *types.ClientConfig, key string, bk *string, flagSets []string, attributes Attributes, evaluationOptions *dtos.EvaluationOptions) (map[string]EvaluationResult, error) { - options := getOptions(optFns...) res := i.ev.EvaluateFeatureByFlagSets(key, bk, flagSets, attributes) toRet := make(map[string]EvaluationResult, len(res.Evaluations)) for feature, curr := range res.Evaluations { var eres EvaluationResult eres.Treatment = curr.Treatment - eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(options.evaluationOptions)) + eres.Impression = i.handleImpression(key, bk, feature, &curr, cfg.Metadata, SerializeProperties(evaluationOptions)) eres.Config = curr.Config toRet[feature] = eres } diff --git a/splitio/sdk/sdk_test.go b/splitio/sdk/sdk_test.go index 1202487..230534f 100644 --- a/splitio/sdk/sdk_test.go +++ b/splitio/sdk/sdk_test.go @@ -61,7 +61,7 @@ func TestTreatmentsWithImpressionsDisabled(t *testing.T) { res, err := client.Treatments( &types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, - "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}) + "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res["f1"].Config) assert.Nil(t, res["f2"].Config) @@ -101,7 +101,7 @@ func TestTreatmentLabelsDisabled(t *testing.T) { cfg: conf.Config{LabelsEnabled: false}, } - res, err := client.Treatment(&types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, "key1", nil, "f1", Attributes{"a": 1}) + res, err := client.Treatment(&types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, "key1", nil, "f1", Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res.Config) assertImpEq(t, expectedImpression, res.Impression) @@ -156,7 +156,7 @@ func TestTreatmentLabelsEnabled(t *testing.T) { cfg: conf.Config{LabelsEnabled: true}, } - res, err := client.Treatment(&types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, "key1", nil, "f1", Attributes{"a": 1}) + res, err := client.Treatment(&types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, "key1", nil, "f1", Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res.Config) assertImpEq(t, expectedImpression, res.Impression) @@ -226,7 +226,7 @@ func TestTreatments(t *testing.T) { res, err := client.Treatments( &types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, - "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}) + "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res["f1"].Config) assert.Nil(t, res["f2"].Config) @@ -308,7 +308,7 @@ func TestTreatmentsWithImpressionProperties(t *testing.T) { } res, err := client.Treatments( &types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, - "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}, client.WithEvaluationOptions(&opts)) + "key1", nil, []string{"f1", "f2", "f3"}, Attributes{"a": 1}, &opts) assert.Nil(t, err) assert.Nil(t, res["f1"].Config) assert.Nil(t, res["f2"].Config) @@ -397,7 +397,7 @@ func TestTreatmentsByFlagSet(t *testing.T) { res, err := client.TreatmentsByFlagSet( &types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, - "key1", nil, "set", Attributes{"a": 1}) + "key1", nil, "set", Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res["f1"].Config) assert.Nil(t, res["f2"].Config) @@ -486,7 +486,7 @@ func TestTreatmentsByFlagSets(t *testing.T) { res, err := client.TreatmentsByFlagSets( &types.ClientConfig{Metadata: types.ClientMetadata{ID: "some", SdkVersion: "go-1.2.3"}}, - "key1", nil, []string{"set_1", "set_2"}, Attributes{"a": 1}) + "key1", nil, []string{"set_1", "set_2"}, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res["f1"].Config) assert.Nil(t, res["f2"].Config) @@ -555,7 +555,7 @@ func TestImpressionsQueueFull(t *testing.T) { for idx := 0; idx < 4; idx++ { feature := fmt.Sprintf("f%d", idx) expectedImpression.FeatureName = feature - res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}) + res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res.Config) assertImpEq(t, expectedImpression, res.Impression) @@ -567,7 +567,7 @@ func TestImpressionsQueueFull(t *testing.T) { for idx := 4; idx < 8; idx++ { feature := fmt.Sprintf("f%d", idx) expectedImpression.FeatureName = feature - res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}) + res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res.Config) assertImpEq(t, expectedImpression, res.Impression) @@ -577,7 +577,7 @@ func TestImpressionsQueueFull(t *testing.T) { feature := "f8" expectedImpression.FeatureName = feature - res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}) + res, err := client.Treatment(clientConf, "key1", nil, feature, Attributes{"a": 1}, nil) assert.Nil(t, err) assert.Nil(t, res.Config) assertImpEq(t, expectedImpression, res.Impression) From be31486e41b12d278c97c3fcc0a958de2778a1a5 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Mon, 26 Jan 2026 11:36:17 -0300 Subject: [PATCH 3/6] Updated docker file --- infra/sidecar.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/sidecar.Dockerfile b/infra/sidecar.Dockerfile index a26df79..e46f6e6 100644 --- a/infra/sidecar.Dockerfile +++ b/infra/sidecar.Dockerfile @@ -1,5 +1,5 @@ # ----- Builder image -ARG GOLANG_VERSION=1.23.6 +ARG GOLANG_VERSION=1.24.0 FROM golang:${GOLANG_VERSION}-bookworm AS builder ARG FIPS_MODE From eba3941e9972dfabca5590e728fc6cff56657e79 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 27 Jan 2026 12:28:31 -0300 Subject: [PATCH 4/6] Updated splitCli --- splitio/commitsha.go | 2 +- splitio/conf/splitcli.go | 61 +++++++++++++++++++++-------------- splitio/conf/splitcli_test.go | 2 ++ 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/splitio/commitsha.go b/splitio/commitsha.go index dfdefd0..49e4c75 100644 --- a/splitio/commitsha.go +++ b/splitio/commitsha.go @@ -1,3 +1,3 @@ package splitio -const CommitSHA = "a651b23" +const CommitSHA = "be31486" diff --git a/splitio/conf/splitcli.go b/splitio/conf/splitcli.go index b192f9b..01b3e07 100644 --- a/splitio/conf/splitcli.go +++ b/splitio/conf/splitcli.go @@ -25,15 +25,16 @@ type CliArgs struct { WriteTimeoutMS int // command - Method string - Key string - BucketingKey string - Feature string - Features []string - TrafficType string - EventType string - EventVal *float64 - Attributes map[string]interface{} + Method string + Key string + BucketingKey string + Feature string + Features []string + TrafficType string + EventType string + EventVal *float64 + Attributes map[string]interface{} + ImpressionProperties map[string]interface{} } func (a *CliArgs) LinkOpts() (*link.ConsumerOptions, error) { @@ -85,6 +86,7 @@ func ParseCliArgs() (*CliArgs, error) { et := cliFlags.String("event-type", "", "event type") ev := cliFlags.String("value", "", "event associated value") at := cliFlags.String("attributes", "", "json representation of attributes") + pr := cliFlags.String("impression-properties", "", "json representation of") err := cliFlags.Parse(os.Args[1:]) if err != nil { return nil, fmt.Errorf("error parsing arguments: %w", err) @@ -107,22 +109,31 @@ func ParseCliArgs() (*CliArgs, error) { return nil, fmt.Errorf("error parsing attributes: %w", err) } + if *pr == "" { + *pr = "null" + } + impressionPorperties := make(map[string]interface{}) + if err = json.Unmarshal([]byte(*pr), &impressionPorperties); err != nil { + return nil, fmt.Errorf("error parsing impression properties: %w", err) + } + return &CliArgs{ - ID: *id, - Serialization: *s, - Protocol: *p, - LogLevel: *ll, - ConnType: *ct, - ConnAddr: *ca, - BufSize: *bs, - Method: *m, - Key: *k, - BucketingKey: *bk, - Feature: *f, - Features: strings.Split(*fs, ","), - TrafficType: *tt, - EventType: *et, - EventVal: eventVal, - Attributes: attrs, + ID: *id, + Serialization: *s, + Protocol: *p, + LogLevel: *ll, + ConnType: *ct, + ConnAddr: *ca, + BufSize: *bs, + Method: *m, + Key: *k, + BucketingKey: *bk, + Feature: *f, + Features: strings.Split(*fs, ","), + TrafficType: *tt, + EventType: *et, + EventVal: eventVal, + Attributes: attrs, + ImpressionProperties: impressionPorperties, }, nil } diff --git a/splitio/conf/splitcli_test.go b/splitio/conf/splitcli_test.go index 102491b..c7e524a 100644 --- a/splitio/conf/splitcli_test.go +++ b/splitio/conf/splitcli_test.go @@ -25,6 +25,7 @@ func TestCliConfig(t *testing.T) { "-event-type=someEventType", "-value=0.123", `-attributes={"some": "attribute"}`, + `-impression-properties={"userId": "123", "age": 30, "premium": true, "balance": 99.5}`, } parsed, err := ParseCliArgs() @@ -42,6 +43,7 @@ func TestCliConfig(t *testing.T) { assert.Equal(t, "someEventType", parsed.EventType) assert.Equal(t, lang.Ref(float64(0.123)), parsed.EventVal) assert.Equal(t, map[string]interface{}{"some": "attribute"}, parsed.Attributes) + assert.Equal(t, map[string]interface{}{"userId": "123", "age": float64(30), "premium": true, "balance": 99.5}, parsed.ImpressionProperties) // test bad buffer size os.Args = []string{os.Args[0], "-buffer-size=sarasa"} From fb71b466f80ddbd5a0a65b844a90af51af99775b Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 30 Jan 2026 12:28:34 -0300 Subject: [PATCH 5/6] Updated rpcs logic to accept more than four params --- splitio/commitsha.go | 2 +- splitio/link/protocol/v1/rpcs.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/splitio/commitsha.go b/splitio/commitsha.go index 49e4c75..4c56802 100644 --- a/splitio/commitsha.go +++ b/splitio/commitsha.go @@ -1,3 +1,3 @@ package splitio -const CommitSHA = "be31486" +const CommitSHA = "eba3941" diff --git a/splitio/link/protocol/v1/rpcs.go b/splitio/link/protocol/v1/rpcs.go index 1c2ab23..8be45b4 100644 --- a/splitio/link/protocol/v1/rpcs.go +++ b/splitio/link/protocol/v1/rpcs.go @@ -218,7 +218,7 @@ func (t *TreatmentsArgs) PopulateFromRPC(rpc *RPC) error { if rpc.OpCode != OCTreatments && rpc.OpCode != OCTreatmentsWithConfig { return RPCParseError{Code: PECOpCodeMismatch} } - if len(rpc.Args) != 4 { + if len(rpc.Args) < 4 { return RPCParseError{Code: PECWrongArgCount} } From d2ecf77b859b391fc6e54ecaebbd0d9ef6e777c1 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 30 Jan 2026 13:01:57 -0300 Subject: [PATCH 6/6] Updated rpcs param condition --- splitio/link/protocol/v1/rpcs.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/splitio/link/protocol/v1/rpcs.go b/splitio/link/protocol/v1/rpcs.go index 8be45b4..4518739 100644 --- a/splitio/link/protocol/v1/rpcs.go +++ b/splitio/link/protocol/v1/rpcs.go @@ -150,7 +150,7 @@ func (t *TreatmentArgs) PopulateFromRPC(rpc *RPC) error { if rpc.OpCode != OCTreatment && rpc.OpCode != OCTreatmentWithConfig { return RPCParseError{Code: PECOpCodeMismatch} } - if len(rpc.Args) != 4 { + if len(rpc.Args) < 4 { return RPCParseError{Code: PECWrongArgCount} } @@ -289,7 +289,7 @@ func (t *TreatmentsByFlagSetArgs) PopulateFromRPC(rpc *RPC) error { if rpc.OpCode != OCTreatmentsByFlagSet && rpc.OpCode != OCTreatmentsWithConfigByFlagSet { return RPCParseError{Code: PECOpCodeMismatch} } - if len(rpc.Args) != 4 { + if len(rpc.Args) < 4 { return RPCParseError{Code: PECWrongArgCount} } @@ -353,7 +353,7 @@ func (t *TreatmentsByFlagSetsArgs) PopulateFromRPC(rpc *RPC) error { if rpc.OpCode != OCTreatmentsByFlagSets && rpc.OpCode != OCTreatmentsWithConfigByFlagSets { return RPCParseError{Code: PECOpCodeMismatch} } - if len(rpc.Args) != 4 { + if len(rpc.Args) < 4 { return RPCParseError{Code: PECWrongArgCount} }