18
18
package client
19
19
20
20
import (
21
+ "encoding/json"
21
22
"errors"
22
23
"fmt"
23
24
"reflect"
@@ -120,6 +121,14 @@ func (o *OptimizelyClient) IsFeatureEnabled(featureKey string, userContext entit
120
121
o .logger .Info (fmt .Sprintf (`Feature "%s" is not enabled for user "%s".` , featureKey , userContext .ID ))
121
122
}
122
123
124
+ if o .notificationCenter != nil {
125
+ decisionNotification := decision .FeatureNotification (featureKey , & featureDecision , & userContext )
126
+
127
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
128
+ o .logger .Warning ("Problem with sending notification" )
129
+ }
130
+ }
131
+
123
132
if featureDecision .Source == decision .FeatureTest && featureDecision .Variation != nil {
124
133
// send impression event for feature tests
125
134
impressionEvent := event .CreateImpressionUserEvent (decisionContext .ProjectConfig , featureDecision .Experiment , * featureDecision .Variation , userContext )
@@ -164,93 +173,230 @@ func (o *OptimizelyClient) GetEnabledFeatures(userContext entities.UserContext)
164
173
}
165
174
166
175
// GetFeatureVariableBoolean returns the feature variable value of type bool associated with the given feature and variable keys.
167
- func (o * OptimizelyClient ) GetFeatureVariableBoolean (featureKey , variableKey string , userContext entities.UserContext ) (value bool , err error ) {
176
+ func (o * OptimizelyClient ) GetFeatureVariableBoolean (featureKey , variableKey string , userContext entities.UserContext ) (convertedValue bool , err error ) {
177
+
178
+ stringValue , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
179
+ defer func () {
180
+ if o .notificationCenter != nil {
181
+ variableMap := map [string ]interface {}{
182
+ "variableKey" : variableKey ,
183
+ "variableType" : variableType ,
184
+ "variableValue" : convertedValue ,
185
+ }
186
+ if err != nil {
187
+ variableMap ["variableValue" ] = stringValue
188
+ }
189
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
190
+ decisionNotification .Type = notification .FeatureVariable
191
+
192
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
193
+ o .logger .Warning ("Problem with sending notification" )
194
+ }
195
+ }
196
+ }()
168
197
169
- val , valueType , err := o .GetFeatureVariable (featureKey , variableKey , userContext )
170
198
if err != nil {
171
- return false , err
199
+ return convertedValue , err
172
200
}
173
- convertedValue , err : = strconv .ParseBool (val )
174
- if err != nil || valueType != entities .Boolean {
201
+ convertedValue , err = strconv .ParseBool (stringValue )
202
+ if err != nil || variableType != entities .Boolean {
175
203
return false , fmt .Errorf ("variable value for key %s is invalid or wrong type" , variableKey )
176
204
}
177
205
return convertedValue , err
178
206
}
179
207
180
208
// GetFeatureVariableDouble returns the feature variable value of type double associated with the given feature and variable keys.
181
- func (o * OptimizelyClient ) GetFeatureVariableDouble (featureKey , variableKey string , userContext entities.UserContext ) (value float64 , err error ) {
209
+ func (o * OptimizelyClient ) GetFeatureVariableDouble (featureKey , variableKey string , userContext entities.UserContext ) (convertedValue float64 , err error ) {
182
210
183
- val , valueType , err := o .GetFeatureVariable (featureKey , variableKey , userContext )
211
+ stringValue , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
212
+ defer func () {
213
+ if o .notificationCenter != nil {
214
+ variableMap := map [string ]interface {}{
215
+ "variableKey" : variableKey ,
216
+ "variableType" : variableType ,
217
+ "variableValue" : convertedValue ,
218
+ }
219
+ if err != nil {
220
+ variableMap ["variableValue" ] = stringValue
221
+ }
222
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
223
+ decisionNotification .Type = notification .FeatureVariable
224
+
225
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
226
+ o .logger .Warning ("Problem with sending notification" )
227
+ }
228
+ }
229
+ }()
184
230
if err != nil {
185
- return 0 , err
231
+ return convertedValue , err
186
232
}
187
- convertedValue , err : = strconv .ParseFloat (val , 64 )
188
- if err != nil || valueType != entities .Double {
233
+ convertedValue , err = strconv .ParseFloat (stringValue , 64 )
234
+ if err != nil || variableType != entities .Double {
189
235
return 0 , fmt .Errorf ("variable value for key %s is invalid or wrong type" , variableKey )
190
236
}
237
+
191
238
return convertedValue , err
192
239
}
193
240
194
241
// GetFeatureVariableInteger returns the feature variable value of type int associated with the given feature and variable keys.
195
- func (o * OptimizelyClient ) GetFeatureVariableInteger (featureKey , variableKey string , userContext entities.UserContext ) (value int , err error ) {
242
+ func (o * OptimizelyClient ) GetFeatureVariableInteger (featureKey , variableKey string , userContext entities.UserContext ) (convertedValue int , err error ) {
196
243
197
- val , valueType , err := o .GetFeatureVariable (featureKey , variableKey , userContext )
244
+ stringValue , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
245
+ defer func () {
246
+ if o .notificationCenter != nil {
247
+ variableMap := map [string ]interface {}{
248
+ "variableKey" : variableKey ,
249
+ "variableType" : variableType ,
250
+ "variableValue" : convertedValue ,
251
+ }
252
+ if err != nil {
253
+ variableMap ["variableValue" ] = stringValue
254
+ }
255
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
256
+ decisionNotification .Type = notification .FeatureVariable
257
+
258
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
259
+ o .logger .Warning ("Problem with sending notification" )
260
+ }
261
+ }
262
+ }()
198
263
if err != nil {
199
- return 0 , err
264
+ return convertedValue , err
200
265
}
201
- convertedValue , err : = strconv .Atoi (val )
202
- if err != nil || valueType != entities .Integer {
266
+ convertedValue , err = strconv .Atoi (stringValue )
267
+ if err != nil || variableType != entities .Integer {
203
268
return 0 , fmt .Errorf ("variable value for key %s is invalid or wrong type" , variableKey )
204
269
}
270
+
205
271
return convertedValue , err
206
272
}
207
273
208
274
// GetFeatureVariableString returns the feature variable value of type string associated with the given feature and variable keys.
209
- func (o * OptimizelyClient ) GetFeatureVariableString (featureKey , variableKey string , userContext entities.UserContext ) (value string , err error ) {
275
+ func (o * OptimizelyClient ) GetFeatureVariableString (featureKey , variableKey string , userContext entities.UserContext ) (stringValue string , err error ) {
276
+
277
+ stringValue , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
278
+
279
+ defer func () {
280
+ if o .notificationCenter != nil {
281
+ variableMap := map [string ]interface {}{
282
+ "variableKey" : variableKey ,
283
+ "variableType" : variableType ,
284
+ "variableValue" : stringValue ,
285
+ }
286
+
287
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
288
+ decisionNotification .Type = notification .FeatureVariable
210
289
211
- value , valueType , err := o .GetFeatureVariable (featureKey , variableKey , userContext )
290
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
291
+ o .logger .Warning ("Problem with sending notification" )
292
+ }
293
+ }
294
+ }()
212
295
if err != nil {
213
296
return "" , err
214
297
}
215
- if valueType != entities .String {
298
+ if variableType != entities .String {
216
299
return "" , fmt .Errorf ("variable value for key %s is wrong type" , variableKey )
217
300
}
218
- return value , err
301
+
302
+ return stringValue , err
219
303
}
220
304
221
305
// GetFeatureVariableJSON returns the feature variable value of type json associated with the given feature and variable keys.
222
- func (o * OptimizelyClient ) GetFeatureVariableJSON (featureKey , variableKey string , userContext entities.UserContext ) (value * optimizelyjson.OptimizelyJSON , err error ) {
306
+ func (o * OptimizelyClient ) GetFeatureVariableJSON (featureKey , variableKey string , userContext entities.UserContext ) (optlyJSON * optimizelyjson.OptimizelyJSON , err error ) {
223
307
224
- val , valueType , err := o .GetFeatureVariable (featureKey , variableKey , userContext )
308
+ stringVal , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
309
+ defer func () {
310
+ if o .notificationCenter != nil {
311
+ var variableValue interface {}
312
+ if optlyJSON != nil {
313
+ variableValue = optlyJSON .ToMap ()
314
+ } else {
315
+ variableValue = stringVal
316
+ }
317
+ variableMap := map [string ]interface {}{
318
+ "variableKey" : variableKey ,
319
+ "variableType" : variableType ,
320
+ "variableValue" : variableValue ,
321
+ }
322
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
323
+ decisionNotification .Type = notification .FeatureVariable
324
+
325
+ if e := o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
326
+ o .logger .Warning ("Problem with sending notification" )
327
+ }
328
+ }
329
+ }()
225
330
if err != nil {
226
- return value , err
331
+ return optlyJSON , err
227
332
}
228
333
229
- value , err = optimizelyjson .NewOptimizelyJSONfromString (val )
230
- if err != nil || valueType != entities .JSON {
231
- return nil , fmt .Errorf ("variable value for key %s is invalid or wrong type" , variableKey )
334
+ optlyJSON , err = optimizelyjson .NewOptimizelyJSONfromString (stringVal )
335
+ if err != nil || variableType != entities .JSON {
336
+ optlyJSON , err = nil , fmt .Errorf ("variable value for key %s is invalid or wrong type" , variableKey )
232
337
}
233
338
234
- return value , err
339
+ return optlyJSON , err
235
340
}
236
341
237
- // GetFeatureVariable returns feature variable as a string along with it's associated type.
238
- func (o * OptimizelyClient ) GetFeatureVariable (featureKey , variableKey string , userContext entities.UserContext ) (value string , valueType entities.VariableType , err error ) {
342
+ // getFeatureVariable is a helper function, returns feature variable as a string along with it's associated type and feature decision
343
+ func (o * OptimizelyClient ) getFeatureVariable (featureKey , variableKey string , userContext entities.UserContext ) (string , entities.VariableType , * decision. FeatureDecision , error ) {
239
344
240
345
featureDecisionContext , featureDecision , err := o .getFeatureDecision (featureKey , variableKey , userContext )
241
346
if err != nil {
242
- return "" , "" , err
347
+ return "" , "" , & featureDecision , err
243
348
}
244
349
245
350
variable := featureDecisionContext .Variable
246
351
247
352
if featureDecision .Variation != nil {
248
353
if v , ok := featureDecision .Variation .Variables [variable .ID ]; ok && featureDecision .Variation .FeatureEnabled {
249
- return v .Value , variable .Type , err
354
+ return v .Value , variable .Type , & featureDecision , nil
250
355
}
251
356
}
252
357
253
- return variable .DefaultValue , variable .Type , err
358
+ return variable .DefaultValue , variable .Type , & featureDecision , nil
359
+ }
360
+
361
+ // GetFeatureVariable returns feature variable as a string along with it's associated type.
362
+ func (o * OptimizelyClient ) GetFeatureVariable (featureKey , variableKey string , userContext entities.UserContext ) (string , entities.VariableType , error ) {
363
+
364
+ stringValue , variableType , featureDecision , err := o .getFeatureVariable (featureKey , variableKey , userContext )
365
+
366
+ func () {
367
+ var convertedValue interface {}
368
+ var e error
369
+
370
+ convertedValue = stringValue
371
+ switch variableType {
372
+ case entities .Integer :
373
+ convertedValue , e = strconv .Atoi (stringValue )
374
+ case entities .Double :
375
+ convertedValue , e = strconv .ParseFloat (stringValue , 64 )
376
+ case entities .Boolean :
377
+ convertedValue , e = strconv .ParseBool (stringValue )
378
+ case entities .JSON :
379
+ convertedValue = map [string ]string {}
380
+ e = json .Unmarshal ([]byte (stringValue ), & convertedValue )
381
+ }
382
+ if e != nil {
383
+ o .logger .Warning ("Problem with converting string value to proper type for notification builder" )
384
+ }
385
+
386
+ variableMap := map [string ]interface {}{
387
+ "variableKey" : variableKey ,
388
+ "variableType" : variableType ,
389
+ "variableValue" : convertedValue ,
390
+ }
391
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , featureDecision , & userContext , variableMap )
392
+ decisionNotification .Type = notification .FeatureVariable
393
+
394
+ if e = o .notificationCenter .Send (notification .Decision , * decisionNotification ); e != nil {
395
+ o .logger .Warning ("Problem with sending notification" )
396
+ }
397
+ }()
398
+
399
+ return stringValue , variableType , err
254
400
}
255
401
256
402
// GetAllFeatureVariablesWithDecision returns all the variables for a given feature along with the enabled state.
@@ -297,7 +443,8 @@ func (o *OptimizelyClient) GetAllFeatureVariablesWithDecision(featureKey string,
297
443
out , err = strconv .Atoi (val )
298
444
errs = multierror .Append (errs , err )
299
445
case entities .JSON :
300
- var optlyJSON , err = optimizelyjson .NewOptimizelyJSONfromString (val )
446
+ var optlyJSON * optimizelyjson.OptimizelyJSON
447
+ optlyJSON , err = optimizelyjson .NewOptimizelyJSONfromString (val )
301
448
out = optlyJSON .ToMap ()
302
449
errs = multierror .Append (errs , err )
303
450
case entities .String :
@@ -308,6 +455,15 @@ func (o *OptimizelyClient) GetAllFeatureVariablesWithDecision(featureKey string,
308
455
variableMap [v .Key ] = out
309
456
}
310
457
458
+ if o .notificationCenter != nil {
459
+ decisionNotification := decision .FeatureNotificationWithVariables (featureKey , & featureDecision , & userContext ,
460
+ map [string ]interface {}{"variableValues" : variableMap })
461
+ decisionNotification .Type = notification .AllFeatureVariables
462
+
463
+ if err = o .notificationCenter .Send (notification .Decision , * decisionNotification ); err != nil {
464
+ o .logger .Warning ("Problem with sending notification" )
465
+ }
466
+ }
311
467
return enabled , variableMap , errs .ErrorOrNil ()
312
468
}
313
469
0 commit comments