Skip to content

Commit

Permalink
prepare 3.2.0 release (#185)
Browse files Browse the repository at this point in the history
* Moved primaryEnvironmentName to LDConfig, simplifying by removing primaryKey separation everywhere but the builder. Add getRequestBuilderFor a specific environment. Add static method to LDClient to get all environment names so that environments can be iterated over. Add accessor to retrieve LDClient specific UserManager. Iterate over all environments in PollingUpdater. Add environment argument to UserManager constructor, removing singleton and creating replacing init with newInstance static method.

* Add back in constructor without environment to UserManager

* Specialize HttpFeatureFlagFetcher to the environment, looks like UserManager may not be able to do the same so removed the environment from the constructor.

* Added SharedPreferences migration strategy

* All tests pass, fixed migration strategy to conform to spec, fixed primaryInstance null when offline in init, fixed primaryEnvironmentName being added to secondaryMobileKeys

* Update StreamUpdateProcessor construct to take an environment for the authorization header key.

* Fix issue with LDConfig mobileKeys hashmap creation.

* Combine futures so LDClient init future waits on all online instances of LDClient.

* Propagate IOException on closing instances to caller.

* Merge futures for identify call.

* Some changes from code review.

* Removed static from instanceId and now old SharedPreferences will only cleared once all environments have a copy in LDClient

* Fixed instanceId

* Updates from PR review.

* Added version and flagVersion, if available

* refactor(LDClient, LDConfig): changes for PR

* refactor(LDClient): changed isInternetConnected behavior for PR

* refactor(LDClient): removed async getForMobileKeys and wait seconds version, replaced with method that returns requested instance

* Bugfix/timber cleanup (#92)

Relates to #60

Cleaned up timber logging messages to use string formatting rather than concatenation. Log messages should remain the same as before.
Also replaced Log with Timber in the example app.

* Fix crash when example app is backgrounded twice.

* Add security provider update mechanism using Google Play Services to
attempt a provider update when TLSv1.2 is not available.

* Shared Preferences Fix for Multi Environment (#94)

* fix(SharedPreferences): added more SharedPreferences first time migration and differentiated SharedPreferences by mobile key

* fix(UserLocalSharePreference.java): added missing mobileKey additions to getSharedPreferences, cleaned up debugging code

* Fix edge cases in how multi-environment handles connection changes.

* fix(UserManagerTest.java): incorrect number of arguments to UserManager instantiation in unit test

* Remove line of testing code accidentally left in and refactor shared
preferences migration to make future migrations easier.

* Final fixes to store migration. Should be fairly future proof.

* Fix issue with primitive variation calls always returning null if fallback is null.

* Remove CircleCI V1 config file. (#97)

* Remove getting/comparing versions as floats (#99)

To prevent floating point errors in flag version comparisons.

* Include values in unknown summary events and compare values for (#100)

equality when creating new summary counters.

* simplify flag property deserialization

* rm debugging

* misc cleanup

* rm debugging

* add eval reason data model classes

* misc fixes

* serialize reason

* add ability to receive evaluation reasons from LD

* Changed shared preferences store system to user a single FlagStore
system that holds all the information on a flag to prevent issues
arising from unsynchronized separate stores for flag meta-data and
values.

* add methods to get value with explanation; refactor existing variation methods

* Abstract FlagStoreManager from FlagStore, new FlagStoreFactory class so manager can construct FlagStores of unknown type. Reformatted interfaces. Removed unused imports.

* Handle null case in allFlags, actually commit changes to UserManager.

* Hopefully fix edge cases in summary event reporting to pass testing.

* Hopefully fix edge cases in summary event reporting to pass testing.

* Simplify getFeaturesJsonObject as no longer using -1 as placeholder for null for variations.

* Make Flag non-mutable. Move GsonCache to gson package, move custom serializer/deserializers to classes in gson package and create one for PUT responses. Removed BaseUserSharedPreferences.

* Send summary event even if stored flag doesn't exist.

* Move sendSummaryEvent update code to UserSummaryEventSharedPreferences to synchronize to prevent data race on sending, updating, and clearing event store. Move SummaryEventSharedPreferences and UserSummaryEventSharedPreferences out of response package.

* Update SharedPrefsFlagStore to hold StoreUpdatedListener in weak reference. Fix various warnings.

* Migration code for upcoming flagstore.

* Remove couple of debug messages.

* Handle todos.

* Revert to old String behavior for allFlags, initialize WeakReference in SharedPrefsFlagStore.

* Better implementation of EvaluationReason serialization type adapter.

* Revert "Better implementation of EvaluationReason serialization type
adapter." Wrong branch...

This reverts commit 69c1c9b.

* Gw/ch29266/flagstore (#105)

* Changed shared preferences store system to user a single FlagStore
system that holds all the information on a flag to prevent issues
arising from unsynchronized separate stores for flag meta-data and
values.

* Abstract FlagStoreManager from FlagStore, new FlagStoreFactory class so manager can construct FlagStores of unknown type. Reformatted interfaces. Removed unused imports.

* Handle null case in allFlags, actually commit changes to UserManager.

* Hopefully fix edge cases in summary event reporting to pass testing.

* Hopefully fix edge cases in summary event reporting to pass testing.

* Simplify getFeaturesJsonObject as no longer using -1 as placeholder for null for variations.

* Make Flag non-mutable. Move GsonCache to gson package, move custom serializer/deserializers to classes in gson package and create one for PUT responses. Removed BaseUserSharedPreferences.

* Send summary event even if stored flag doesn't exist.

* Move sendSummaryEvent update code to UserSummaryEventSharedPreferences to synchronize to prevent data race on sending, updating, and clearing event store. Move SummaryEventSharedPreferences and UserSummaryEventSharedPreferences out of response package.

* Update SharedPrefsFlagStore to hold StoreUpdatedListener in weak reference. Fix various warnings.

* Migration code for upcoming flagstore.

* Remove couple of debug messages.

* Handle todos.

* Revert to old String behavior for allFlags, initialize WeakReference in SharedPrefsFlagStore.

* Better implementation of EvaluationReason serialization type adapter.

* Remove isUnknown argument from SummaryEventSharedPreferences methods. Use Runnable instead of Callable in UserManager to avoid useless return nulls. Rename FlagStoreFactoryInterface to FlagStoreFactory.

* Statically initialize Gson instance in GsonCache.

* Make Gson instance in GsonCache final on principle.

* Return json flags as JsonElement in allFlags map. (#106)

* Bump ok-http version to 3.9.1 (#107)

* fix annotations so eval reasons are serialized in events

* fix/expand doc comments for public methods

* typo

* typo

* add version string getter method

* Check for null key before file comparison check. (#110)

* [ch33658] Add unsafeReset() for LDClient testing re-initialization (#111)

Add `unsafeReset()` method to close and clear instances for re-initializing client between tests. Update LDClientTest to call `unsafeReset()` before tests.

* [ch33846] Rename tests to not start with capitals and general refactoring (#112)

* Rename tests to not start with capitals
* Reindent MultiEnvironmentLDClientTest to be consistent
* Optimize imports
* Move TLS patch into TLSUtils
* Make setModernTlsVersionsOnSocket private and remove redundant null check
* Remove code duplication in LDClient track overloaded methods.
* Remove validateParameter in LDClient that was using a NullPointerException as a null test.
* Simplify Debounce to use listener instead of callback.

* Add documentation for flagstore implementation (#113)

* [ch35150] Unit tests and bug fixes (#114)

- Use android test orchestrator to run tests isolated from each other. This prevents the issues testing singletons. Also enabled option to clear package data between runs allowing more extensive flagstore testing.
- Remove unsafe reset as it was added only for allowing testing the LDClient singleton.
- Tests for new FlagStore code.
- Convenience test FlagBuilder
- Fix Migration to not turn all flags into Strings
- Fix issue with clearAndApplyFlagUpdates not generating correct events for listeners.

* Add compatibility behavior to stringVariation and allFlags methods. (#115)

If a Json flag is requested with stringVariation it will serialize it to a String. Json flags will also be serialized to Strings for the map returned by allFlags()

* Update LDUser not to store all fields as Json. (#116)

Add testing rule to setup and teardown Timber trees for debug logging. Add additional LDUser tests. Fixed a bit of flakiness in deletesOlderThanLastFiveStoredUsers test that showed up all of a sudden.

* Add metricValue field to CustomEvent, add overloaded track method for (#118)

creating custom events with metricValues.

* [ch37794] Run connected emulator tests in CircleCI (#120)

* [ch34533] connection status, removing guava, network restructuring. (#117)

* Add ConnectionInformation class.
* Remove all internal uses of Guava.
* Update StreamUpdateProcessor to only debounce ping events.
* Add a connection state monitor to the example app.

* rename repo and package name and apply markdown templates (#121)

* Fix issue that stream could be started before stopping when calling identify. (#122)

* Revert "Fix issue that stream could be started before stopping when calling identify. (#122)"

This reverts commit fdede38.

* Revert "rename repo and package name and apply markdown templates (#121)"

This reverts commit 2215275.

* Revert "Revert "Fix issue that stream could be started before stopping when calling identify. (#122)""

This reverts commit 0849812.

* Revert "Revert "rename repo and package name and apply markdown templates (#121)""

This reverts commit bbbeb81.

* Fix thread leak on identify call from restarting EventProcessor without shutting it down first. (#123)

* Add top level try/catch to migration methods. Check flag version SharedPreferences object for String type before cast. (#124)

* Update Throttler to call runnable on background thread. (#125)

* Fix ConcurrentModificationException of instance map (#126)

Move iteration over client instances for ConnectivityReceiver and PollingUpdater to within LDClient to allow synchronizing on initialization.

* adding a circleci badge to the readme (#127)

* Fix bug where `stop` in StreamUpdateProcessor could not call it's listener when the stream is already closed.

This caused a race condition in repeated stream restarts that could put the SDK in a bad state.

* Change LDAwaitFuture to not treat zero timeout as unlimited timeout

Treating a timeout of zero as unlimited caused a change in behavior when initializing the SDK. This update restores the behavior init had when zero was passed as the timeout argument from pre-2.8.0. Also improves handling of spurious wakeups, and includes test cases for LDAwaitFuture.

* Revert "Merge remote-tracking branch 'remotes/origin/experiment' into next-release"

This reverts commit 3ac167f, reversing
changes made to d26e006.

* CircleCI fixes (#131)

* Better ci fix (#132)

* Speedup tests by building on macOS (#137)

* Background identify fixes (#133)

Add new testing controllers for network and foreground states. For network control, mobile data must be disabled on recent Android versions, updated circleci config to do this. Add new connectivity manager tests. Made EventProcessor and UserManager minimal interfaces for mocking, with actual implementations moved to DefaultEventProcessor and DefaultUserManager. Fixed issue with blocking in background modes.

* Experimentation 1.5 updates (#134)

* add entire compile-time classpath to javadoc classpath

* javadoc fixes: <p/> is not a thing

* do fail on javadoc errors

* add javadoc step, misc CI cleanup

* misc javadoc fixes

* remove unintentional(?) immediate event flush; clean up event tests

* remove unreliable test assumption about elapsed time

* [ch57098] Deprecate LDCountryCode (#141)

Deprecate LDCountryCode class and LDUser setters that take LDCountryCode as an argument.

* Catch `SecurityException` when setting alarm in case there are already (#143)

the maximum allowed number of alarms on Samsung devices.

* Revert "[ch57098] Deprecate LDCountryCode (#141)" so we can do a patch release
first.

This reverts commit c0e71ae.

* Revert "Revert "[ch57098] Deprecate LDCountryCode (#141)" so we can do a patch release"

This reverts commit 23b930f.

* Deprecate public classes (#145)

* Deprecate some unnecessarily public classes, duplicate classes as non-public to
avoid using the deprecated classes.

* [ch61092] Add event payload ID. (#147)

* Add event retry. (#149)

* Fix javadoc comment for release.

* Fix broken merge.

* [ch65133] Deprecate classes (#150)

* Deprecate UserSummaryEventSharedPreferences, SummaryEventSharedPreferences, FeatureFlagFetcher, Util, Debounce.

* Improve Javadoc and reduce interface clutter. (#152)

* Save Javadoc artifact and include logcat in circle output with tee. (#153)

* Save Javadoc artifact on circleci.

* Add step to kill emulator after tests, and tee output of logcat for visibility
during run.

* [ch62120] Background during identify callback (#154)

* Adding more connectivity manager tests.
* Updated internal `Foreground` class to call listeners on a background thread.
* Add some comments explaining the behavior of test controllers.
* Adding fixes for cases where the completion callback may not be called.

* [ch65914] Diagnostic events (#156)

* [ch65352] Expose LDValue rather than Gson types (#158)

* Remove SET_ALARM permission. The comment that this was required for background updating is incorrect, this permission is only for sending broadcasts to an alarm clock application, something we do not do, and should never do. (#159)

* Fix minimum diagnostic recording interval comment. (#160)

* Data since date was not getting reset after each periodic diagnostic event. (#161)

* [ch75315] Add maxCachedUsers configuration option (#162)

Adds maxCachedUsers configuration option for configuring the limit on how many
users have their flags cached locally.

* Configure okhttp cache for polling requests to be stored in a subdirectory of the application cache directory. (#164)

* Fixes ch76614 and add test of null fallback unknown flag event generation. Also some finishing touches to LDValue changes, including LDClientInterface updates, more tests, and improvements to null behavior handling. (#163)

* Removing ldvalue changes before release (#165)

* Revert "[ch65352] Expose LDValue rather than Gson types (#158)"

This reverts commit 1e29a82

* Fixes after revert.

* [ch69437] Support for setting additional headers to be included in requests. (#166)

* [ch89933] Improve resiliency of store for summary events. (#167)

See #105 for the original issue.

* [ch94053] Improve throttler behavior. (#169)

* Add doubleVariation, doubleVariationDetail. (#171)

Deprecates floatVariation, floatVariationDetail.

* Provide pollUri configuration and deprecate baseUri. (#172)

* Fix throttler behavior to ensure attempt count resets are not cancelled (#178)

* [ch98336] Broaden catch statement on scheduling polling alarm (#181)

This is to handle more than just the SecurityException that Samsung throws, as we've gotten an issue report that some devices throw a IllegalStateException instead.

* Removed the guides link

* Include flag key in warning message when converting a json flag to a string (#185)

* (2.x) Prevent NullPointerException when diagnostic processor shut down before starting. (#210)

* Release 2.14.2 (#130)

## [2.14.2] - 2021-06-02
### Fixed
- Added check to prevent `NullPointerException` in `DiagnosticEventProcessor.stopScheduler` when `LDClient.close` is called before the application is foregrounded when the SDK was initialized in the background. ([#127](#127))
- Log message warning that JSON flag was requested as a String has been updated to include the key of the flag requested to assist in discovering which flag is being requested with an unexpected type. ([#116](#116))

* Bump version and update changelog for release.

* Explicitly specify android:exported attribute on manifest receivers. (#211)

* Update java common (#212)

* Flag PendingIntent on new enough platforms as the flag is required on Android S+ (#213)

* Add try for getting network capabilities (#214)

* ch103537 bump java-sdk-common to 1.2 to support inExperiment on eval reason (#215)

* Remove `allowBackup` manifest attribute that can conflict with the application's (#217)

* Update the version to 2.8.9

* Add explicit proguard directives for keeping BroadcastReceivers. (#219)

* Using the version that still support Java 8 but pin the grgit core behind the scene

* Remove Android Appcompat dependency (#222)

* Bump dependencies and reorganize Gradle file somewhat. (#223)

* Add the null check to prevent multiple allocation of the DiagnosticEventProcessor

* Fix sonatype release plugin (#226)

* Add .ldrelease configuration (#227)

* Add contract test service (#228)

* Fix test service failing on later API versions (#229)

* Add usesCleartextTraffic=true to contract-tests AndroidManifest

This allows the contract tests to work on API level 28 and above

* Fix start-emulator.sh to pick the newest image instead of the oldest

* Refactor CI config into separate jobs with a matrix (#230)

* Don't auto-retry emulator tests (#231)

* Add contract tests for API level 21 (#232)

* Remove unnecessary locking in LDClient (#233)

* Remove `synchronized` keywords from every `LDClient` method

* Treat `instances` as immutable, and swap out the whole map after constructing all the clients

* Use a lock to ensure we don't try to init twice

* Update `ConnectivityManager` so it now manages `DiagnosticEventManager`

* Run contract tests on Android 31, 33 (#234)

* Unsuppress streaming/requests and polling/requests (#236)

* don't create a new executor just to trigger a flush

* remove short publishing timeout, use defaults of 60 retries & 10 seconds

* Serialize null values of `anonymous` as null (#237)

* fix URL path concatenation to avoid double slashes

* fix NPE in edge case where variation is null but value isn't

* use SecureRandom instead of Random, just to make scanners happier

* rm unused

* fix deletion versioning logic, implement tombstones (#244)

* disable contract tests for API 31/33

* use okhttp-eventsource 1.11.3

* ensure timed-out clients get closed in contract tests

* clean up instances map on close (#247)

* clean up instances map on close

* improve atomicity of access to instances, ensure they can't be modified via closed clients

* update more methods that iterate over instances

* rm unnecessary LDClientControl

* use com.launchdarkly.logging with Timber adapter (#235)

Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: torchhound <[email protected]>
Co-authored-by: torchhound <[email protected]>
Co-authored-by: Arun Bhalla <[email protected]>
Co-authored-by: jamesthacker <[email protected]>
Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: torchhound <[email protected]>
Co-authored-by: Eli Bishop <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Elliot <[email protected]>
Co-authored-by: Robert J. Neal <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Alex Engelberg <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
  • Loading branch information
17 people authored Aug 23, 2022
1 parent b33cd44 commit 51de904
Show file tree
Hide file tree
Showing 35 changed files with 812 additions and 244 deletions.
1 change: 0 additions & 1 deletion contract-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ android {
}

dependencies {
implementation("com.jakewharton.timber:timber:5.0.1")
// https://mvnrepository.com/artifact/org.nanohttpd/nanohttpd
implementation("org.nanohttpd:nanohttpd:2.3.1")
implementation("com.google.code.gson:gson:2.8.9")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import android.os.Bundle;
import android.widget.TextView;

import java.io.IOException;
import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdk.android.LDAndroidLogging;

import timber.log.Timber;
import java.io.IOException;

public class MainActivity extends Activity {

private Config config;
private TestService server;
private Timber.DebugTree debugTree;
private LDLogger logger = LDLogger.withAdapter(LDAndroidLogging.adapter(), "MainActivity");

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -22,11 +22,6 @@ protected void onCreate(Bundle savedInstanceState) {

TextView textIpaddr = findViewById(R.id.ipaddr);
textIpaddr.setText("Contract test service running on port " + config.port);

if (Timber.treeCount() == 0) {
debugTree = new Timber.DebugTree();
Timber.plant(debugTree);
}
}

@Override
Expand All @@ -40,13 +35,13 @@ public void onStop() {
@Override
protected void onResume() {
super.onResume();
Timber.w("Restarting test service on port " + config.port);
logger.warn("Restarting test service on port {}", config.port);
server = new TestService(getApplication());
if (!server.isAlive()) {
try {
server.start();
} catch (IOException e) {
Timber.e(e, "Error starting server");
logger.error("Error starting server: {}", e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.launchdarkly.sdktest;

import com.launchdarkly.logging.LDLogAdapter;
import com.launchdarkly.logging.LDLogLevel;

/**
* This wraps the underlying logging adapter to use the logger name as a prefix for the message
* text, rather than passing it through as a tag, because Android logging tags have a length
* limit so we can't put the whole test name there.
*/
public class PrefixedLogAdapter implements LDLogAdapter {
private final LDLogAdapter wrappedAdapter;
private final String singleLoggerName;

public PrefixedLogAdapter(LDLogAdapter wrappedAdapter, String singleLoggerName) {
this.wrappedAdapter = wrappedAdapter;
this.singleLoggerName = singleLoggerName;
}

@Override
public Channel newChannel(String name) {
return new ChannelImpl(wrappedAdapter.newChannel(singleLoggerName),
"[" + name + "] ");
}

private static final class ChannelImpl implements Channel {
private final Channel wrappedChannel;
private final String prefix;

public ChannelImpl(Channel wrappedChannel, String prefix) {
this.wrappedChannel = wrappedChannel;
this.prefix = prefix;
}

@Override
public boolean isEnabled(LDLogLevel level) {
return wrappedChannel.isEnabled(level);
}

@Override
public void log(LDLogLevel level, Object message) {
wrappedChannel.log(level, prefix + message.toString());
}

@Override
public void log(LDLogLevel level, String format, Object param) {
wrappedChannel.log(level, prefix + format, param);
}

@Override
public void log(LDLogLevel level, String format, Object param1, Object param2) {
wrappedChannel.log(level, prefix + format, param1, param2);
}

@Override
public void log(LDLogLevel level, String format, Object... params) {
wrappedChannel.log(level, prefix + format, params);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.launchdarkly.sdktest;

import com.launchdarkly.logging.LDLogAdapter;
import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdk.EvaluationDetail;
import com.launchdarkly.sdk.LDValue;
import com.launchdarkly.sdk.UserAttribute;
Expand Down Expand Up @@ -30,8 +32,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import timber.log.Timber;

/**
* This class implements all the client-level testing protocols defined in
* the contract tests service specification, such as executing commands,
Expand All @@ -41,13 +41,13 @@
*/
public class SdkClientEntity {
private final LDClient client;
private final LDLogger logger;

public SdkClientEntity(Application application, CreateInstanceParams params) {
Timber.i("Creating client for %s", params.tag);
LDConfig config = buildSdkConfig(params.configuration);
// Each new client will plant a new Timber tree, so we uproot any existing ones
// to avoid spamming stdout with duplicate log lines
Timber.uprootAll();
public SdkClientEntity(Application application, CreateInstanceParams params, LDLogAdapter logAdapter) {
LDLogAdapter logAdapterForTest = new PrefixedLogAdapter(logAdapter, "test");
this.logger = LDLogger.withAdapter(logAdapterForTest, params.tag);
logger.info("Creating client");
LDConfig config = buildSdkConfig(params.configuration, logAdapterForTest, params.tag);
long startWaitMs = params.configuration.startWaitTimeMs != null ?
params.configuration.startWaitTimeMs.longValue() : 5000;
Future<LDClient> initFuture = LDClient.init(
Expand All @@ -59,9 +59,9 @@ public SdkClientEntity(Application application, CreateInstanceParams params) {
try {
initFuture.get(startWaitMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException e) {
Timber.e(e, "Exception during Client initialization");
logger.error("Exception during Client initialization: {}", e);
} catch (TimeoutException e) {
Timber.w("Client did not successfully initialize within %s ms. It could be taking longer than expected to start up", startWaitMs);
logger.warn("Client did not successfully initialize within {} ms. It could be taking longer than expected to start up", startWaitMs);
}
try {
this.client = LDClient.get();
Expand All @@ -73,13 +73,13 @@ public SdkClientEntity(Application application, CreateInstanceParams params) {
throw new RuntimeException("client initialization failed or timed out");
}
} catch (LaunchDarklyException e) {
Timber.e(e, "Exception when initializing LDClient");
logger.error("Exception when initializing LDClient: {}", e);
throw new RuntimeException("Exception when initializing LDClient", e);
}
}

public Object doCommand(CommandParams params) throws TestService.BadRequestException {
Timber.i("Test harness sent command: %s", TestService.gson.toJson(params));
logger.info("Test harness sent command: {}", TestService.gson.toJson(params));
switch (params.command) {
case "evaluate":
return doEvaluateFlag(params.evaluate);
Expand Down Expand Up @@ -192,9 +192,10 @@ private void doAliasEvent(AliasEventParams params) {
client.alias(params.user, params.previousUser);
}

private LDConfig buildSdkConfig(SdkConfigParams params) {
private LDConfig buildSdkConfig(SdkConfigParams params, LDLogAdapter logAdapter, String tag) {
LDConfig.Builder builder = new LDConfig.Builder();
builder.mobileKey(params.credential);
builder.logAdapter(logAdapter).loggerName(tag + ".sdk");

if (params.streaming != null) {
builder.stream(true);
Expand Down Expand Up @@ -257,9 +258,9 @@ private LDConfig buildSdkConfig(SdkConfigParams params) {
public void close() {
try {
client.close();
Timber.i("Closed LDClient");
logger.info("Closed LDClient");
} catch (IOException e) {
Timber.e(e, "Unexpected error closing client");
logger.error("Unexpected error closing client: {}", e);
throw new RuntimeException("Unexpected error closing client", e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.launchdarkly.logging.LDLogAdapter;
import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdktest.Representations.CommandParams;
import com.launchdarkly.sdktest.Representations.CreateInstanceParams;
import com.launchdarkly.sdktest.Representations.Status;
import com.launchdarkly.sdk.android.BuildConfig;
import com.launchdarkly.sdk.android.LDAndroidLogging;
import com.launchdarkly.sdk.json.LDGson;

import java.io.IOException;
Expand All @@ -20,8 +23,6 @@

import fi.iki.elonen.NanoHTTPD;

import timber.log.Timber;

public class TestService extends NanoHTTPD {
private static final int PORT = 8001;
private static final String[] CAPABILITIES = new String[]{
Expand All @@ -37,6 +38,8 @@ public class TestService extends NanoHTTPD {

private final Router router = new Router();
private final Application application;
private final LDLogAdapter logAdapter;
private final LDLogger logger;

private final Map<String, SdkClientEntity> clients = new ConcurrentHashMap<String, SdkClientEntity>();
private final AtomicInteger clientCounter = new AtomicInteger(0);
Expand All @@ -50,6 +53,8 @@ public BadRequestException(String message) {
TestService(Application application) {
super(PORT);
this.application = application;
this.logAdapter = LDAndroidLogging.adapter();
this.logger = LDLogger.withAdapter(logAdapter, "service");
router.add("GET", "/", (params, body) -> getStatus());
router.add("POST", "/", (params, body) -> postCreateClient(body));
router.addRegex("POST", Pattern.compile("/clients/(.*)"), (params, body) -> postClientCommand(params, body));
Expand All @@ -72,13 +77,13 @@ public Response serve(IHTTPSession session) {
body = new String(buffer);
}

Timber.i("Handling request: %s %s", method.name(), session.getUri());
logger.info("Handling request: {} {}", method.name(), session.getUri());
try {
return router.route(method.name(), session.getUri(), body);
} catch (JsonSyntaxException jse) {
return newFixedLengthResponse(Response.Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, "Invalid JSON Format\n");
} catch (Exception e) {
Timber.e(e, "Exception when handling request: %s %s", method.name(), session.getUri());
logger.error("Exception when handling request: {} {} - {}", method.name(), session.getUri(), e);
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, e.toString());
}
}
Expand All @@ -97,7 +102,7 @@ private Response postCreateClient(String jsonPayload) {
CreateInstanceParams params = gson.fromJson(jsonPayload, CreateInstanceParams.class);

String clientId = String.valueOf(clientCounter.incrementAndGet());
SdkClientEntity client = new SdkClientEntity(application, params);
SdkClientEntity client = new SdkClientEntity(application, params, logAdapter);

clients.put(clientId, client);

Expand Down
12 changes: 12 additions & 0 deletions launchdarkly-android-client-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ ext.versions = [
"jacksonDatabind": "2.10.5.1",
"junit": "4.13",
"launchdarklyJavaSdkCommon": "1.2.0",
"launchdarklyLogging": "1.1.1",
"okhttp": "4.9.2",
"timber": "5.0.1",
]

dependencies {
api("com.launchdarkly:launchdarkly-java-sdk-common:${versions.launchdarklyJavaSdkCommon}")
api("com.launchdarkly:launchdarkly-logging:${versions.launchdarklyLogging}")

commonDoc("com.launchdarkly:launchdarkly-java-sdk-common:${versions.launchdarklyJavaSdkCommon}:sources")
// These are included only for Javadoc generation.
Expand Down Expand Up @@ -137,6 +139,16 @@ if (JavaVersion.current().isJava8Compatible()) {
}
}

tasks.withType(Javadoc) {
// The following should allow hyperlinks to com.launchdarkly.logging classes to go to
// the correct external URLs
if (options instanceof StandardJavadocDocletOptions) {
(options as StandardJavadocDocletOptions).links(
"https://javadoc.io/doc/com.launchdarkly/launchdarkly-logging/${versions.launchdarklyLogging}"
)
}
}

artifacts {
archives sourcesJar, javadocJar
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdk.android.ConnectionInformation.ConnectionMode;
import com.launchdarkly.sdk.LDUser;

Expand Down Expand Up @@ -131,7 +132,8 @@ private void createTestManager(boolean setOffline, boolean streaming, boolean ba
.streamUri(streamUri != null ? Uri.parse(streamUri) : Uri.parse(mockStreamServer.url("/").toString()))
.build();

connectivityManager = new ConnectivityManager(app, config, eventProcessor, userManager, "default", null, null);
connectivityManager = new ConnectivityManager(app, config, eventProcessor, userManager, "default",
null, null, LDLogger.none());
}

private void awaitStartUp() throws ExecutionException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.google.gson.JsonObject;
import com.launchdarkly.logging.LDLogger;
import com.launchdarkly.sdk.LDUser;

import org.easymock.Capture;
Expand Down Expand Up @@ -47,7 +48,8 @@ public class DefaultUserManagerTest extends EasyMockSupport {

@Before
public void before() {
userManager = new DefaultUserManager(ApplicationProvider.getApplicationContext(), fetcher, "test", "test", 3);
userManager = new DefaultUserManager(ApplicationProvider.getApplicationContext(), fetcher,
"test", "test", 3, LDLogger.none());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import static junit.framework.Assert.assertEquals;

import com.launchdarkly.logging.LDLogger;

@RunWith(AndroidJUnit4.class)
public class DiagnosticEventProcessorTest {

Expand Down Expand Up @@ -47,7 +49,8 @@ public void defaultDiagnosticRequest() throws InterruptedException {
.eventsUri(Uri.parse(mockEventsServer.url("").toString()))
.build();
DiagnosticStore diagnosticStore = new DiagnosticStore(ApplicationProvider.getApplicationContext(), "test-mobile-key");
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore, ApplicationProvider.getApplicationContext(), okHttpClient);
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore,
ApplicationProvider.getApplicationContext(), okHttpClient, LDLogger.none());

DiagnosticEvent testEvent = new DiagnosticEvent("test-kind", System.currentTimeMillis(), diagnosticStore.getDiagnosticId());

Expand All @@ -74,7 +77,8 @@ public void defaultDiagnosticRequestIncludingWrapper() throws InterruptedExcepti
.wrapperVersion("1.0.0")
.build();
DiagnosticStore diagnosticStore = new DiagnosticStore(ApplicationProvider.getApplicationContext(), "test-mobile-key");
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore, ApplicationProvider.getApplicationContext(), okHttpClient);
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore,
ApplicationProvider.getApplicationContext(), okHttpClient, LDLogger.none());

DiagnosticEvent testEvent = new DiagnosticEvent("test-kind", System.currentTimeMillis(), diagnosticStore.getDiagnosticId());

Expand Down Expand Up @@ -102,7 +106,8 @@ public void defaultDiagnosticRequestIncludingAdditionalHeaders() throws Interrup
})
.build();
DiagnosticStore diagnosticStore = new DiagnosticStore(ApplicationProvider.getApplicationContext(), "test-mobile-key");
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore, ApplicationProvider.getApplicationContext(), okHttpClient);
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore,
ApplicationProvider.getApplicationContext(), okHttpClient, LDLogger.none());

DiagnosticEvent testEvent = new DiagnosticEvent("test-kind", System.currentTimeMillis(), diagnosticStore.getDiagnosticId());

Expand All @@ -123,7 +128,8 @@ public void closeWithoutStart() {

LDConfig ldConfig = new LDConfig.Builder().mobileKey("test-mobile-key").build();
DiagnosticStore diagnosticStore = new DiagnosticStore(ApplicationProvider.getApplicationContext(), "test-mobile-key");
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore, ApplicationProvider.getApplicationContext(), okHttpClient);
DiagnosticEventProcessor diagnosticEventProcessor = new DiagnosticEventProcessor(ldConfig, "default", diagnosticStore,
ApplicationProvider.getApplicationContext(), okHttpClient, LDLogger.none());
diagnosticEventProcessor.close();
}
}
Loading

0 comments on commit 51de904

Please sign in to comment.