2727 */
2828@ JsonAdapter (EvaluationReasonTypeAdapter .class )
2929public final class EvaluationReason implements JsonSerializable {
30+ private static boolean IN_EXPERIMENT = true ;
31+ private static boolean NOT_IN_EXPERIMENT = false ;
32+
3033 /**
3134 * Enumerated type defining the possible values of {@link EvaluationReason#getKind()}.
3235 */
@@ -96,6 +99,7 @@ public static enum ErrorKind {
9699 // static instances to avoid repeatedly allocating reasons for the same parameters
97100 private static final EvaluationReason OFF_INSTANCE = new EvaluationReason (Kind .OFF );
98101 private static final EvaluationReason FALLTHROUGH_INSTANCE = new EvaluationReason (Kind .FALLTHROUGH );
102+ private static final EvaluationReason FALLTHROUGH_INSTANCE_IN_EXPERIMENT = new EvaluationReason (Kind .FALLTHROUGH , IN_EXPERIMENT );
99103 private static final EvaluationReason TARGET_MATCH_INSTANCE = new EvaluationReason (Kind .TARGET_MATCH );
100104 private static final EvaluationReason ERROR_CLIENT_NOT_READY = new EvaluationReason (ErrorKind .CLIENT_NOT_READY , null );
101105 private static final EvaluationReason ERROR_FLAG_NOT_FOUND = new EvaluationReason (ErrorKind .FLAG_NOT_FOUND , null );
@@ -108,25 +112,31 @@ public static enum ErrorKind {
108112 private final int ruleIndex ;
109113 private final String ruleId ;
110114 private final String prerequisiteKey ;
115+ private final boolean inExperiment ;
111116 private final ErrorKind errorKind ;
112117 private final Exception exception ;
113118
114- private EvaluationReason (Kind kind , int ruleIndex , String ruleId , String prerequisiteKey ,
119+ private EvaluationReason (Kind kind , int ruleIndex , String ruleId , String prerequisiteKey , boolean inExperiment ,
115120 ErrorKind errorKind , Exception exception ) {
116121 this .kind = kind ;
117122 this .ruleIndex = ruleIndex ;
118123 this .ruleId = ruleId ;
119124 this .prerequisiteKey = prerequisiteKey ;
125+ this .inExperiment = inExperiment ;
120126 this .errorKind = errorKind ;
121127 this .exception = exception ;
122128 }
123129
124130 private EvaluationReason (Kind kind ) {
125- this (kind , -1 , null , null , null , null );
131+ this (kind , -1 , null , null , NOT_IN_EXPERIMENT , null , null );
132+ }
133+
134+ private EvaluationReason (Kind kind , boolean inExperiment ) {
135+ this (kind , -1 , null , null , inExperiment , null , null );
126136 }
127137
128138 private EvaluationReason (ErrorKind errorKind , Exception exception ) {
129- this (Kind .ERROR , -1 , null , null , errorKind , exception );
139+ this (Kind .ERROR , -1 , null , null , NOT_IN_EXPERIMENT , errorKind , exception );
130140 }
131141
132142 /**
@@ -171,6 +181,17 @@ public String getPrerequisiteKey() {
171181 return prerequisiteKey ;
172182 }
173183
184+ /**
185+ * Whether the evaluation was part of an experiment. Returns true if the evaluation
186+ * resulted in an experiment rollout *and* served one of the variations in the
187+ * experiment. Otherwise it returns false.
188+ *
189+ * @return whether the evaluation was part of an experiment
190+ */
191+ public boolean isInExperiment () {
192+ return inExperiment ;
193+ }
194+
174195 /**
175196 * An enumeration value indicating the general category of error, if the
176197 * {@code kind} is {@link Kind#PREREQUISITE_FAILED}. Otherwise {@code null}.
@@ -223,16 +244,20 @@ public boolean equals(Object other) {
223244 }
224245 if (other instanceof EvaluationReason ) {
225246 EvaluationReason o = (EvaluationReason )other ;
226- return kind == o .kind && ruleIndex == o .ruleIndex && Objects .equals (ruleId , o .ruleId )&&
227- Objects .equals (prerequisiteKey , o .prerequisiteKey ) && Objects .equals (errorKind , o .errorKind ) &&
228- Objects .equals (exception , o .exception );
247+ return kind == o .kind &&
248+ ruleIndex == o .ruleIndex &&
249+ Objects .equals (ruleId , o .ruleId ) &&
250+ Objects .equals (prerequisiteKey , o .prerequisiteKey ) &&
251+ inExperiment == o .inExperiment &&
252+ Objects .equals (errorKind , o .errorKind ) &&
253+ Objects .equals (exception , o .exception );
229254 }
230255 return false ;
231256 }
232257
233258 @ Override
234259 public int hashCode () {
235- return Objects .hash (kind , ruleIndex , ruleId , prerequisiteKey , errorKind , exception );
260+ return Objects .hash (kind , ruleIndex , ruleId , prerequisiteKey , inExperiment , errorKind , exception );
236261 }
237262
238263 /**
@@ -253,6 +278,18 @@ public static EvaluationReason fallthrough() {
253278 return FALLTHROUGH_INSTANCE ;
254279 }
255280
281+ /**
282+ * Returns an instance whose {@code kind} is {@link Kind#FALLTHROUGH} and
283+ * where the inExperiment parameter represents whether the evaluation was
284+ * part of an experiment.
285+ *
286+ * @param inExperiment whether the evaluation was part of an experiment
287+ * @return a reason object
288+ */
289+ public static EvaluationReason fallthrough (boolean inExperiment ) {
290+ return inExperiment ? FALLTHROUGH_INSTANCE_IN_EXPERIMENT : FALLTHROUGH_INSTANCE ;
291+ }
292+
256293 /**
257294 * Returns an instance whose {@code kind} is {@link Kind#TARGET_MATCH}.
258295 *
@@ -270,7 +307,21 @@ public static EvaluationReason targetMatch() {
270307 * @return a reason object
271308 */
272309 public static EvaluationReason ruleMatch (int ruleIndex , String ruleId ) {
273- return new EvaluationReason (Kind .RULE_MATCH , ruleIndex , ruleId , null , null , null );
310+ return ruleMatch (ruleIndex , ruleId , NOT_IN_EXPERIMENT );
311+ }
312+
313+ /**
314+ * Returns an instance whose {@code kind} is {@link Kind#RULE_MATCH} and
315+ * where the inExperiment parameter represents whether the evaluation was
316+ * part of an experiment.
317+ *
318+ * @param ruleIndex the rule index
319+ * @param ruleId the rule identifier
320+ * @param inExperiment whether the evaluation was part of an experiment
321+ * @return a reason object
322+ */
323+ public static EvaluationReason ruleMatch (int ruleIndex , String ruleId , boolean inExperiment ) {
324+ return new EvaluationReason (Kind .RULE_MATCH , ruleIndex , ruleId , null , inExperiment , null , null );
274325 }
275326
276327 /**
@@ -280,7 +331,7 @@ public static EvaluationReason ruleMatch(int ruleIndex, String ruleId) {
280331 * @return a reason object
281332 */
282333 public static EvaluationReason prerequisiteFailed (String prerequisiteKey ) {
283- return new EvaluationReason (Kind .PREREQUISITE_FAILED , -1 , null , prerequisiteKey , null , null );
334+ return new EvaluationReason (Kind .PREREQUISITE_FAILED , -1 , null , prerequisiteKey , NOT_IN_EXPERIMENT , null , null );
284335 }
285336
286337 /**
0 commit comments