Skip to content

Commit

Permalink
The Simple Logging Facade for Java was added (#62)
Browse files Browse the repository at this point in the history
Co-authored-by: Bohdan Akimenko <bohdan.akimenko@kevychsolutions.com>
  • Loading branch information
vazarkevych and Bohdan-Kim committed Jun 7, 2024
1 parent 6481547 commit f773be4
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 75 deletions.
9 changes: 9 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ dependencies {
// https://mvnrepository.com/artifact/org.projectlombok/lombok
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'

// logging
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation 'com.github.tony19:logback-android:3.0.0'
testImplementation 'ch.qos.logback:logback-classic:1.2.11'
}

publishing {
Expand Down Expand Up @@ -102,3 +107,7 @@ jacocoTestReport {
html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
}
}

configurations.testImplementation {
exclude module: 'logback-android'
}
6 changes: 4 additions & 2 deletions lib/src/main/java/growthbook/sdk/java/ConditionEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import java.lang.reflect.Type;
import java.util.ArrayList;
Expand All @@ -18,6 +19,7 @@
/**
* <b>INTERNAL</b>: Implementation of condition evaluation
*/
@Slf4j
class ConditionEvaluator implements IConditionEvaluator {

private final GrowthBookJsonUtils jsonUtils = GrowthBookJsonUtils.getInstance();
Expand Down Expand Up @@ -69,7 +71,7 @@ public Boolean evaluateCondition(String attributesJsonString, String conditionJs

return true;
} catch (RuntimeException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return false;
}
}
Expand Down Expand Up @@ -467,7 +469,7 @@ Boolean arePrimitivesEqual(JsonPrimitive a, JsonPrimitive b, DataType dataType)
//
}

System.out.printf("\nUnsupported data type %s", dataType);
log.info("\nUnsupported data type {}", dataType);

return false;
}
Expand Down
7 changes: 6 additions & 1 deletion lib/src/main/java/growthbook/sdk/java/DecryptionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import lombok.extern.slf4j.Slf4j;

