From 5ea55ec99151321af4458c8450667e4b2139cabe Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Wed, 12 Feb 2025 13:36:38 -0500 Subject: [PATCH 1/4] feat: update sdk to support sdkPlatform metadata, update WASM lib, update OpenFeature --- build.gradle | 4 +- .../server/common/api/IDevCycleClient.java | 4 + .../sdk/server/common/model/DevCycleUser.java | 6 +- .../sdk/server/common/model/PlatformData.java | 13 +- .../server/local/api/DevCycleLocalClient.java | 16 +- .../server/openfeature/DevCycleProvider.java | 182 ++++++++++++------ src/main/resources/bucketing-lib.release.wasm | Bin 214842 -> 215020 bytes .../server/common/model/DevCycleUserTest.java | 2 + .../server/helpers/MockDevCycleClient.java | 5 + .../server/local/DevCycleLocalClientTest.java | 18 +- .../DevCycleProviderLocalSDKTest.java | 10 + 11 files changed, 190 insertions(+), 70 deletions(-) diff --git a/build.gradle b/build.gradle index 424ee0e1..7dfca6fd 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,7 @@ sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 def wasmResourcePath = "$projectDir/src/main/resources" -def wasmVersion = "1.25.3" +def wasmVersion = "1.31.2" def wasmUrl = "https://unpkg.com/@devcycle/bucketing-assembly-script@$wasmVersion/build/bucketing-lib.release.wasm" task downloadDVCBucketingWASM(type: Download) { src wasmUrl @@ -113,7 +113,7 @@ ext { junit_version = "4.13.2" mockito_core_version = "5.6.0" protobuf_version = "3.24.4" - openfeature_version = "1.7.0" + openfeature_version = "1.14.0" eventsource_version = "4.1.1" } diff --git a/src/main/java/com/devcycle/sdk/server/common/api/IDevCycleClient.java b/src/main/java/com/devcycle/sdk/server/common/api/IDevCycleClient.java index 9ccc241c..14955fbb 100644 --- a/src/main/java/com/devcycle/sdk/server/common/api/IDevCycleClient.java +++ b/src/main/java/com/devcycle/sdk/server/common/api/IDevCycleClient.java @@ -1,5 +1,7 @@ package com.devcycle.sdk.server.common.api; +import com.devcycle.sdk.server.common.exception.DevCycleException; +import com.devcycle.sdk.server.common.model.DevCycleEvent; import com.devcycle.sdk.server.common.model.DevCycleUser; import com.devcycle.sdk.server.common.model.Variable; import dev.openfeature.sdk.FeatureProvider; @@ -32,6 +34,8 @@ public interface IDevCycleClient { */ Variable variable(DevCycleUser user, String key, T defaultValue); + void track(DevCycleUser user, DevCycleEvent event) throws DevCycleException; + /** * Close the client and release any resources. */ diff --git a/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java b/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java index bfd200e4..0605bfd9 100755 --- a/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java +++ b/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java @@ -104,6 +104,10 @@ public class DevCycleUser { @JsonProperty("sdkVersion") private String sdkVersion = getPlatformData().getSdkVersion(); + @Schema(description = "DevCycle SDK Platform") + @JsonProperty("sdkPlatform") + private String sdkPlatform = null; + @Schema(description = "Hostname where the SDK is running") @Builder.Default @JsonProperty("hostname") @@ -155,7 +159,7 @@ public static DevCycleUser fromEvaluationContext(EvaluationContext ctx) { Map privateCustomData = new LinkedHashMap<>(); for (String key : ctx.keySet()) { - if (key.equals("user_id")) { + if (key.equals("user_id") || key.equals("targetingKey")) { continue; } diff --git a/src/main/java/com/devcycle/sdk/server/common/model/PlatformData.java b/src/main/java/com/devcycle/sdk/server/common/model/PlatformData.java index 7c3722b9..873cceb8 100644 --- a/src/main/java/com/devcycle/sdk/server/common/model/PlatformData.java +++ b/src/main/java/com/devcycle/sdk/server/common/model/PlatformData.java @@ -20,23 +20,31 @@ public class PlatformData { @Schema(description = "Platform the SDK is running on") @Builder.Default private String platform = "Java"; + @Schema(description = "Version of the platform the SDK is running on") @Builder.Default private String platformVersion = System.getProperty("java.version"); + @Schema(description = "DevCycle SDK type") @Builder.Default private PlatformData.SdkTypeEnum sdkType = PlatformData.SdkTypeEnum.SERVER; + @Schema(description = "DevCycle SDK Version") @Builder.Default private String sdkVersion = "2.5.0"; + + @Schema(description = "DevCycle SDK Platform") + private String sdkPlatform = null; + @Schema(description = "Hostname where the SDK is running") private String hostname; - public PlatformData(String platform, String platformVersion, SdkTypeEnum sdkType, String sdkVersion, String hostname) { + public PlatformData(String platform, String platformVersion, SdkTypeEnum sdkType, String sdkVersion, String sdkPlatform, String hostname) { this.platform = platform; this.platformVersion = platformVersion; this.sdkType = sdkType; this.sdkVersion = sdkVersion; + this.sdkPlatform = sdkPlatform; try { this.hostname = hostname != null ? hostname : InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { @@ -53,6 +61,9 @@ public String toString() { platformData.put("platformVersion", platformVersion); platformData.put("sdkType", sdkType.toString()); platformData.put("sdkVersion", sdkVersion); + if (sdkPlatform != null) { + platformData.put("sdkPlatform", sdkPlatform); + } platformData.put("hostname", hostname); String platformDataString = null; diff --git a/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java b/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java index 7900025b..35959be4 100755 --- a/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java +++ b/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java @@ -25,7 +25,6 @@ public final class DevCycleLocalClient implements IDevCycleClient { private final String sdkKey; - private final DevCycleProvider openFeatureProvider; private final LocalBucketing localBucketing = new LocalBucketing(); private final EnvironmentConfigManager configManager; private EventQueueManager eventQueueManager; @@ -61,7 +60,6 @@ public DevCycleLocalClient(String sdkKey, DevCycleLocalOptions dvcOptions) { } catch (Exception e) { DevCycleLogger.error("Error creating event queue due to error: " + e.getMessage()); } - this.openFeatureProvider = new DevCycleProvider(this); } /** @@ -249,12 +247,24 @@ public void close() { } } + + private static DevCycleProvider openFeatureProvider = null; + /** * @return the OpenFeature provider for this client. */ @Override public FeatureProvider getOpenFeatureProvider() { - return this.openFeatureProvider; + if (openFeatureProvider == null) { + synchronized (DevCycleLocalClient.class) { + if (openFeatureProvider == null) { + openFeatureProvider = new DevCycleProvider(this);; + } + PlatformData platformData = PlatformData.builder().sdkPlatform("java-of").build(); + localBucketing.setPlatformData(platformData.toString()); + } + } + return openFeatureProvider; } @Override diff --git a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java index 3590d7a7..eafc8f59 100644 --- a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java +++ b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java @@ -1,13 +1,18 @@ package com.devcycle.sdk.server.openfeature; import com.devcycle.sdk.server.common.api.IDevCycleClient; +import com.devcycle.sdk.server.common.exception.DevCycleException; +import com.devcycle.sdk.server.common.model.DevCycleEvent; import com.devcycle.sdk.server.common.model.DevCycleUser; import com.devcycle.sdk.server.common.model.Variable; import dev.openfeature.sdk.*; import dev.openfeature.sdk.exceptions.ProviderNotReadyError; +import dev.openfeature.sdk.exceptions.GeneralError; import dev.openfeature.sdk.exceptions.TypeMismatchError; +import java.math.BigDecimal; import java.util.Map; +import java.util.Optional; public class DevCycleProvider implements FeatureProvider { private static final String PROVIDER_NAME = "DevCycle"; @@ -23,6 +28,28 @@ public Metadata getMetadata() { return () -> PROVIDER_NAME + " " + devcycleClient.getSDKPlatform(); } + @Override + public void initialize(EvaluationContext evaluationContext) throws Exception { + if (devcycleClient.isInitialized()) { + return; + } + + long deadline = 2 * 1000; // Delay in milliseconds + long start = System.currentTimeMillis(); + + do { + if (deadline <= System.currentTimeMillis() - start) { + throw new GeneralError("DevCycle client not initialized within 2 seconds"); + } + Thread.sleep(5); + } while (!devcycleClient.isInitialized()); + } + + @Override + public void shutdown() { + devcycleClient.close(); + } + @Override public ProviderEvaluation getBooleanEvaluation(String key, Boolean defaultValue, EvaluationContext ctx) { return resolvePrimitiveVariable(key, defaultValue, ctx); @@ -62,83 +89,120 @@ public ProviderEvaluation getObjectEvaluation(String key, Value defaultVa } } - if (devcycleClient.isInitialized()) { - try { - DevCycleUser user = DevCycleUser.fromEvaluationContext(ctx); + if (!devcycleClient.isInitialized()) { + throw new ProviderNotReadyError("DevCycle client not initialized"); + } - Variable variable = devcycleClient.variable(user, key, defaultValue.asStructure().asObjectMap()); + try { + DevCycleUser user = DevCycleUser.fromEvaluationContext(ctx); - if (variable == null || variable.getIsDefaulted()) { + Variable variable = devcycleClient.variable(user, key, defaultValue.asStructure().asObjectMap()); + + if (variable == null || variable.getIsDefaulted()) { + return ProviderEvaluation.builder() + .value(defaultValue) + .reason(Reason.DEFAULT.toString()) + .build(); + } else { + if (variable.getValue() instanceof Map) { + // JSON objects are managed as Map implementations and must be converted to an OpenFeature structure + Value objectValue = new Value(Structure.mapToStructure((Map) variable.getValue())); return ProviderEvaluation.builder() - .value(defaultValue) - .reason(Reason.DEFAULT.toString()) + .value(objectValue) + .reason(Reason.TARGETING_MATCH.toString()) .build(); } else { - if (variable.getValue() instanceof Map) { - // JSON objects are managed as Map implementations and must be converted to an OpenFeature structure - Value objectValue = new Value(Structure.mapToStructure((Map) variable.getValue())); - return ProviderEvaluation.builder() - .value(objectValue) - .reason(Reason.TARGETING_MATCH.toString()) - .build(); - } else { - throw new TypeMismatchError("DevCycle variable for key " + key + " is not a JSON object"); - } + throw new TypeMismatchError("DevCycle variable for key " + key + " is not a JSON object"); } - } catch (IllegalArgumentException e) { - return ProviderEvaluation.builder() - .value(defaultValue) - .reason(Reason.ERROR.toString()) - .errorCode(ErrorCode.GENERAL) - .errorMessage(e.getMessage()) - .build(); } - } else { - throw new ProviderNotReadyError("DevCycle client not initialized"); + } catch (IllegalArgumentException e) { + return ProviderEvaluation.builder() + .value(defaultValue) + .reason(Reason.ERROR.toString()) + .errorCode(ErrorCode.GENERAL) + .errorMessage(e.getMessage()) + .build(); } } - @Override - public void shutdown() { - devcycleClient.close(); - } - ProviderEvaluation resolvePrimitiveVariable(String key, T defaultValue, EvaluationContext ctx) { - if (devcycleClient.isInitialized()) { - try { - DevCycleUser user = DevCycleUser.fromEvaluationContext(ctx); + if (!devcycleClient.isInitialized()) { + throw new ProviderNotReadyError("DevCycle client not initialized"); + } - Variable variable = devcycleClient.variable(user, key, defaultValue); + try { + DevCycleUser user = DevCycleUser.fromEvaluationContext(ctx); - if (variable == null || variable.getIsDefaulted()) { - return ProviderEvaluation.builder() - .value(defaultValue) - .reason(Reason.DEFAULT.toString()) - .build(); - } else { - T value = variable.getValue(); - if (variable.getType() == Variable.TypeEnum.NUMBER && defaultValue.getClass() == Integer.class) { - // Internally in the DevCycle SDK all number values are stored as Doubles - // need to explicitly convert to an Integer if the requested type is Integer - Number numVal = (Number) value; - value = (T) Integer.valueOf(numVal.intValue()); - } - - return ProviderEvaluation.builder() - .value(value) - .reason(Reason.TARGETING_MATCH.toString()) - .build(); - } - } catch (IllegalArgumentException e) { + Variable variable = devcycleClient.variable(user, key, defaultValue); + + if (variable == null || variable.getIsDefaulted()) { return ProviderEvaluation.builder() .value(defaultValue) - .reason(Reason.ERROR.toString()) - .errorCode(ErrorCode.GENERAL) - .errorMessage(e.getMessage()) + .reason(Reason.DEFAULT.toString()) + .build(); + } else { + T value = variable.getValue(); + if (variable.getType() == Variable.TypeEnum.NUMBER && defaultValue.getClass() == Integer.class) { + // Internally in the DevCycle SDK all number values are stored as Doubles + // need to explicitly convert to an Integer if the requested type is Integer + Number numVal = (Number) value; + value = (T) Integer.valueOf(numVal.intValue()); + } + + return ProviderEvaluation.builder() + .value(value) + .reason(Reason.TARGETING_MATCH.toString()) .build(); } - } else { + } catch (IllegalArgumentException e) { + return ProviderEvaluation.builder() + .value(defaultValue) + .reason(Reason.ERROR.toString()) + .errorCode(ErrorCode.GENERAL) + .errorMessage(e.getMessage()) + .build(); + } + } + + @Override + public void track(String eventName, EvaluationContext context, TrackingEventDetails details) { + if (!devcycleClient.isInitialized()) { throw new ProviderNotReadyError("DevCycle client not initialized"); } + + DevCycleUser user = DevCycleUser.fromEvaluationContext(context); + try { + // This casting is required because the TrackingEventDetails interface doesn't expose the getValue() + // call that returns the numeric value + Object rawValue = null; + if (details instanceof MutableTrackingEventDetails) { + rawValue = ((MutableTrackingEventDetails) details).getValue(); + } else if (details instanceof ImmutableTrackingEventDetails) { + rawValue = ((ImmutableTrackingEventDetails) details).getValue(); + } + + // Unwrap Optional if present + if (rawValue instanceof Optional) { + rawValue = ((Optional) rawValue).orElse(null); + } + Value value = rawValue != null ? Value.objectToValue(rawValue) : null; + + BigDecimal bigDecimalValue = null; + if (value != null && value.isNumber()) { + bigDecimalValue = new BigDecimal(Double.toString(value.asDouble())); + } + + Map metaData = details.asObjectMap(); + metaData.remove("value"); + + DevCycleEvent event = DevCycleEvent.builder() + .type(eventName) + .value(bigDecimalValue) + .metaData(metaData) + .build(); + devcycleClient.track(user, event); + } catch (DevCycleException e) { + throw new GeneralError(e); + } } } diff --git a/src/main/resources/bucketing-lib.release.wasm b/src/main/resources/bucketing-lib.release.wasm index 348b8bd01f30cc66445ede5f41c5021ed7e501c6..5eb145f5992cfbd5f1be3d6090136b3bd2037b86 100644 GIT binary patch delta 61081 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 Date: Wed, 12 Feb 2025 14:06:35 -0500 Subject: [PATCH 2/4] fix: update example apps, set sdkPlatform for OF context. Signed-off-by: Jonathan Norris --- .../com/devcycle/examples/LocalExample.java | 9 ++++--- .../devcycle/examples/OpenFeatureExample.java | 26 +++++++++++-------- .../sdk/server/common/model/DevCycleUser.java | 3 ++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/examples/java/com/devcycle/examples/LocalExample.java b/src/examples/java/com/devcycle/examples/LocalExample.java index ccb09532..2df9724c 100644 --- a/src/examples/java/com/devcycle/examples/LocalExample.java +++ b/src/examples/java/com/devcycle/examples/LocalExample.java @@ -1,6 +1,7 @@ package com.devcycle.examples; import com.devcycle.sdk.server.common.logging.SimpleDevCycleLogger; +import com.devcycle.sdk.server.common.model.DevCycleEvent; import com.devcycle.sdk.server.common.model.DevCycleUser; import com.devcycle.sdk.server.local.api.DevCycleLocalClient; import com.devcycle.sdk.server.local.model.DevCycleLocalOptions; @@ -24,9 +25,7 @@ public static void main(String[] args) throws InterruptedException { Boolean defaultValue = false; DevCycleLocalOptions options = DevCycleLocalOptions.builder() - .configPollingIntervalMS(60000) .customLogger(new SimpleDevCycleLogger(SimpleDevCycleLogger.Level.DEBUG)) - .enableBetaRealtimeUpdates(true) .build(); // Initialize DevCycle Client @@ -50,6 +49,10 @@ public static void main(String[] args) throws InterruptedException { } else { System.out.println("feature is NOT enabled"); } - Thread.sleep(10000); + + DevCycleEvent event = DevCycleEvent.builder().type("local-test").build(); + client.track(user, event); + + Thread.sleep(20000); } } diff --git a/src/examples/java/com/devcycle/examples/OpenFeatureExample.java b/src/examples/java/com/devcycle/examples/OpenFeatureExample.java index ceb23d0f..6e8652c0 100644 --- a/src/examples/java/com/devcycle/examples/OpenFeatureExample.java +++ b/src/examples/java/com/devcycle/examples/OpenFeatureExample.java @@ -1,5 +1,6 @@ package com.devcycle.examples; +import com.devcycle.sdk.server.common.logging.SimpleDevCycleLogger; import com.devcycle.sdk.server.local.api.DevCycleLocalClient; import com.devcycle.sdk.server.local.model.DevCycleLocalOptions; import dev.openfeature.sdk.*; @@ -15,22 +16,16 @@ public static void main(String[] args) throws InterruptedException { System.exit(1); } - DevCycleLocalOptions options = DevCycleLocalOptions.builder().configPollingIntervalMS(60000) - .disableAutomaticEventLogging(false).disableCustomEventLogging(false).build(); + DevCycleLocalOptions options = DevCycleLocalOptions.builder() + .customLogger(new SimpleDevCycleLogger(SimpleDevCycleLogger.Level.DEBUG)) + .build(); // Initialize DevCycle Client DevCycleLocalClient devCycleClient = new DevCycleLocalClient(server_sdk_key, options); - for (int i = 0; i < 10; i++) { - if (devCycleClient.isInitialized()) { - break; - } - Thread.sleep(500); - } - // Setup OpenFeature with the DevCycle Provider OpenFeatureAPI api = OpenFeatureAPI.getInstance(); - api.setProvider(devCycleClient.getOpenFeatureProvider()); + api.setProviderAndWait(devCycleClient.getOpenFeatureProvider()); Client openFeatureClient = api.getClient(); @@ -41,7 +36,7 @@ public static void main(String[] args) throws InterruptedException { context.add("language", "en"); context.add("country", "CA"); context.add("appVersion", "1.0.0"); - context.add("appBuild", "1"); + context.add("appBuild", 1.0); context.add("deviceModel", "Macbook"); // Add Devcycle Custom Data values @@ -81,5 +76,14 @@ public static void main(String[] args) throws InterruptedException { System.out.println("Value: " + details.getValue()); System.out.println("Reason: " + details.getReason()); + MutableTrackingEventDetails eventDetails = new MutableTrackingEventDetails(610.1); + eventDetails.add("test-string", "test-value"); + eventDetails.add("test-number", 123.456); + eventDetails.add("test-boolean", true); + eventDetails.add("test-json", new Value(Structure.mapToStructure(defaultJsonData))); + + openFeatureClient.track("test-of-event", context, eventDetails); + + Thread.sleep(20000); } } diff --git a/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java b/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java index 0605bfd9..955417a4 100755 --- a/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java +++ b/src/main/java/com/devcycle/sdk/server/common/model/DevCycleUser.java @@ -105,6 +105,7 @@ public class DevCycleUser { private String sdkVersion = getPlatformData().getSdkVersion(); @Schema(description = "DevCycle SDK Platform") + @Builder.Default @JsonProperty("sdkPlatform") private String sdkPlatform = null; @@ -153,7 +154,7 @@ public static DevCycleUser fromEvaluationContext(EvaluationContext ctx) { throw new TargetingKeyMissingError(); } - DevCycleUser user = DevCycleUser.builder().userId(userId).build(); + DevCycleUser user = DevCycleUser.builder().userId(userId).sdkPlatform("java-of").build(); Map customData = new LinkedHashMap<>(); Map privateCustomData = new LinkedHashMap<>(); From ead335908bc9314dc32834d74520307b0be5745c Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Wed, 12 Feb 2025 14:22:41 -0500 Subject: [PATCH 3/4] chore: cleanup --- .../com/devcycle/sdk/server/local/api/DevCycleLocalClient.java | 2 +- .../com/devcycle/sdk/server/common/model/DevCycleUserTest.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java b/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java index 35959be4..6de89d8d 100755 --- a/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java +++ b/src/main/java/com/devcycle/sdk/server/local/api/DevCycleLocalClient.java @@ -258,7 +258,7 @@ public FeatureProvider getOpenFeatureProvider() { if (openFeatureProvider == null) { synchronized (DevCycleLocalClient.class) { if (openFeatureProvider == null) { - openFeatureProvider = new DevCycleProvider(this);; + openFeatureProvider = new DevCycleProvider(this); } PlatformData platformData = PlatformData.builder().sdkPlatform("java-of").build(); localBucketing.setPlatformData(platformData.toString()); diff --git a/src/test/java/com/devcycle/sdk/server/common/model/DevCycleUserTest.java b/src/test/java/com/devcycle/sdk/server/common/model/DevCycleUserTest.java index 5c67c1b4..99a4d550 100644 --- a/src/test/java/com/devcycle/sdk/server/common/model/DevCycleUserTest.java +++ b/src/test/java/com/devcycle/sdk/server/common/model/DevCycleUserTest.java @@ -117,8 +117,6 @@ public void testCreateUserWithCustomData() { DevCycleUser user = DevCycleUser.fromEvaluationContext(ctx); Assert.assertEquals(user.getUserId(), "test-1234"); - System.out.println("Custom Data: " + user.getCustomData().toString()); - Assert.assertEquals(user.getCustomData().size(), 4); Assert.assertEquals(user.getCustomData().get("strValue"), "hello"); Assert.assertEquals(user.getCustomData().get("intValue"), 123.0); From 3ae111a8176843d8148c02d6bc533227b0565f3e Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Tue, 18 Feb 2025 11:48:10 -0500 Subject: [PATCH 4/4] feat: update OF version, cleanup event value code --- build.gradle | 2 +- .../server/openfeature/DevCycleProvider.java | 47 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 7dfca6fd..bb6e60d7 100644 --- a/build.gradle +++ b/build.gradle @@ -113,7 +113,7 @@ ext { junit_version = "4.13.2" mockito_core_version = "5.6.0" protobuf_version = "3.24.4" - openfeature_version = "1.14.0" + openfeature_version = "1.14.1" eventsource_version = "4.1.1" } diff --git a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java index eafc8f59..bae42ea0 100644 --- a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java +++ b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java @@ -172,32 +172,12 @@ public void track(String eventName, EvaluationContext context, TrackingEventDeta DevCycleUser user = DevCycleUser.fromEvaluationContext(context); try { - // This casting is required because the TrackingEventDetails interface doesn't expose the getValue() - // call that returns the numeric value - Object rawValue = null; - if (details instanceof MutableTrackingEventDetails) { - rawValue = ((MutableTrackingEventDetails) details).getValue(); - } else if (details instanceof ImmutableTrackingEventDetails) { - rawValue = ((ImmutableTrackingEventDetails) details).getValue(); - } - - // Unwrap Optional if present - if (rawValue instanceof Optional) { - rawValue = ((Optional) rawValue).orElse(null); - } - Value value = rawValue != null ? Value.objectToValue(rawValue) : null; - - BigDecimal bigDecimalValue = null; - if (value != null && value.isNumber()) { - bigDecimalValue = new BigDecimal(Double.toString(value.asDouble())); - } - - Map metaData = details.asObjectMap(); - metaData.remove("value"); + BigDecimal eventValue = extractEventValue(details); + Map metaData = getMetadataWithoutValue(details); DevCycleEvent event = DevCycleEvent.builder() .type(eventName) - .value(bigDecimalValue) + .value(eventValue) .metaData(metaData) .build(); devcycleClient.track(user, event); @@ -205,4 +185,25 @@ public void track(String eventName, EvaluationContext context, TrackingEventDeta throw new GeneralError(e); } } + + private BigDecimal extractEventValue(TrackingEventDetails details) { + Optional rawValue = details.getValue(); + if (rawValue.isEmpty()) { + return null; + } + + Number numberValue = rawValue.get(); + if (numberValue == null) { + return null; + } + + Value value = Value.objectToValue(numberValue); + return value.isNumber() ? new BigDecimal(Double.toString(value.asDouble())) : null; + } + + private Map getMetadataWithoutValue(TrackingEventDetails details) { + Map metaData = details.asObjectMap(); + metaData.remove("value"); + return metaData; + } }