feat: add logging on provider state transitions (#1444)

* NOISSUE add logging on provider state transitions

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix npe

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix failing test

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* fix failing test

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

* format

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>

---------

Signed-off-by: christian.lutnik <christian.lutnik@dynatrace.com>
Co-authored-by: Simon Schrottner <simon.schrottner@dynatrace.com>
This commit is contained in:
chrfwow 2025-05-14 11:11:36 +02:00 committed by GitHub
parent bc10bacb5a
commit e2813b2e5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 14 deletions

View File

@ -2,14 +2,14 @@ package dev.openfeature.sdk;
import dev.openfeature.sdk.exceptions.OpenFeatureError;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.Getter;
import java.util.concurrent.atomic.AtomicReference;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class FeatureProviderStateManager implements EventProviderListener {
private final FeatureProvider delegate;
private final AtomicBoolean isInitialized = new AtomicBoolean();
@Getter
private ProviderState state = ProviderState.NOT_READY;
private final AtomicReference<ProviderState> state = new AtomicReference<>(ProviderState.NOT_READY);
public FeatureProviderStateManager(FeatureProvider delegate) {
this.delegate = delegate;
@ -24,17 +24,17 @@ class FeatureProviderStateManager implements EventProviderListener {
}
try {
delegate.initialize(evaluationContext);
state = ProviderState.READY;
setState(ProviderState.READY);
} catch (OpenFeatureError openFeatureError) {
if (ErrorCode.PROVIDER_FATAL.equals(openFeatureError.getErrorCode())) {
state = ProviderState.FATAL;
setState(ProviderState.FATAL);
} else {
state = ProviderState.ERROR;
setState(ProviderState.ERROR);
}
isInitialized.set(false);
throw openFeatureError;
} catch (Exception e) {
state = ProviderState.ERROR;
setState(ProviderState.ERROR);
isInitialized.set(false);
throw e;
}
@ -42,7 +42,7 @@ class FeatureProviderStateManager implements EventProviderListener {
public void shutdown() {
delegate.shutdown();
state = ProviderState.NOT_READY;
setState(ProviderState.NOT_READY);
isInitialized.set(false);
}
@ -50,17 +50,34 @@ class FeatureProviderStateManager implements EventProviderListener {
public void onEmit(ProviderEvent event, ProviderEventDetails details) {
if (ProviderEvent.PROVIDER_ERROR.equals(event)) {
if (details != null && details.getErrorCode() == ErrorCode.PROVIDER_FATAL) {
state = ProviderState.FATAL;
setState(ProviderState.FATAL);
} else {
state = ProviderState.ERROR;
setState(ProviderState.ERROR);
}
} else if (ProviderEvent.PROVIDER_STALE.equals(event)) {
state = ProviderState.STALE;
setState(ProviderState.STALE);
} else if (ProviderEvent.PROVIDER_READY.equals(event)) {
state = ProviderState.READY;
setState(ProviderState.READY);
}
}
private void setState(ProviderState state) {
ProviderState oldState = this.state.getAndSet(state);
if (oldState != state) {
String providerName;
if (delegate.getMetadata() == null || delegate.getMetadata().getName() == null) {
providerName = "unknown";
} else {
providerName = delegate.getMetadata().getName();
}
log.info("Provider {} transitioned from state {} to state {}", providerName, oldState, state);
}
}
public ProviderState getState() {
return state.get();
}
FeatureProvider getProvider() {
return delegate;
}

View File

@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import dev.openfeature.sdk.providers.memory.InMemoryProvider;
@ -112,7 +113,7 @@ class OpenFeatureAPITest {
api.getClient().track("track-event", new ImmutableContext(), new MutableTrackingEventDetails(22.2f));
verify(featureProvider).initialize(any());
verify(featureProvider).getMetadata();
verify(featureProvider, times(2)).getMetadata();
verify(featureProvider).track(any(), any(), any());
}
}