/**
* INTERNAL: This class is used internally to decrypt an encrypted features response
*/
@Slf4j
class DecryptionUtils {

public static class DecryptionException extends Exception {
Expand All @@ -28,6 +30,7 @@ public DecryptionException(String errorMessage) {

public static String decrypt(String payload, String encryptionKey) throws DecryptionException {
if (!payload.contains(".")) {
log.error("DecryptionException: Invalid payload");
throw new DecryptionException("Invalid payload");
}

Expand All @@ -54,8 +57,10 @@ public static String decrypt(String payload, String encryptionKey) throws Decryp

return new String(plainText);
} catch (InvalidAlgorithmParameterException e) {
log.error("DecryptionException: Invalid payload", e);
throw new DecryptionException("Invalid payload");
} catch (InvalidKeyException e) {
log.error("DecryptionException: Invalid encryption key", e);
throw new DecryptionException("Invalid encryption key");
} catch (
NoSuchAlgorithmException
Expand All @@ -65,7 +70,7 @@ public static String decrypt(String payload, String encryptionKey) throws Decryp
| IllegalArgumentException
| BadPaddingException e
) {
e.printStackTrace();
log.error(e.getMessage(), e);
throw new DecryptionException(e.getMessage());
}
}
Expand Down
11 changes: 8 additions & 3 deletions lib/src/main/java/growthbook/sdk/java/ExperimentEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import javax.annotation.Nullable;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;

/**
* <b>INTERNAL</b>: Implementation of experiment evaluation
*/
@Slf4j
class ExperimentEvaluator implements IExperimentEvaluator {

private final ConditionEvaluator conditionEvaluator = new ConditionEvaluator();
Expand Down Expand Up @@ -111,6 +113,7 @@ public <ValueType> ExperimentResult<ValueType> evaluateExperiment(Experiment<Val
if (!foundStickyBucket) {

List<Filter> filters = experiment.getFilters();
@Deprecated
Namespace namespace = experiment.getNamespace();

if (filters != null) {
Expand Down Expand Up @@ -156,8 +159,10 @@ public <ValueType> ExperimentResult<ValueType> evaluateExperiment(Experiment<Val
)
);

if (parentResult.source.equals(FeatureResultSource.CYCLIC_PREREQUISITE)) {
return getExperimentResult(context, experiment, -1, false, featureId, null, null, attributeOverrides);
if (parentResult.getSource() != null) {
if (parentResult.getSource().equals(FeatureResultSource.CYCLIC_PREREQUISITE)) {
return getExperimentResult(context, experiment, -1, false, featureId, null, null, attributeOverrides);
}
}

Map<String, Object> evalObj = new HashMap<>();
Expand All @@ -173,7 +178,7 @@ public <ValueType> ExperimentResult<ValueType> evaluateExperiment(Experiment<Val

// blocking prerequisite eval failed: feature evaluation fails
if (!evalCondition) {
System.out.println("Feature blocked by prerequisite");
log.info("Feature blocked by prerequisite");
return getExperimentResult(context, experiment, -1, false, featureId, null, null, attributeOverrides);
}
}
Expand Down
44 changes: 21 additions & 23 deletions lib/src/main/java/growthbook/sdk/java/FeatureEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import java.net.MalformedURLException;
import java.net.URL;
Expand All @@ -13,13 +14,12 @@

/**
* <b>INTERNAL</b>: Implementation of feature evaluation
*/

/**
* <p>
* Feature Evaluator Class
* Takes Context and Feature Key
* Returns Calculated Feature Result against that key
*/
@Slf4j
class FeatureEvaluator implements IFeatureEvaluator {

private final GrowthBookJsonUtils jsonUtils = GrowthBookJsonUtils.getInstance();
Expand Down Expand Up @@ -49,7 +49,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(

try {
// block that handle recursion
// System.out.println("evaluateFeature: circular dependency detected:");
log.info("evaluateFeature: circular dependency detected:");
if (featureEvalContext.getEvaluatedFeatures().contains(key)) {
FeatureResult<ValueType> featureResultWhenCircularDependencyDetected = FeatureResult
.<ValueType>builder()
Expand Down Expand Up @@ -102,7 +102,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
.build();

if (featureJson == null) {
System.out.println("featureJson is null");
log.info("featureJson is null");

// When key exists but there is no value, should be default value with null value
if (featureUsageCallback != null) {
Expand Down Expand Up @@ -143,7 +143,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
if (attributes == null) {
attributes = new JsonObject();
}
// System.out.printf("\n\nAttributes = %s", attributes);
log.info("\n\nAttributes = {}", attributes);

// Loop through the feature rules (if any)

Expand All @@ -158,18 +158,20 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
attributeOverrides);

// break out for cyclic prerequisites
if (parentResult.getSource().equals(FeatureResultSource.CYCLIC_PREREQUISITE)) {
FeatureResult<ValueType> featureResultWhenCircularDependencyDetected =
FeatureResult
.<ValueType>builder()
.value(null)
.source(FeatureResultSource.CYCLIC_PREREQUISITE)
.build();
if (parentResult.getSource() != null) {
if (parentResult.getSource().equals(FeatureResultSource.CYCLIC_PREREQUISITE)) {
FeatureResult<ValueType> featureResultWhenCircularDependencyDetected =
FeatureResult
.<ValueType>builder()
.value(null)
.source(FeatureResultSource.CYCLIC_PREREQUISITE)
.build();

if (featureUsageCallback != null) {
featureUsageCallback.onFeatureUsage(key, featureResultWhenCircularDependencyDetected);
if (featureUsageCallback != null) {
featureUsageCallback.onFeatureUsage(key, featureResultWhenCircularDependencyDetected);
}
return featureResultWhenCircularDependencyDetected;
}
return featureResultWhenCircularDependencyDetected;
}

Map<String, Object> evalObj = new HashMap<>();
Expand All @@ -187,7 +189,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
if (!evalCondition) {
// blocking prerequisite eval failed: feature evaluation fails
if (parentCondition.getGate()) {
System.out.println("Feature blocked by prerequisite");
log.info("Feature blocked by prerequisite");

FeatureResult<ValueType> featureResultWhenBlockedByPrerequisite =
FeatureResult
Expand All @@ -203,8 +205,6 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
}
// non-blocking prerequisite eval failed: break out
// of parentConditions loop, jump to the next rule

continue;
}
}
}
Expand Down Expand Up @@ -358,8 +358,6 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
}
return experimentFeatureResult;
}
} else {
continue;
}
}
}
Expand All @@ -381,7 +379,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(
// Return (value = defaultValue or null, source = defaultValue)
return defaultValueFeatureResult;
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);

// If the key doesn't exist in context.features, return immediately
// (value = null, source = unknownFeature).
Expand Down Expand Up @@ -417,7 +415,7 @@ public <ValueType> FeatureResult<ValueType> evaluateFeature(

return GrowthBookUtils.getForcedSerializableValueFromUrl(key, url, valueTypeClass, jsonUtils.gson);
} catch (MalformedURLException | ClassCastException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
* UNKNOWN:
* - there was an unknown error that occurred when attempting to make the request.
*/
@Getter
public class FeatureFetchException extends Exception {

/**
* Allows you to identify an error by its unique error code.
* Separate from the custom message.
*/
@Getter
private final FeatureFetchErrorCode errorCode;

/**
Expand Down
8 changes: 5 additions & 3 deletions lib/src/main/java/growthbook/sdk/java/GBContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
Expand All @@ -19,6 +20,7 @@
* Alternatively, you can use the class's constructor.
*/
@Data
@Slf4j
public class GBContext {

/**
Expand Down Expand Up @@ -63,7 +65,7 @@ public GBContext(
String decrypted = DecryptionUtils.decrypt(featuresJson, encryptionKey);
this.featuresJson = decrypted.trim();
} catch (DecryptionUtils.DecryptionException e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
} else if (featuresJson != null) {
// Use features
Expand Down Expand Up @@ -199,7 +201,7 @@ private static JsonObject transformFeatures(String featuresJsonString) {
try {
return GrowthBookJsonUtils.getInstance().gson.fromJson(featuresJsonString, JsonObject.class);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return null;
}
}
Expand All @@ -217,7 +219,7 @@ private static JsonObject transformAttributes(@Nullable String attributesJsonStr

return GrowthBookJsonUtils.getInstance().gson.fromJson(attributesJsonString, JsonObject.class);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return new JsonObject();
}
}
Expand Down
Loading

0 comments on commit f773be4

Please sign in to comment.