Skip to content

Commit 4db8193

Browse files
mfahadahmednchilada
authored andcommitted
feat(Audience Evaluation): Audience Logging (#130)
Summary ------- This adds logging support to audience evaluation.
1 parent ee353e5 commit 4db8193

17 files changed

+497
-176
lines changed

OptimizelySDK.Tests/AudienceConditionsTests/ConditionEvaluationTest.cs

+158-52
Large diffs are not rendered by default.

OptimizelySDK.Tests/AudienceConditionsTests/ConditionsTest.cs

+27-19
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using NUnit.Framework;
1919
using OptimizelySDK.AudienceConditions;
2020
using OptimizelySDK.Entity;
21+
using OptimizelySDK.Logger;
2122

2223
namespace OptimizelySDK.Tests.AudienceConditionsTests
2324
{
@@ -32,19 +33,26 @@ public class ConditionsTest
3233
private ICondition FalseCondition;
3334
private ICondition NullCondition;
3435

36+
private ILogger Logger;
37+
private Mock<ILogger> MockLogger;
38+
3539
[TestFixtureSetUp]
3640
public void Initialize()
3741
{
3842
TrueConditionMock = new Mock<ICondition>();
39-
TrueConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>())).Returns(true);
43+
TrueConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>(), It.IsAny<ILogger>())).Returns(true);
4044
FalseConditionMock = new Mock<ICondition>();
41-
FalseConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>())).Returns(false);
45+
FalseConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>(), It.IsAny<ILogger>())).Returns(false);
4246
NullConditionMock = new Mock<ICondition>();
43-
NullConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>())).Returns((bool?)null);
47+
NullConditionMock.Setup(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>(), It.IsAny<ILogger>())).Returns((bool?)null);
4448

4549
TrueCondition = TrueConditionMock.Object;
4650
FalseCondition = FalseConditionMock.Object;
4751
NullCondition = NullConditionMock.Object;
52+
53+
MockLogger = new Mock<ILogger>();
54+
MockLogger.Setup(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()));
55+
Logger = MockLogger.Object;
4856
}
4957

5058
#region AND Condition Tests
@@ -55,7 +63,7 @@ public void TestAndEvaluatorReturnsTrueWhenAllOperandsEvaluateToTrue()
5563
ICondition[] conditions = new ICondition[] { TrueCondition, TrueCondition };
5664
var andCondition = new AndCondition { Conditions = conditions };
5765

58-
Assert.That(andCondition.Evaluate(null, null), Is.True);
66+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.True);
5967
}
6068

6169
[Test]
@@ -64,10 +72,10 @@ public void TestAndEvaluatorReturnsFalseWhenAnyOperandEvaluatesToFalse()
6472
ICondition[] conditions = new ICondition[] { FalseCondition, TrueCondition };
6573
var andCondition = new AndCondition { Conditions = conditions };
6674

67-
Assert.That(andCondition.Evaluate(null, null), Is.False);
75+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.False);
6876

6977
// Should not be called due to short circuiting.
70-
TrueConditionMock.Verify(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>()), Times.Never);
78+
TrueConditionMock.Verify(condition => condition.Evaluate(It.IsAny<ProjectConfig>(), It.IsAny<UserAttributes>(), Logger), Times.Never);
7179
}
7280

7381
[Test]
@@ -76,7 +84,7 @@ public void TestAndEvaluatorReturnsNullWhenAllOperandsEvaluateToNull()
7684
ICondition[] conditions = new ICondition[] { NullCondition, NullCondition };
7785
var andCondition = new AndCondition { Conditions = conditions };
7886

79-
Assert.That(andCondition.Evaluate(null, null), Is.Null);
87+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.Null);
8088
}
8189

8290
[Test]
@@ -85,7 +93,7 @@ public void TestAndEvaluatorReturnsNullWhenOperandsEvaluateToTrueAndNull()
8593
ICondition[] conditions = new ICondition[] { TrueCondition, NullCondition, TrueCondition };
8694
var andCondition = new AndCondition { Conditions = conditions };
8795

88-
Assert.That(andCondition.Evaluate(null, null), Is.Null);
96+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.Null);
8997
}
9098

9199
[Test]
@@ -94,7 +102,7 @@ public void TestAndEvaluatorReturnsFalseWhenOperandsEvaluateToFalseAndNull()
94102
ICondition[] conditions = new ICondition[] { NullCondition, FalseCondition, NullCondition };
95103
var andCondition = new AndCondition { Conditions = conditions };
96104

97-
Assert.That(andCondition.Evaluate(null, null), Is.False);
105+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.False);
98106
}
99107

100108
[Test]
@@ -103,7 +111,7 @@ public void TestAndEvaluatorReturnsFalseWhenOperandsEvaluateToTrueFalseAndNull()
103111
ICondition[] conditions = new ICondition[] { TrueCondition, FalseCondition, NullCondition };
104112
var andCondition = new AndCondition { Conditions = conditions };
105113

106-
Assert.That(andCondition.Evaluate(null, null), Is.False);
114+
Assert.That(andCondition.Evaluate(null, null, Logger), Is.False);
107115
}
108116

