@@ -209,18 +209,15 @@ Variation activate(@Nonnull ProjectConfig projectConfig,
209
209
logger .info ("Not activating user \" {}\" for experiment \" {}\" ." , userId , experiment .getKey ());
210
210
return null ;
211
211
}
212
- // determine whether all the given attributes are present in the project config. If not, filter out the unknown
213
- // attributes.
214
- Map <String , ?> filteredAttributes = filterAttributes (projectConfig , attributes );
215
-
212
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
216
213
// bucket the user to the given experiment and dispatch an impression event
217
- Variation variation = decisionService .getVariation (experiment , userId , filteredAttributes );
214
+ Variation variation = decisionService .getVariation (experiment , userId , copiedAttributes );
218
215
if (variation == null ) {
219
216
logger .info ("Not activating user \" {}\" for experiment \" {}\" ." , userId , experiment .getKey ());
220
217
return null ;
221
218
}
222
219
223
- sendImpression (projectConfig , experiment , userId , filteredAttributes , variation );
220
+ sendImpression (projectConfig , experiment , userId , copiedAttributes , variation );
224
221
225
222
return variation ;
226
223
}
@@ -292,6 +289,7 @@ public void track(@Nonnull String eventName,
292
289
}
293
290
294
291
ProjectConfig currentConfig = getProjectConfig ();
292
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
295
293
296
294
EventType eventType = currentConfig .getEventTypeForName (eventName , errorHandler );
297
295
if (eventType == null ) {
@@ -300,20 +298,15 @@ public void track(@Nonnull String eventName,
300
298
return ;
301
299
}
302
300
303
- // determine whether all the given attributes are present in the project config. If not, filter out the unknown
304
- // attributes.
305
- Map <String , ?> filteredAttributes = filterAttributes (currentConfig , attributes );
306
-
307
301
if (eventTags == null ) {
308
302
logger .warn ("Event tags is null when non-null was expected. Defaulting to an empty event tags map." );
309
- eventTags = Collections .<String , String >emptyMap ();
310
303
}
311
304
312
305
List <Experiment > experimentsForEvent = projectConfig .getExperimentsForEventKey (eventName );
313
306
Map <Experiment , Variation > experimentVariationMap = new HashMap <Experiment , Variation >(experimentsForEvent .size ());
314
307
for (Experiment experiment : experimentsForEvent ) {
315
308
if (experiment .isRunning ()) {
316
- Variation variation = decisionService .getVariation (experiment , userId , filteredAttributes );
309
+ Variation variation = decisionService .getVariation (experiment , userId , copiedAttributes );
317
310
if (variation != null ) {
318
311
experimentVariationMap .put (experiment , variation );
319
312
}
@@ -331,7 +324,7 @@ public void track(@Nonnull String eventName,
331
324
userId ,
332
325
eventType .getId (),
333
326
eventType .getKey (),
334
- filteredAttributes ,
327
+ copiedAttributes ,
335
328
eventTags );
336
329
337
330
if (conversionEvent == null ) {
@@ -354,7 +347,7 @@ public void track(@Nonnull String eventName,
354
347
}
355
348
356
349
notificationCenter .sendNotifications (NotificationCenter .NotificationType .Track , eventName , userId ,
357
- filteredAttributes , eventTags , conversionEvent );
350
+ copiedAttributes , eventTags , conversionEvent );
358
351
}
359
352
360
353
//======== FeatureFlag APIs ========//
@@ -406,17 +399,15 @@ else if (userId == null) {
406
399
logger .info ("No feature flag was found for key \" {}\" ." , featureKey );
407
400
return false ;
408
401
}
409
-
410
- Map <String , ?> filteredAttributes = filterAttributes (projectConfig , attributes );
411
-
412
- FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , filteredAttributes );
402
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
403
+ FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , copiedAttributes );
413
404
if (featureDecision .variation != null ) {
414
405
if (featureDecision .decisionSource .equals (FeatureDecision .DecisionSource .EXPERIMENT )) {
415
406
sendImpression (
416
407
projectConfig ,
417
408
featureDecision .experiment ,
418
409
userId ,
419
- filteredAttributes ,
410
+ copiedAttributes ,
420
411
featureDecision .variation );
421
412
} else {
422
413
logger .info ("The user \" {}\" is not included in an experiment for feature \" {}\" ." ,
@@ -655,8 +646,9 @@ else if (userId == null) {
655
646
}
656
647
657
648
String variableValue = variable .getDefaultValue ();
649
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
658
650
659
- FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , attributes );
651
+ FeatureDecision featureDecision = decisionService .getVariationForFeature (featureFlag , userId , copiedAttributes );
660
652
if (featureDecision .variation != null ) {
661
653
LiveVariableUsageInstance liveVariableUsageInstance =
662
654
featureDecision .variation .getVariableIdToLiveVariableUsageInstanceMap ().get (variable .getId ());
@@ -716,10 +708,9 @@ Variation getVariation(@Nonnull Experiment experiment,
716
708
Variation getVariation (@ Nonnull Experiment experiment ,
717
709
@ Nonnull String userId ,
718
710
@ Nonnull Map <String , ?> attributes ) throws UnknownExperimentException {
711
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
719
712
720
- Map <String , ?> filteredAttributes = filterAttributes (projectConfig , attributes );
721
-
722
- return decisionService .getVariation (experiment , userId , filteredAttributes );
713
+ return decisionService .getVariation (experiment , userId , copiedAttributes );
723
714
}
724
715
725
716
public @ Nullable
@@ -754,10 +745,8 @@ Variation getVariation(@Nonnull String experimentKey,
754
745
// if we're unable to retrieve the associated experiment, return null
755
746
return null ;
756
747
}
757
-
758
- Map <String , ?> filteredAttributes = filterAttributes (projectConfig , attributes );
759
-
760
- return decisionService .getVariation (experiment ,userId ,filteredAttributes );
748
+ Map <String , ?> copiedAttributes = copyAttributes (attributes );
749
+ return decisionService .getVariation (experiment , userId , copiedAttributes );
761
750
}
762
751
763
752
/**
@@ -817,50 +806,6 @@ public UserProfileService getUserProfileService() {
817
806
}
818
807
819
808
//======== Helper methods ========//
820
-
821
- /**
822
- * Helper method to verify that the given attributes map contains only keys that are present in the
823
- * {@link ProjectConfig}.
824
- *
825
- * @param projectConfig the current project config
826
- * @param attributes the attributes map to validate and potentially filter. Attributes which starts with reserved key
827
- * {@link ProjectConfig#RESERVED_ATTRIBUTE_PREFIX} are kept.
828
- * @return the filtered attributes map (containing only attributes that are present in the project config) or an
829
- * empty map if a null attributes object is passed in
830
- */
831
- private Map <String , ?> filterAttributes (@ Nonnull ProjectConfig projectConfig ,
832
- @ Nonnull Map <String , ?> attributes ) {
833
- if (attributes == null ) {
834
- logger .warn ("Attributes is null when non-null was expected. Defaulting to an empty attributes map." );
835
- return Collections .<String , String >emptyMap ();
836
- }
837
-
838
- // List of attribute keys
839
- List <String > unknownAttributes = null ;
840
-
841
- Map <String , Attribute > attributeKeyMapping = projectConfig .getAttributeKeyMapping ();
842
- for (Map .Entry <String , ?> attribute : attributes .entrySet ()) {
843
- if (!attributeKeyMapping .containsKey (attribute .getKey ()) &&
844
- !attribute .getKey ().startsWith (ProjectConfig .RESERVED_ATTRIBUTE_PREFIX )) {
845
- if (unknownAttributes == null ) {
846
- unknownAttributes = new ArrayList <String >();
847
- }
848
- unknownAttributes .add (attribute .getKey ());
849
- }
850
- }
851
-
852
- if (unknownAttributes != null ) {
853
- logger .warn ("Attribute(s) {} not in the datafile." , unknownAttributes );
854
- // make a copy of the passed through attributes, then remove the unknown list
855
- attributes = new HashMap <>(attributes );
856
- for (String unknownAttribute : unknownAttributes ) {
857
- attributes .remove (unknownAttribute );
858
- }
859
- }
860
-
861
- return attributes ;
862
- }
863
-
864
809
/**
865
810
* Helper function to check that the provided userId is valid
866
811
*
@@ -880,6 +825,20 @@ private boolean validateUserId(String userId) {
880
825
return true ;
881
826
}
882
827
828
+ /**
829
+ * Helper function to check that the provided attributes are null if not than it returns a copy
830
+ *
831
+ * @param attributes the attributes map being validated
832
+ * @return copy of attributes
833
+ */
834
+ private Map <String , ?> copyAttributes (Map <String , ?> attributes ) {
835
+ Map <String , ?> copiedAttributes = null ;
836
+ if (attributes != null ) {
837
+ copiedAttributes = new HashMap <>(attributes );
838
+ }
839
+ return copiedAttributes ;
840
+ }
841
+
883
842
//======== Builder ========//
884
843
885
844
public static Builder builder (@ Nonnull String datafile ,
0 commit comments