Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.launchdarkly.sdk.server.DataModel.FEATURES;
Expand All @@ -66,6 +67,8 @@ public final class LDClient implements LDClientInterface {
private final ScheduledExecutorService sharedExecutor;
private final LDLogger baseLogger;
private final LDLogger evaluationLogger;
// isFlagKnown logs its cached-data warning once per client. This flag records that log.
private final AtomicBoolean isFlagKnownCachedDataWarned = new AtomicBoolean(false);

private static final int EXCESSIVE_INIT_WAIT_MILLIS = 60000;

Expand Down Expand Up @@ -429,7 +432,10 @@ public boolean isFlagKnown(String featureKey) {

if (!isInitialized()) {
if (store.isInitialized()) {
baseLogger.warn("isFlagKnown called before client initialized for feature flag \"{}\"; using last known values from data store", featureKey);
if (isFlagKnownCachedDataWarned.compareAndSet(false, true)) {
baseLogger.warn("isFlagKnown called before client initialized for feature flag \"{}\"; "
+ "using last known values from data store. This message is logged once.", featureKey);
}
} else {
baseLogger.warn("isFlagKnown called before client initialized for feature flag \"{}\"; data store unavailable, returning false", featureKey);
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.launchdarkly.sdk.server;

import com.launchdarkly.logging.LDLogLevel;
import com.launchdarkly.sdk.LDContext;
import com.launchdarkly.sdk.LDValue;
import com.launchdarkly.sdk.server.integrations.MockPersistentDataStore;
Expand Down Expand Up @@ -427,6 +428,30 @@ public void isFlagKnownReturnsFalseIfStoreAndClientAreNotInitialized() throws Ex
mocks.verifyAll();
}

@Test
public void isFlagKnownLogsCachedDataWarningOnlyOnce() throws Exception {
DataStore testDataStore = initedDataStore();
LDConfig.Builder config = new LDConfig.Builder()
.startWait(Duration.ZERO)
.dataStore(specificComponent(testDataStore));
expect(dataSource.start()).andReturn(initFuture);
expect(dataSource.isInitialized()).andReturn(false).times(2);
mocks.replayAll();

client = createMockClient(config);

upsertFlag(testDataStore, flagWithValue("key", LDValue.of(1)));
assertTrue(client.isFlagKnown("key"));
assertTrue(client.isFlagKnown("key"));

long warningCount = logCapture.getMessages().stream()
.filter(m -> m.getLevel() == LDLogLevel.WARN
&& m.getText().contains("using last known values from data store"))
.count();
assertEquals(1, warningCount);
mocks.verifyAll();
}

@Test
public void isFlagKnownUsesStoreIfStoreIsInitializedButClientIsNot() throws Exception {
DataStore testDataStore = initedDataStore();
Expand Down
Loading