109117
#endregion // AND Condition Tests
@@ -116,7 +124,7 @@ public void TestOrEvaluatorReturnsTrueWhenAnyOperandEvaluatesToTrue()
116124
ICondition[] conditions = new ICondition[] { TrueCondition, FalseCondition, NullCondition };
117125
var orCondition = new OrCondition { Conditions = conditions };
118126

119-
Assert.That(orCondition.Evaluate(null, null), Is.True);
127+
Assert.That(orCondition.Evaluate(null, null, Logger), Is.True);
120128
}
121129

122130
[Test]
@@ -125,7 +133,7 @@ public void TestOrEvaluatorReturnsFalseWhenAllOperandsEvaluatesToFalse()
125133
ICondition[] conditions = new ICondition[] { FalseCondition, FalseCondition };
126134
var orCondition = new OrCondition { Conditions = conditions };
127135

128-
Assert.That(orCondition.Evaluate(null, null), Is.False);
136+
Assert.That(orCondition.Evaluate(null, null, Logger), Is.False);
129137
}
130138

131139
[Test]
@@ -134,7 +142,7 @@ public void TestOrEvaluatorReturnsNullWhenOperandsEvaluateToFalseAndNull()
134142
ICondition[] conditions = new ICondition[] { FalseCondition, NullCondition, FalseCondition };
135143
var orCondition = new OrCondition { Conditions = conditions };
136144

137-
Assert.That(orCondition.Evaluate(null, null), Is.Null);
145+
Assert.That(orCondition.Evaluate(null, null, Logger), Is.Null);
138146
}
139147

140148
[Test]
@@ -143,7 +151,7 @@ public void TestOrEvaluatorReturnsTrueWhenOperandsEvaluateToTrueAndNull()
143151
ICondition[] conditions = new ICondition[] { TrueCondition, NullCondition, TrueCondition };
144152
var orCondition = new OrCondition { Conditions = conditions };
145153

146-
Assert.That(orCondition.Evaluate(null, null), Is.True);
154+
Assert.That(orCondition.Evaluate(null, null, Logger), Is.True);
147155
}
148156

149157
[Test]
@@ -152,7 +160,7 @@ public void TestOrEvaluatorReturnsTrueWhenOperandsEvaluateToFalseTrueAndNull()
152160
ICondition[] conditions = new ICondition[] { FalseCondition, NullCondition, TrueCondition };
153161
var orCondition = new OrCondition { Conditions = conditions };
154162

155-
Assert.That(orCondition.Evaluate(null, null), Is.True);
163+
Assert.That(orCondition.Evaluate(null, null, Logger), Is.True);
156164
}
157165

158166
#endregion // OR Condition Tests
@@ -163,28 +171,28 @@ public void TestOrEvaluatorReturnsTrueWhenOperandsEvaluateToFalseTrueAndNull()
163171
public void TestNotEvaluatorReturnsNullWhenOperandEvaluateToNull()
164172
{
165173
var notCondition = new NotCondition { Condition = NullCondition };
166-
Assert.That(notCondition.Evaluate(null, null), Is.Null);
174+
Assert.That(notCondition.Evaluate(null, null, Logger), Is.Null);
167175
}
168176

169177
[Test]
170178
public void TestNotEvaluatorReturnsTrueWhenOperandEvaluateToFalse()
171179
{
172180
var notCondition = new NotCondition { Condition = FalseCondition };
173-
Assert.That(notCondition.Evaluate(null, null), Is.True);
181+
Assert.That(notCondition.Evaluate(null, null, Logger), Is.True);
174182
}
175183

176184
[Test]
177185
public void TestNotEvaluatorReturnsFalseWhenOperandEvaluateToTrue()
178186
{
179187
var notCondition = new NotCondition { Condition = TrueCondition };
180-
Assert.That(notCondition.Evaluate(null, null), Is.False);
188+
Assert.That(notCondition.Evaluate(null, null, Logger), Is.False);
181189
}
182190

183191
[Test]
184192
public void TestNotEvaluatorReturnsNullWhenConditionIsNull()
185193
{
186194
var notCondition = new NotCondition { Condition = null };
187-
Assert.That(notCondition.Evaluate(null, null), Is.Null);
195+
Assert.That(notCondition.Evaluate(null, null, Logger), Is.Null);
188196
}
189197

190198
#endregion // NOT Condition Tests

OptimizelySDK.Tests/OptimizelyTest.cs

+10-23
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ public void TestValidatePreconditionsUserNotInForcedVariationInExperiment()
281281
};
282282

283283
var variation = Optimizely.GetVariation("test_experiment", "test_user", attributes);
284-
285-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(4));
284+
286285
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "User \"test_user\" is not in the forced variation map."), Times.Once);
287286
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
288287
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [test_user] is in variation [control] of experiment [test_experiment]."), Times.Once);
@@ -327,8 +326,7 @@ public void TestActivateUserInNoVariation()
327326

