Skip to content

Commit c4c5455

Browse files
feat: support tracking
1 parent 25ad7d1 commit c4c5455

File tree

4 files changed

+126
-3
lines changed

4 files changed

+126
-3
lines changed

build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,14 @@ nexusPublishing {
107107
dependencies {
108108
implementation group: 'com.launchdarkly', name: 'launchdarkly-java-server-sdk', version: '[7.1.0, 8.0.0)'
109109

110-
implementation 'dev.openfeature:sdk:[1.7.0,2.0.0)'
110+
implementation 'dev.openfeature:sdk:[1.14.0,2.0.0)'
111111

112112
// Use JUnit test framework
113113
testImplementation(platform('org.junit:junit-bom:5.10.0'))
114114
testImplementation('org.junit.jupiter:junit-jupiter')
115115
testImplementation "org.mockito:mockito-core:3.+"
116+
117+
testImplementation 'org.awaitility:awaitility:4.2.0'
116118
}
117119

118120
test {

src/main/java/com/launchdarkly/openfeature/serverprovider/Provider.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,34 @@ public void shutdown() {
222222
}
223223
}
224224

225+
@Override
226+
public void track(String eventName, EvaluationContext ctx, TrackingEventDetails details) {
227+
if(ctx == null) {
228+
logger.info("The 'track' method was called with a null EvaluationContext. No 'track' event will be sent to LaunchDarkly. The LaunchDarkly SDK requires a non-null EvaluationContext.");
229+
return;
230+
}
231+
232+
if(details != null) {
233+
Double metricValue = null;
234+
if (details.getValue().isPresent()) {
235+
metricValue = (Double)details.getValue().get();
236+
}
237+
// Convert the Structure portion of the TrackingEventDetails into a key value map.
238+
// This will not put the metricValue extracted above into the map.
239+
LDValue data = valueConverter.toLdValue(new Value(details));
240+
241+
if (metricValue != null) {
242+
client.trackMetric(eventName, evaluationContextConverter.toLdContext(ctx), data, metricValue);
243+
} else if (!data.isNull() && data.size() > 0) {
244+
client.trackData(eventName, evaluationContextConverter.toLdContext(ctx), data);
245+
} else {
246+
client.track(eventName, evaluationContextConverter.toLdContext(ctx));
247+
}
248+
} else {
249+
client.track(eventName, evaluationContextConverter.toLdContext(ctx));
250+
}
251+
}
252+
225253
/**
226254
* Get the LaunchDarkly client associated with this provider.
227255
* <p>

src/main/java/com/launchdarkly/openfeature/serverprovider/Version.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ abstract class Version {
44
private Version() {}
55

66
// This constant is updated automatically by our Gradle script during a release, if the project version has changed
7-
static final String SDK_VERSION = "0.2.0";
7+
static final String SDK_VERSION = "1.0.1";
88
}

src/test/java/com/launchdarkly/openfeature/serverprovider/ProviderTest.java

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import org.junit.jupiter.api.Test;
1010

1111
import static org.mockito.Mockito.*;
12+
13+
import org.awaitility.Awaitility;
14+
1215
import static org.junit.jupiter.api.Assertions.*;
1316

1417
public class ProviderTest {
@@ -35,6 +38,11 @@ public void itCanDoABooleanEvaluation() {
3538

3639
OpenFeatureAPI.getInstance().setProvider(ldProvider);
3740

41+
Awaitility.await().forever().until(() -> OpenFeatureAPI
42+
.getInstance()
43+
.getClient()
44+
.getBooleanValue("the-key", false, evaluationContext));
45+
3846
assertTrue(OpenFeatureAPI
3947
.getInstance()
4048
.getClient()
@@ -60,6 +68,11 @@ public void itCanDoAStringEvaluation() {
6068

6169
OpenFeatureAPI.getInstance().setProvider(ldProvider);
6270

71+
Awaitility.await().forever().until(() -> OpenFeatureAPI
72+
.getInstance()
73+
.getClient()
74+
.getStringValue("the-key", "default", evaluationContext).equals("evaluated"));
75+
6376
assertEquals("evaluated", OpenFeatureAPI
6477
.getInstance()
6578
.getClient()
@@ -83,6 +96,12 @@ public void itCanDoADoubleEvaluation() {
8396
.thenReturn(EvaluationDetail.fromValue(1.0, 42, EvaluationReason.targetMatch()));
8497

8598
OpenFeatureAPI.getInstance().setProvider(ldProvider);
99+
100+
Awaitility.await().forever().until(() -> OpenFeatureAPI
101+
.getInstance()
102+
.getClient()
103+
.getDoubleValue("the-key", 0.0, evaluationContext) != 0.0);
104+
86105
assertEquals(1.0, OpenFeatureAPI
87106
.getInstance()
88107
.getClient()
@@ -122,8 +141,82 @@ public void itCanDoAValueEvaluation() {
122141
.getObjectDetails("the-key", new Value(), evaluationContext);
123142

124143
assertEquals("aValue", detailed.getValue().asStructure().getValue("aKey").asString());
125-
126144
assertEquals("84", detailed.getVariant());
127145
assertEquals("TARGETING_MATCH", detailed.getReason());
128146
}
147+
148+
@Test
149+
public void itCanTrackNoTrackingEventDetails() {
150+
EvaluationContext evaluationContext = new ImmutableContext("user-key");
151+
EvaluationContextConverter evaluationContextConverter = new EvaluationContextConverter(null);
152+
153+
OpenFeatureAPI.getInstance().setProvider(ldProvider);
154+
155+
OpenFeatureAPI
156+
.getInstance()
157+
.getClient().track("metric-key", evaluationContext);
158+
159+
verify(mockedLdClient).track(
160+
"metric-key",
161+
evaluationContextConverter.toLdContext(evaluationContext));
162+
}
163+
164+
@Test
165+
public void itCanTrackEmptyTrackingEventDetails() {
166+
EvaluationContext evaluationContext = new ImmutableContext("user-key");
167+
EvaluationContextConverter evaluationContextConverter = new EvaluationContextConverter(null);
168+
169+
TrackingEventDetails trackingEventDetails = new MutableTrackingEventDetails(null);
170+
171+
OpenFeatureAPI.getInstance().setProvider(ldProvider);
172+
173+
OpenFeatureAPI
174+
.getInstance()
175+
.getClient().track("metric-key", evaluationContext, trackingEventDetails);
176+
177+
verify(mockedLdClient).track(
178+
"metric-key",
179+
evaluationContextConverter.toLdContext(evaluationContext));
180+
}
181+
182+
@Test
183+
public void itCanTrackTrackingEventDetailsWithNoValue() {
184+
EvaluationContext evaluationContext = new ImmutableContext("user-key");
185+
EvaluationContextConverter evaluationContextConverter = new EvaluationContextConverter(null);
186+
ValueConverter valueConverter = new ValueConverter(null);
187+
188+
TrackingEventDetails trackingEventDetails = new MutableTrackingEventDetails(null).add("currency", "USD");
189+
190+
OpenFeatureAPI.getInstance().setProvider(ldProvider);
191+
192+
OpenFeatureAPI
193+
.getInstance()
194+
.getClient().track("metric-key", evaluationContext, trackingEventDetails);
195+
196+
verify(mockedLdClient).trackData(
197+
"metric-key",
198+
evaluationContextConverter.toLdContext(evaluationContext),
199+
valueConverter.toLdValue(new Value(trackingEventDetails)));
200+
}
201+
202+
@Test
203+
public void itCanTrackFullTrackingEventDetails() {
204+
EvaluationContext evaluationContext = new ImmutableContext("user-key");
205+
EvaluationContextConverter evaluationContextConverter = new EvaluationContextConverter(null);
206+
ValueConverter valueConverter = new ValueConverter(null);
207+
208+
TrackingEventDetails trackingEventDetails = new MutableTrackingEventDetails(99.77).add("currency", "USD");
209+
210+
OpenFeatureAPI.getInstance().setProvider(ldProvider);
211+
212+
OpenFeatureAPI
213+
.getInstance()
214+
.getClient().track("metric-key", evaluationContext, trackingEventDetails);
215+
216+
verify(mockedLdClient).trackMetric(
217+
"metric-key",
218+
evaluationContextConverter.toLdContext(evaluationContext),
219+
valueConverter.toLdValue(new Value(trackingEventDetails)),
220+
99.77);
221+
}
129222
}

0 commit comments

Comments
 (0)