From c9a2e25ce3cd039891553db88262e78345db0708 Mon Sep 17 00:00:00 2001 From: Andrew Bell <115623869+andybharness@users.noreply.github.com> Date: Mon, 14 Aug 2023 16:42:31 +0100 Subject: [PATCH 1/2] [FFM-8148] - Standardise SDK error codes What Adding standardised SDK error codes + pushing some logs down to debug to reduce noise Why Each SDK uses different log messages for its lifecycle. We want to standardise messages across SDKs with a unique code. Testing Manual testing + unit testing --- examples/pom.xml | 4 +- pom.xml | 2 +- .../io/harness/cf/client/api/AuthService.java | 2 + .../io/harness/cf/client/api/Evaluator.java | 31 ++++- .../io/harness/cf/client/api/InnerClient.java | 24 ++-- .../cf/client/api/MetricsProcessor.java | 8 +- .../cf/client/api/PollingProcessor.java | 5 +- .../io/harness/cf/client/common/SdkCodes.java | 128 ++++++++++++++++++ .../cf/client/connector/EventSource.java | 6 +- .../cf/client/connector/HarnessConnector.java | 2 + .../cf/client/connector/LocalConnector.java | 2 +- .../harness/cf/client/connector/Updater.java | 4 +- .../cf/client/connector/CountingUpdater.java | 11 +- .../cf/client/connector/EventSourceTest.java | 1 - 14 files changed, 188 insertions(+), 42 deletions(-) create mode 100644 src/main/java/io/harness/cf/client/common/SdkCodes.java diff --git a/examples/pom.xml b/examples/pom.xml index e4d6a182..cc1e0aef 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,7 +6,7 @@ io.harness.featureflags examples - 1.2.5 + 1.3.0-SNAPSHOT 8 @@ -33,7 +33,7 @@ io.harness ff-java-server-sdk - 1.2.5 + 1.3.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 78ef5447..17633ea2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.harness ff-java-server-sdk - 1.2.5 + 1.3.0-SNAPSHOT jar Harness Feature Flag Java Server SDK Harness Feature Flag Java Server SDK diff --git a/src/main/java/io/harness/cf/client/api/AuthService.java b/src/main/java/io/harness/cf/client/api/AuthService.java index 370d8258..0ac18893 100644 --- a/src/main/java/io/harness/cf/client/api/AuthService.java +++ b/src/main/java/io/harness/cf/client/api/AuthService.java @@ -1,6 +1,7 @@ package io.harness.cf.client.api; import com.google.common.util.concurrent.AbstractScheduledService; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.connector.Connector; import io.harness.cf.client.connector.ConnectorException; import java.util.concurrent.TimeUnit; @@ -29,6 +30,7 @@ public AuthService( protected void runOneIteration() { try { connector.authenticate(); + SdkCodes.infoSdkAuthOk(); callback.onAuthSuccess(); stopAsync(); log.info("Stopping Auth service"); diff --git a/src/main/java/io/harness/cf/client/api/Evaluator.java b/src/main/java/io/harness/cf/client/api/Evaluator.java index cdb94d59..6108a395 100644 --- a/src/main/java/io/harness/cf/client/api/Evaluator.java +++ b/src/main/java/io/harness/cf/client/api/Evaluator.java @@ -6,6 +6,7 @@ import com.google.gson.JsonObject; import com.sangupta.murmur.Murmur3; import com.sangupta.murmur.MurmurConstants; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.common.StringUtils; import io.harness.cf.client.dto.Target; import io.harness.cf.model.*; @@ -411,29 +412,51 @@ public boolean boolVariation( String identifier, Target target, boolean defaultValue, FlagEvaluateCallback callback) { final Optional variation = evaluate(identifier, target, FeatureConfig.KindEnum.BOOLEAN, callback); - return variation.map(value -> Boolean.parseBoolean(value.getValue())).orElse(defaultValue); + + if (variation.isPresent()) { + return Boolean.parseBoolean(variation.get().getValue()); + } + + SdkCodes.warnDefaultVariationServed(identifier, target, String.valueOf(defaultValue)); + return defaultValue; } public String stringVariation( String identifier, Target target, String defaultValue, FlagEvaluateCallback callback) { final Optional variation = evaluate(identifier, target, FeatureConfig.KindEnum.STRING, callback); - return variation.map(Variation::getValue).orElse(defaultValue); + + if (variation.isPresent()) { + return variation.get().getValue(); + } + + SdkCodes.warnDefaultVariationServed(identifier, target, defaultValue); + return defaultValue; } public double numberVariation( String identifier, Target target, double defaultValue, FlagEvaluateCallback callback) { final Optional variation = evaluate(identifier, target, FeatureConfig.KindEnum.INT, callback); - return variation.map(value -> Double.parseDouble(value.getValue())).orElse(defaultValue); + + if (variation.isPresent()) { + return Double.parseDouble(variation.get().getValue()); + } + + SdkCodes.warnDefaultVariationServed(identifier, target, String.valueOf(defaultValue)); + return defaultValue; } public JsonObject jsonVariation( String identifier, Target target, JsonObject defaultValue, FlagEvaluateCallback callback) { final Optional variation = evaluate(identifier, target, FeatureConfig.KindEnum.JSON, callback); - if (variation.isPresent()) + + if (variation.isPresent()) { return new Gson().fromJson(variation.get().getValue(), JsonObject.class); + } + + SdkCodes.warnDefaultVariationServed(identifier, target, defaultValue.toString()); return defaultValue; } } diff --git a/src/main/java/io/harness/cf/client/api/InnerClient.java b/src/main/java/io/harness/cf/client/api/InnerClient.java index ac1db566..cb27b3ef 100644 --- a/src/main/java/io/harness/cf/client/api/InnerClient.java +++ b/src/main/java/io/harness/cf/client/api/InnerClient.java @@ -4,6 +4,7 @@ import com.google.common.util.concurrent.Service; import com.google.gson.JsonObject; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.connector.Connector; import io.harness.cf.client.connector.HarnessConfig; import io.harness.cf.client.connector.HarnessConnector; @@ -49,8 +50,6 @@ enum Processor { private boolean streamReady = false; private boolean metricReady = false; - private static final String MISSING_SDK_KEY = "SDK key cannot be empty!"; - private final ConcurrentHashMap>> events = new ConcurrentHashMap<>(); @@ -205,7 +204,8 @@ public synchronized void onMetricsFailure() { @Override public void onConnected() { - log.info("onConnected triggered"); + SdkCodes.infoStreamConnected(); + if (pollProcessor.state() == Service.State.RUNNING) { // refresh any flags that may have gotten out of sync if the SSE connection was down pollProcessor.retrieveAll(); @@ -214,7 +214,10 @@ public void onConnected() { } @Override - public void onDisconnected() { + public void onDisconnected(String reason) { + + SdkCodes.warnStreamDisconnected(reason); + if (!closing && pollProcessor.state() == Service.State.TERMINATED) { log.info("onDisconnected triggered, starting poller to get latest flags"); @@ -239,23 +242,16 @@ public void onReady() { initialize(Processor.STREAM); } - @Override - public void onError() { - log.info("onError triggered"); - // when error happens on updater (stream) - onDisconnected(); - } - @Override public synchronized void onFailure(@NonNull final String error) { - log.info("onFailure triggered [error={}] ", error); + SdkCodes.warnAuthFailedSrvDefaults(error); failure = true; notifyAll(); } @Override public void update(@NonNull final Message message) { - log.info("update triggered [event={}] ", message.getEvent()); + log.debug("update triggered [event={}] ", message.getEvent()); updateProcessor.update(message); } @@ -297,7 +293,7 @@ private synchronized void initialize(@NonNull final Processor processor) { initialized = true; notifyAll(); notifyConsumers(Event.READY, null); - log.info("Initialization is complete"); + SdkCodes.infoSdkInitOk(); } protected void notifyConsumers(@NonNull final Event event, final String value) { diff --git a/src/main/java/io/harness/cf/client/api/MetricsProcessor.java b/src/main/java/io/harness/cf/client/api/MetricsProcessor.java index ce9504c2..8d984f87 100644 --- a/src/main/java/io/harness/cf/client/api/MetricsProcessor.java +++ b/src/main/java/io/harness/cf/client/api/MetricsProcessor.java @@ -2,6 +2,7 @@ import com.google.common.util.concurrent.AbstractScheduledService; import com.google.common.util.concurrent.AtomicLongMap; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.common.StringUtils; import io.harness.cf.client.connector.Connector; import io.harness.cf.client.connector.ConnectorException; @@ -152,7 +153,7 @@ public void sendDataAndResetCache( } log.info("Successfully sent analytics data to the server"); } catch (ConnectorException e) { - log.error("Exception while posting metrics to the event server"); + SdkCodes.warnPostMetricsFailed(e.getMessage()); } } globalTargetSet.addAll(stagingTargetSet); @@ -268,13 +269,14 @@ protected Scheduler scheduler() { } public void start() { - log.info("Starting MetricsProcessor with request interval: {}", config.getFrequency()); + SdkCodes.infoMetricsThreadStarted(config.getFrequency()); startAsync(); } public void stop() { - log.info("Stopping MetricsProcessor"); + log.debug("Stopping MetricsProcessor"); stopAsync(); + SdkCodes.infoMetricsThreadExited(); } public void close() { diff --git a/src/main/java/io/harness/cf/client/api/PollingProcessor.java b/src/main/java/io/harness/cf/client/api/PollingProcessor.java index add24546..1a444ab4 100644 --- a/src/main/java/io/harness/cf/client/api/PollingProcessor.java +++ b/src/main/java/io/harness/cf/client/api/PollingProcessor.java @@ -3,6 +3,7 @@ import com.google.common.util.concurrent.AbstractScheduledService; import com.google.common.util.concurrent.MoreExecutors; import io.harness.cf.client.common.ScheduledServiceStateLogger; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.connector.Connector; import io.harness.cf.model.FeatureConfig; import io.harness.cf.model.Segment; @@ -111,7 +112,7 @@ public void start() { if (isRunning()) { return; } - log.info("Starting PollingProcessor with request interval: {}", pollIntervalSeconds); + SdkCodes.infoPollStarted(pollIntervalSeconds); startAsync(); } @@ -119,7 +120,7 @@ public void stop() { log.info("Stopping PollingProcessor"); if (isRunning()) { stopAsync(); - log.info("PollingProcessor stopped"); + SdkCodes.infoPollingStopped(); } } diff --git a/src/main/java/io/harness/cf/client/common/SdkCodes.java b/src/main/java/io/harness/cf/client/common/SdkCodes.java new file mode 100644 index 00000000..ef5d38a4 --- /dev/null +++ b/src/main/java/io/harness/cf/client/common/SdkCodes.java @@ -0,0 +1,128 @@ +package io.harness.cf.client.common; + +import static java.lang.String.valueOf; +import static java.util.Optional.*; + +import io.harness.cf.client.dto.Target; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SdkCodes { + + public static void errorMissingSdkKey() { + log.error(sdkErrMsg(1002)); + } + + public static void infoPollStarted(int durationSec) { + log.info(sdkErrMsg(4000, of(valueOf(durationSec * 1000)))); + } + + public static void infoSdkInitOk() { + log.info(sdkErrMsg(1000)); + } + + public static void infoSdkAuthOk() { + log.info(sdkErrMsg(2000)); + } + + public static void infoPollingStopped() { + log.info(sdkErrMsg(4001)); + } + + public static void infoStreamConnected() { + log.info(sdkErrMsg(5000)); + } + + public static void infoStreamEventReceived(String eventJson) { + log.info(sdkErrMsg(5002, of(eventJson))); + } + + public static void infoMetricsThreadStarted(int intervalSec) { + log.info(sdkErrMsg(7000, of(valueOf(intervalSec * 1000)))); + } + + public static void infoMetricsThreadExited() { + log.info(sdkErrMsg(7000)); + } + + public static void warnAuthFailedSrvDefaults(String reason) { + log.warn(sdkErrMsg(2001, Optional.of(reason))); + } + + public static void warnAuthRetying(int attempt) { + log.warn(sdkErrMsg(2003, Optional.of(", attempt " + attempt))); + } + + public static void warnStreamDisconnected(String reason) { + log.warn(sdkErrMsg(5001, Optional.of(reason))); + } + + public static void warnPostMetricsFailed(String reason) { + log.warn(sdkErrMsg(7002, Optional.of(reason))); + } + + public static void warnDefaultVariationServed(String identifier, Target target, String def) { + String targetId = (target == null) ? "null" : target.getIdentifier(); + String msg = String.format("identifier=%s, target=%s, default=%s", identifier, targetId, def); + log.warn(sdkErrMsg(6001, of(msg))); + } + + private static final Map MAP = + Arrays.stream( + new String[][] { + // SDK_INIT_1xxx + {"1000", "The SDK has successfully initialized"}, + { + "1001", + "The SDK has failed to initialize due to the following authentication error:" + }, + {"1002", "The SDK has failed to initialize due to a missing or empty API key"}, + // SDK_AUTH_2xxx + {"2000", "Authenticated ok"}, + { + "2001", + "Authentication failed with a non-recoverable error - defaults will be served" + }, + {"2003", "Retrying to authenticate"}, + // SDK_POLL_4xxx + {"4000", "Polling started, intervalMs:"}, + {"4001", "Polling stopped"}, + // SDK_STREAM_5xxx + {"5000", "SSE stream connected ok"}, + {"5001", "SSE stream disconnected, reason:"}, + {"5002", "SSE event received: "}, + {"5003", "SSE retrying to connect in"}, + // SDK_EVAL_6xxx + {"6000", "Evaluated variation successfully"}, + {"6001", "Default variation was served"}, + // SDK_METRICS_7xxx + {"7000", "Metrics thread started, intervalMs: "}, + {"7001", "Metrics thread exited"}, + {"7002", "Posting metrics failed, reason:"} + }) + .collect(Collectors.toMap(entry -> Integer.parseInt(entry[0]), entry -> entry[1])); + + private static String sdkErrMsg(int error_code) { + return sdkErrMsg(error_code, Optional.empty()); + } + + private static String sdkErrMsg(int error_code, Optional appendText) { + return String.format( + "SDKCODE(%s:%s): %s %s", + getErrClass(error_code), error_code, MAP.get(error_code), appendText.orElse("")); + } + + private static String getErrClass(int error_code) { + if (error_code >= 1000 && error_code <= 1999) return "init"; + else if (error_code >= 2000 && error_code <= 2999) return "auth"; + else if (error_code >= 4000 && error_code <= 4999) return "poll"; + else if (error_code >= 5000 && error_code <= 5999) return "stream"; + else if (error_code >= 6000 && error_code <= 6999) return "eval"; + else if (error_code >= 7000 && error_code <= 7999) return "metric"; + return ""; + } +} diff --git a/src/main/java/io/harness/cf/client/connector/EventSource.java b/src/main/java/io/harness/cf/client/connector/EventSource.java index dedd9ffc..6f6878ac 100644 --- a/src/main/java/io/harness/cf/client/connector/EventSource.java +++ b/src/main/java/io/harness/cf/client/connector/EventSource.java @@ -1,6 +1,7 @@ package io.harness.cf.client.connector; import com.google.gson.Gson; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.dto.Message; import io.harness.cf.client.logger.LogUtil; import java.io.IOException; @@ -240,7 +241,7 @@ public void close() { @Override // Callback public void onFailure(@NotNull Call call, @NotNull IOException e) { log.warn("SSE stream error", e); - updater.onDisconnected(); + updater.onDisconnected(e.getMessage()); } @Override // Callback @@ -266,6 +267,7 @@ public void onResponse(@NotNull Call call, @NotNull Response response) throws IO if (line.startsWith("data:")) { Message msg = gson.fromJson(line.substring(6), Message.class); + SdkCodes.infoStreamEventReceived(line.substring(6)); updater.update(msg); } } @@ -273,7 +275,7 @@ public void onResponse(@NotNull Call call, @NotNull Response response) throws IO throw new SSEStreamException("End of SSE stream"); } catch (Throwable ex) { log.warn("SSE Stream aborted: " + ex.getMessage()); - updater.onDisconnected(); + updater.onDisconnected(ex.getMessage()); if (ex instanceof SSEStreamException) { throw ex; } diff --git a/src/main/java/io/harness/cf/client/connector/HarnessConnector.java b/src/main/java/io/harness/cf/client/connector/HarnessConnector.java index dbbcc000..aa350656 100644 --- a/src/main/java/io/harness/cf/client/connector/HarnessConnector.java +++ b/src/main/java/io/harness/cf/client/connector/HarnessConnector.java @@ -6,6 +6,7 @@ import io.harness.cf.api.ClientApi; import io.harness.cf.api.MetricsApi; import io.harness.cf.client.api.MissingSdkKeyException; +import io.harness.cf.client.common.SdkCodes; import io.harness.cf.client.dto.Claim; import io.harness.cf.client.logger.LogUtil; import io.harness.cf.model.*; @@ -52,6 +53,7 @@ public HarnessConnector(@NonNull String apiKey) { public HarnessConnector(@NonNull final String apiKey, @NonNull final HarnessConfig options) { if (isNullOrEmpty(apiKey)) { + SdkCodes.errorMissingSdkKey(); throw new MissingSdkKeyException(); } diff --git a/src/main/java/io/harness/cf/client/connector/LocalConnector.java b/src/main/java/io/harness/cf/client/connector/LocalConnector.java index 3346d720..354072cd 100644 --- a/src/main/java/io/harness/cf/client/connector/LocalConnector.java +++ b/src/main/java/io/harness/cf/client/connector/LocalConnector.java @@ -210,7 +210,7 @@ public void stop() throws InterruptedException { log.info("FileWatcherService stopping"); flagWatcher.stop(); segmentWatcher.stop(); - updater.onDisconnected(); + updater.onDisconnected("LocalConnector stopped"); log.info("FileWatcherService stopped"); } diff --git a/src/main/java/io/harness/cf/client/connector/Updater.java b/src/main/java/io/harness/cf/client/connector/Updater.java index cbdf99f6..70890da4 100644 --- a/src/main/java/io/harness/cf/client/connector/Updater.java +++ b/src/main/java/io/harness/cf/client/connector/Updater.java @@ -5,13 +5,11 @@ public interface Updater { void onConnected(); - void onDisconnected(); + void onDisconnected(String reason); void onReady(); void onFailure(final String message); - void onError(); - void update(final Message message); } diff --git a/src/test/java/io/harness/cf/client/connector/CountingUpdater.java b/src/test/java/io/harness/cf/client/connector/CountingUpdater.java index 3d6b66ce..1c59a385 100644 --- a/src/test/java/io/harness/cf/client/connector/CountingUpdater.java +++ b/src/test/java/io/harness/cf/client/connector/CountingUpdater.java @@ -13,7 +13,6 @@ class CountingUpdater implements Updater { @Getter @Setter private PollingAtomicLong readyCount = new PollingAtomicLong(0); @Getter @Setter private PollingAtomicLong failureCount = new PollingAtomicLong(0); @Getter @Setter private PollingAtomicLong updateCount = new PollingAtomicLong(0); - @Getter @Setter private PollingAtomicLong errorCount = new PollingAtomicLong(0); @Override public void onConnected() { @@ -22,8 +21,8 @@ public void onConnected() { } @Override - public void onDisconnected() { - log.debug("onDisconnected"); + public void onDisconnected(String reason) { + log.debug("onDisconnected" + reason); disconnectCount.incrementAndGet(); } @@ -39,12 +38,6 @@ public void onFailure(String message) { failureCount.incrementAndGet(); } - @Override - public void onError() { - log.info("onError"); - errorCount.incrementAndGet(); - } - @Override public void update(Message message) { log.debug("update: " + message); diff --git a/src/test/java/io/harness/cf/client/connector/EventSourceTest.java b/src/test/java/io/harness/cf/client/connector/EventSourceTest.java index b0fcd8cd..9cf33132 100644 --- a/src/test/java/io/harness/cf/client/connector/EventSourceTest.java +++ b/src/test/java/io/harness/cf/client/connector/EventSourceTest.java @@ -89,7 +89,6 @@ void shouldNotCallErrorHandlerIfRetryEventuallyReconnectsToStreamEndpoint() assertTrue(updater.getConnectCount().get() >= 1); assertEquals(0, updater.getFailureCount().get()); - assertEquals(0, updater.getErrorCount().get()); } @Test From 49c76e9a709899801d9847243ad1a4c41657d95e Mon Sep 17 00:00:00 2001 From: Andrew Bell <115623869+andybharness@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:35:32 +0100 Subject: [PATCH 2/2] adding additional coverage + some minor fixes --- .../io/harness/cf/client/common/SdkCodes.java | 14 +++---- .../cf/client/common/SdkCodesTest.java | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 src/test/java/io/harness/cf/client/common/SdkCodesTest.java diff --git a/src/main/java/io/harness/cf/client/common/SdkCodes.java b/src/main/java/io/harness/cf/client/common/SdkCodes.java index ef5d38a4..5a8468a2 100644 --- a/src/main/java/io/harness/cf/client/common/SdkCodes.java +++ b/src/main/java/io/harness/cf/client/common/SdkCodes.java @@ -38,7 +38,7 @@ public static void infoStreamConnected() { } public static void infoStreamEventReceived(String eventJson) { - log.info(sdkErrMsg(5002, of(eventJson))); + log.info(sdkErrMsg(5002, ofNullable(eventJson))); } public static void infoMetricsThreadStarted(int intervalSec) { @@ -46,11 +46,11 @@ public static void infoMetricsThreadStarted(int intervalSec) { } public static void infoMetricsThreadExited() { - log.info(sdkErrMsg(7000)); + log.info(sdkErrMsg(7001)); } public static void warnAuthFailedSrvDefaults(String reason) { - log.warn(sdkErrMsg(2001, Optional.of(reason))); + log.warn(sdkErrMsg(2001, Optional.ofNullable(reason))); } public static void warnAuthRetying(int attempt) { @@ -58,11 +58,11 @@ public static void warnAuthRetying(int attempt) { } public static void warnStreamDisconnected(String reason) { - log.warn(sdkErrMsg(5001, Optional.of(reason))); + log.warn(sdkErrMsg(5001, Optional.ofNullable(reason))); } public static void warnPostMetricsFailed(String reason) { - log.warn(sdkErrMsg(7002, Optional.of(reason))); + log.warn(sdkErrMsg(7002, Optional.ofNullable(reason))); } public static void warnDefaultVariationServed(String identifier, Target target, String def) { @@ -94,13 +94,13 @@ public static void warnDefaultVariationServed(String identifier, Target target, // SDK_STREAM_5xxx {"5000", "SSE stream connected ok"}, {"5001", "SSE stream disconnected, reason:"}, - {"5002", "SSE event received: "}, + {"5002", "SSE event received:"}, {"5003", "SSE retrying to connect in"}, // SDK_EVAL_6xxx {"6000", "Evaluated variation successfully"}, {"6001", "Default variation was served"}, // SDK_METRICS_7xxx - {"7000", "Metrics thread started, intervalMs: "}, + {"7000", "Metrics thread started, intervalMs:"}, {"7001", "Metrics thread exited"}, {"7002", "Posting metrics failed, reason:"} }) diff --git a/src/test/java/io/harness/cf/client/common/SdkCodesTest.java b/src/test/java/io/harness/cf/client/common/SdkCodesTest.java new file mode 100644 index 00000000..f72a5aaa --- /dev/null +++ b/src/test/java/io/harness/cf/client/common/SdkCodesTest.java @@ -0,0 +1,40 @@ +package io.harness.cf.client.common; + +import static io.harness.cf.client.common.SdkCodes.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import io.harness.cf.client.dto.Target; +import org.junit.jupiter.api.Test; + +class SdkCodesTest { + + @Test + void testAllLogs() { + assertDoesNotThrow( + () -> { + errorMissingSdkKey(); + infoPollStarted(123); + infoSdkInitOk(); + infoSdkAuthOk(); + infoPollingStopped(); + infoStreamConnected(); + infoStreamEventReceived(null); + infoStreamEventReceived("dummy data"); + infoMetricsThreadStarted(321); + infoMetricsThreadExited(); + warnAuthFailedSrvDefaults(null); + warnAuthFailedSrvDefaults("error 1"); + warnAuthRetying(1); + warnAuthRetying(-1); + warnStreamDisconnected("error 2"); + warnStreamDisconnected(null); + warnPostMetricsFailed(null); + warnPostMetricsFailed("error 3"); + warnDefaultVariationServed("id1", null, null); + warnDefaultVariationServed("id1", null, "defaultVal"); + + Target target = Target.builder().identifier("test").isPrivate(false).build(); + warnDefaultVariationServed("id2", target, "defaultVal2"); + }); + } +}