328327
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), It.IsAny<Experiment>(),
329328
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UserAttributes>()), Times.Never);
330-
331-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(4));
329+
332330
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [8495] to user [not_in_variation_user] with bucketing ID [not_in_variation_user]."), Times.Once);
333331
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [not_in_variation_user] is in no variation."), Times.Once);
334332
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "Not activating user not_in_variation_user."), Times.Once);
@@ -356,8 +354,7 @@ public void TestActivateNoAudienceNoAttributes()
356354

357355
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), Config.GetExperimentFromKey("group_experiment_1"),
358356
"7722360022", "user_1", null), Times.Once);
359-
360-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(8));
357+
361358
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [1922] to user [user_1] with bucketing ID [user_1]."), Times.Once);
362359
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [user_1] is in experiment [group_experiment_1] of group [7722400015]."), Times.Once);
363360
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [9525] to user [user_1] with bucketing ID [user_1]."), Times.Once);
@@ -380,8 +377,7 @@ public void TestActivateAudienceNoAttributes()
380377

381378
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), It.IsAny<Experiment>(),
382379
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UserAttributes>()), Times.Never);
383-
384-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(3));
380+
385381
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User \"test_user\" does not meet conditions to be in experiment \"test_experiment\"."), Times.Once);
386382
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "Not activating user test_user."), Times.Once);
387383

@@ -403,8 +399,6 @@ public void TestActivateWithAttributes()
403399
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), Config.GetExperimentFromKey("test_experiment"),
404400
"7722370027", "test_user", OptimizelyHelper.UserAttributes), Times.Once);
405401

406-
407-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(6));
408402
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "User \"test_user\" is not in the forced variation map."), Times.Once);
409403
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
410404
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [test_user] is in variation [control] of experiment [test_experiment]."), Times.Once);
@@ -429,9 +423,7 @@ public void TestActivateWithNullAttributes()
429423

430424
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), Config.GetExperimentFromKey("test_experiment"),
431425
"7722370027", "test_user", OptimizelyHelper.NullUserAttributes), Times.Once);
432-
433-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(6));
434-
426+
435427
//"User "test_user" is not in the forced variation map."
436428
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "User \"test_user\" is not in the forced variation map."), Times.Once);
437429
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
@@ -483,8 +475,7 @@ public void TestActivateWithTypedAttributes()
483475

484476
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), Config.GetExperimentFromKey("test_experiment"),
485477
"7722370027", "test_user", userAttributes), Times.Once);
486-
487-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(6));
478+
488479
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
489480
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [test_user] is in variation [control] of experiment [test_experiment]."), Times.Once);
490481
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "Activating user test_user in experiment test_experiment."), Times.Once);
@@ -530,8 +521,7 @@ public void TestGetVariationAudienceMatch()
530521
};
531522

532523
var variation = Optimizely.GetVariation("test_experiment", "test_user", attributes);
533-
534-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(4));
524+
535525
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
536526
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [test_user] is in variation [control] of experiment [test_experiment]."), Times.Once);
537527
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "This decision will not be saved since the UserProfileService is null."), Times.Once);
@@ -701,8 +691,7 @@ public void TestInvalidDispatchImpressionEvent()
701691
optly.SetFieldOrProperty("EventDispatcher", new InvalidEventDispatcher());
702692

703693
var variation = (Variation)optly.Invoke("Activate", "test_experiment", "test_user", OptimizelyHelper.UserAttributes);
704-
705-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(7));
694+
706695
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [3037] to user [test_user] with bucketing ID [test_user]."), Times.Once);
707696
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "User [test_user] is in variation [control] of experiment [test_experiment]."), Times.Once);
708697
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "Activating user test_user in experiment test_experiment."), Times.Once);
@@ -841,8 +830,7 @@ public void TestForcedVariationPreceedsUserProfile()
841830

842831
variationUserProfile = optimizely.GetVariation(experimentKey, userId);
843832
Assert.IsTrue(TestData.CompareObjects(expectedVariation, variationUserProfile));
844-
845-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(13));
833+
846834
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "User \"testUser3\" is not in the forced variation map."), Times.Once);
847835
LoggerMock.Verify(l => l.Log(LogLevel.INFO, "No previously activated variation of experiment \"etag1\" for user \"testUser3\" found in user profile."), Times.Exactly(2));
848836
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [4969] to user [testUser3] with bucketing ID [testUser3]."), Times.Exactly(2));
@@ -1117,8 +1105,7 @@ public void TestActivateNoAudienceNoAttributesAfterSetForcedVariation()
11171105

11181106
EventBuilderMock.Verify(b => b.CreateImpressionEvent(It.IsAny<ProjectConfig>(), Config.GetExperimentFromKey("group_experiment_1"),
11191107
"7722360022", "user_1", null), Times.Once);
1120-
1121-
LoggerMock.Verify(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()), Times.Exactly(9));
1108+
11221109
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, string.Format(@"Set variation ""{0}"" for experiment ""{1}"" and user ""{2}"" in the forced variation map.", variationId, experimentId, userId)), Times.Once);
11231110
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "User \"user_1\" is not in the forced variation map."), Times.Once);
11241111
LoggerMock.Verify(l => l.Log(LogLevel.DEBUG, "Assigned bucket [1922] to user [user_1] with bucketing ID [user_1]."), Times.Once);

0 commit comments

Comments
 (0)