Skip to content

Commit ebd3329

Browse files
liran2000toddbaert
andauthored
feat(optimizely)!: Optimizely provider concepts updates (#1658)
Signed-off-by: liran2000 <liran2000@gmail.com> Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
1 parent 630d470 commit ebd3329

5 files changed

Lines changed: 364 additions & 54 deletions

File tree

providers/optimizely/README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@
1919

2020
## Concepts
2121

22-
* Boolean evaluation gets feature [enabled](https://docs.developers.optimizely.com/feature-experimentation/docs/create-feature-flags) value.
23-
* Object evaluation gets a structure representing the evaluated variant variables.
24-
* String/Integer/Double evaluations evaluation are not directly supported by Optimizely provider, use getObjectEvaluation instead.
22+
### Evaluation Context
23+
24+
The `targetingKey` is required and maps to the Optimizely user ID. Additional attributes are passed to Optimizely for audience targeting.
25+
26+
### Variable Key Selection
27+
28+
Optimizely flags can have multiple variables. By default, the provider looks for a variable named `"value"`. Specify a different variable using the `variableKey` attribute:
2529

2630
## Usage
2731
Optimizely OpenFeature Provider is based on [Optimizely Java SDK documentation](https://docs.developers.optimizely.com/feature-experimentation/docs/java-sdk).
@@ -57,3 +61,9 @@ provider.getOptimizely()...
5761
Unit test based on optimizely [Local Data File](https://docs.developers.optimizely.com/feature-experimentation/docs/initialize-sdk-java).
5862
See [OptimizelyProviderTest](./src/test/java/dev/openfeature/contrib/providers/optimizely/OptimizelyProviderTest.java)
5963
for more information.
64+
65+
## Release Notes
66+
67+
### 0.1.0
68+
69+
Concepts updated, evaluation acts accordingly.

providers/optimizely/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111
<groupId>dev.openfeature.contrib.providers</groupId>
1212
<artifactId>optimizely</artifactId>
13-
<version>0.0.1</version> <!--x-release-please-version -->
13+
<version>0.1.0</version> <!--x-release-please-version -->
1414

1515
<name>optimizely</name>
1616
<description>optimizely provider for Java</description>

providers/optimizely/src/main/java/dev/openfeature/contrib/providers/optimizely/OptimizelyProvider.java

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
import com.optimizely.ab.Optimizely;
44
import com.optimizely.ab.OptimizelyUserContext;
5-
import com.optimizely.ab.optimizelydecision.OptimizelyDecision;
65
import com.optimizely.ab.optimizelyjson.OptimizelyJSON;
76
import dev.openfeature.sdk.EvaluationContext;
87
import dev.openfeature.sdk.EventProvider;
98
import dev.openfeature.sdk.Metadata;
109
import dev.openfeature.sdk.ProviderEvaluation;
10+
import dev.openfeature.sdk.Reason;
1111
import dev.openfeature.sdk.Structure;
1212
import dev.openfeature.sdk.Value;
13-
import java.util.List;
1413
import java.util.Map;
1514
import lombok.Getter;
1615
import lombok.SneakyThrows;
@@ -69,68 +68,135 @@ public Metadata getMetadata() {
6968
@Override
7069
public ProviderEvaluation<Boolean> getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) {
7170
OptimizelyUserContext userContext = contextTransformer.transform(ctx);
72-
OptimizelyDecision decision = userContext.decide(key);
73-
String variationKey = decision.getVariationKey();
74-
String reasonsString = null;
75-
if (variationKey == null) {
76-
List<String> reasons = decision.getReasons();
77-
reasonsString = String.join(", ", reasons);
71+
72+
String variableKey = getVariableKey(ctx);
73+
Boolean enabled = optimizely.getFeatureVariableBoolean(
74+
key, variableKey, userContext.getUserId(), userContext.getAttributes());
75+
76+
String variant = variableKey;
77+
String reason = Reason.TARGETING_MATCH.name();
78+
if (enabled == null) {
79+
enabled = false;
80+
variant = null;
81+
reason = Reason.DEFAULT.name();
7882
}
7983

80-
boolean enabled = decision.getEnabled();
8184
return ProviderEvaluation.<Boolean>builder()
8285
.value(enabled)
83-
.reason(reasonsString)
86+
.reason(reason)
87+
.variant(variant)
8488
.build();
8589
}
8690

91+
private static String getVariableKey(EvaluationContext ctx) {
92+
String variableKey = "value";
93+
Value varKey = ctx.getValue("variableKey");
94+
if (varKey != null && varKey.isString() && !varKey.asString().isBlank()) {
95+
variableKey = varKey.asString();
96+
}
97+
return variableKey;
98+
}
99+
87100
@SneakyThrows
88101
@Override
89102
public ProviderEvaluation<String> getStringEvaluation(String key, String defaultValue, EvaluationContext ctx) {
90-
throw new UnsupportedOperationException("String evaluation is not directly supported by Optimizely provider,"
91-
+ "use getObjectEvaluation instead.");
103+
OptimizelyUserContext userContext = contextTransformer.transform(ctx);
104+
105+
String variableKey = getVariableKey(ctx);
106+
String value = optimizely.getFeatureVariableString(
107+
key, variableKey, userContext.getUserId(), userContext.getAttributes());
108+
109+
String variant = variableKey;
110+
String reason = Reason.TARGETING_MATCH.name();
111+
if (value == null) {
112+
value = defaultValue;
113+
variant = null;
114+
reason = Reason.DEFAULT.name();
115+
}
116+
117+
return ProviderEvaluation.<String>builder()
118+
.value(value)
119+
.reason(reason)
120+
.variant(variant)
121+
.build();
92122
}
93123

94124
@Override
95125
public ProviderEvaluation<Integer> getIntegerEvaluation(String key, Integer defaultValue, EvaluationContext ctx) {
96-
throw new UnsupportedOperationException("Integer evaluation is not directly supported by Optimizely provider,"
97-
+ "use getObjectEvaluation instead.");
126+
OptimizelyUserContext userContext = contextTransformer.transform(ctx);
127+
128+
String variableKey = getVariableKey(ctx);
129+
Integer value = optimizely.getFeatureVariableInteger(
130+
key, variableKey, userContext.getUserId(), userContext.getAttributes());
131+
132+
String variant = variableKey;
133+
String reason = Reason.TARGETING_MATCH.name();
134+
if (value == null) {
135+
value = defaultValue;
136+
variant = null;
137+
reason = Reason.DEFAULT.name();
138+
}
139+
140+
return ProviderEvaluation.<Integer>builder()
141+
.value(value)
142+
.reason(reason)
143+
.variant(variant)
144+
.build();
98145
}
99146

100147
@Override
101148
public ProviderEvaluation<Double> getDoubleEvaluation(String key, Double defaultValue, EvaluationContext ctx) {
102-
throw new UnsupportedOperationException("Double evaluation is not directly supported by Optimizely provider,"
103-
+ "use getObjectEvaluation instead.");
149+
OptimizelyUserContext userContext = contextTransformer.transform(ctx);
150+
151+
String variableKey = getVariableKey(ctx);
152+
Double value = optimizely.getFeatureVariableDouble(
153+
key, variableKey, userContext.getUserId(), userContext.getAttributes());
154+
155+
String variant = variableKey;
156+
String reason = Reason.TARGETING_MATCH.name();
157+
if (value == null) {
158+
value = defaultValue;
159+
variant = null;
160+
reason = Reason.DEFAULT.name();
161+
}
162+
163+
return ProviderEvaluation.<Double>builder()
164+
.value(value)
165+
.reason(reason)
166+
.variant(variant)
167+
.build();
104168
}
105169

106170
@SneakyThrows
107171
@Override
108172
public ProviderEvaluation<Value> getObjectEvaluation(String key, Value defaultValue, EvaluationContext ctx) {
109173
OptimizelyUserContext userContext = contextTransformer.transform(ctx);
110-
OptimizelyDecision decision = userContext.decide(key);
111-
String variationKey = decision.getVariationKey();
112-
String reasonsString = null;
113-
if (variationKey == null) {
114-
List<String> reasons = decision.getReasons();
115-
reasonsString = String.join(", ", reasons);
116-
}
117174

118-
Value evaluatedValue = defaultValue;
119-
boolean enabled = decision.getEnabled();
120-
if (enabled) {
121-
OptimizelyJSON variables = decision.getVariables();
122-
evaluatedValue = toValue(variables);
175+
String variableKey = getVariableKey(ctx);
176+
OptimizelyJSON value = optimizely.getFeatureVariableJSON(
177+
key, variableKey, userContext.getUserId(), userContext.getAttributes());
178+
Value evaluatedValue = toValue(value);
179+
180+
String variant = variableKey;
181+
String reason = Reason.TARGETING_MATCH.name();
182+
if (value == null) {
183+
evaluatedValue = defaultValue;
184+
variant = null;
185+
reason = Reason.DEFAULT.name();
123186
}
124187

125188
return ProviderEvaluation.<Value>builder()
126189
.value(evaluatedValue)
127-
.reason(reasonsString)
128-
.variant(variationKey)
190+
.reason(reason)
191+
.variant(variant)
129192
.build();
130193
}
131194

132195
@SneakyThrows
133196
private Value toValue(OptimizelyJSON optimizelyJson) {
197+
if (optimizelyJson == null) {
198+
return new Value();
199+
}
134200
Map<String, Object> map = optimizelyJson.toMap();
135201
Structure structure = Structure.mapToStructure(map);
136202
return new Value(structure);

0 commit comments

Comments
 (0)