Skip to content

Commit

Permalink
Expose the name of a ShadowFlow
Browse files Browse the repository at this point in the history
  • Loading branch information
martinvisser committed Nov 22, 2023
1 parent 126e41a commit 2044050
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
44 changes: 28 additions & 16 deletions src/main/java/io/github/rabobank/shadow_tool/ShadowFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
* @param <T> The model that the current and new flow should be mapped to for comparison.
*/
public class ShadowFlow<T> {
private static final Logger logger = LoggerFactory.getLogger(ShadowFlow.class);

private static final Javers JAVERS = JaversBuilder.javers().withListCompareAlgorithm(LEVENSHTEIN_DISTANCE).build();
private static final int ZERO = 0;
private static final int HUNDRED = 100;
private static final Logger logger = LoggerFactory.getLogger(ShadowFlow.class);
private static final String INSTANCE_PREFIX_FORMAT = "[instance=%s]";
private static final String DEFAULT_INSTANCE_NAME = "default";
private static final String CALLING_NEW_FLOW = "{} Calling new flow: {}";
Expand All @@ -44,15 +45,16 @@ public class ShadowFlow<T> {
private final EncryptionService encryptionService;
private final Scheduler scheduler;
private final String instanceNameLogPrefix;
private final String instanceName;

ShadowFlow(final int percentage,
final ExecutorService executorService,
final EncryptionService encryptionService,
final String instanceName) {
this.percentage = percentage;
this.encryptionService = encryptionService;
final var nonNullInstanceName = instanceName == null ? DEFAULT_INSTANCE_NAME : instanceName;
instanceNameLogPrefix = String.format(INSTANCE_PREFIX_FORMAT, nonNullInstanceName);
this.instanceName = instanceName == null ? DEFAULT_INSTANCE_NAME : instanceName;
instanceNameLogPrefix = String.format(INSTANCE_PREFIX_FORMAT, this.instanceName);

if (executorService != null) {
this.executorService = executorService;
Expand All @@ -63,9 +65,13 @@ public class ShadowFlow<T> {
}
}

private final Javers javers = JaversBuilder.javers()
.withListCompareAlgorithm(LEVENSHTEIN_DISTANCE)
.build();

/**
* @return Name of the Shadow Flow instance or "default" if not configured
*/
public String getInstanceName() {
return instanceName;
}

/**
* This will always call currentFlow, and based on the percentage also call the
Expand All @@ -85,7 +91,7 @@ public class ShadowFlow<T> {
*/
public T compare(final Supplier<T> currentFlow, final Supplier<T> newFlow) {
final var currentFlowResponse = currentFlow.get();
doShadowFlow(() -> javers.compare(currentFlowResponse, newFlow.get()));
doShadowFlow(() -> JAVERS.compare(currentFlowResponse, newFlow.get()));

return currentFlowResponse;
}
Expand All @@ -112,7 +118,7 @@ public T compare(final Supplier<T> currentFlow, final Supplier<T> newFlow) {
*/
public <C extends Collection<T>> C compareCollections(final Supplier<C> currentFlow, final Supplier<C> newFlow, final Class<T> clazz) {
final var currentFlowResponse = currentFlow.get();
doShadowFlow(() -> javers.compareCollections(currentFlowResponse, newFlow.get(), clazz));
doShadowFlow(() -> JAVERS.compareCollections(currentFlowResponse, newFlow.get(), clazz));

return currentFlowResponse;
}
Expand All @@ -136,7 +142,7 @@ public Mono<T> compare(final Mono<T> currentFlow, final Mono<T> newFlow) {
currentFlow.doOnNext(currentResponse -> {
logger.info(CALLING_NEW_FLOW, instanceNameLogPrefix, callNewFlow);
if (callNewFlow) {
newFlow.doOnNext(newResponse -> logDifferences(javers.compare(currentResponse, newResponse)))
newFlow.doOnNext(newResponse -> logDifferences(JAVERS.compare(currentResponse, newResponse)))
.doOnError(ex -> logger.warn(FAILED_TO_COMPARE, instanceNameLogPrefix, ex))
.contextWrite(contextView)
.subscribeOn(scheduler)
Expand Down Expand Up @@ -168,7 +174,7 @@ public <C extends Collection<T>> Mono<C> compareCollections(final Mono<? extends
currentFlow.doOnNext(currentResponse -> {
logger.info(CALLING_NEW_FLOW, instanceNameLogPrefix, callNewFlow);
if (callNewFlow) {
newFlow.doOnNext(newResponse -> logDifferences(javers.compareCollections(currentResponse, newResponse, clazz)))
newFlow.doOnNext(newResponse -> logDifferences(JAVERS.compareCollections(currentResponse, newResponse, clazz)))
.doOnError(ex -> logger.warn(FAILED_TO_COMPARE, instanceNameLogPrefix, ex))
.contextWrite(contextView)
.subscribeOn(scheduler)
Expand Down Expand Up @@ -233,6 +239,7 @@ private boolean shouldCallNewFlow() {
public static class ShadowFlowBuilder<T> {

private final Logger logger = LoggerFactory.getLogger(ShadowFlowBuilder.class);
private static final IllegalStateException ENCRYPTION_SERVICE_ALREADY_CONFIGURED = new IllegalStateException("An encryption service has already been configured");

private final int percentage;

Expand Down Expand Up @@ -277,11 +284,12 @@ public ShadowFlowBuilder<T> withExecutorService(final ExecutorService executorSe
* @return This builder.
*/
public ShadowFlowBuilder<T> withEncryption(final PublicKey publicKey) {
requireNull();
try {
final var cipher = Cipher.getInstance(DEFAULT_ALGORITHM_MODE_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
withCipher(cipher);
} catch (Exception e) {
} catch (final Exception e) {
logger.error("Invalid encryption setup. Encryption and logging of values is disabled", e);
}
return this;
Expand All @@ -297,11 +305,8 @@ public ShadowFlowBuilder<T> withEncryption(final PublicKey publicKey) {
* @return This builder.
*/
public ShadowFlowBuilder<T> withCipher(final Cipher cipher) {
try {
encryptionService = new DefaultEncryptionService(cipher);
} catch (Exception e) {
logger.error("Invalid encryption setup. Encryption and logging of values is disabled", e);
}
requireNull();
encryptionService = new DefaultEncryptionService(cipher);
return this;
}

Expand All @@ -314,10 +319,17 @@ public ShadowFlowBuilder<T> withCipher(final Cipher cipher) {
* @return This builder.
*/
public ShadowFlowBuilder<T> withEncryptionService(final EncryptionService encryptionService) {
requireNull();
this.encryptionService = encryptionService;
return this;
}

private void requireNull() {
if (encryptionService != null) {
throw ENCRYPTION_SERVICE_ALREADY_CONFIGURED;
}
}

/**
* If the shadow tool is used for two separate use-cases in one application, this allows you to distinguish them.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

class ShadowFlowTest {

private static final Logger logger = ((Logger) LoggerFactory.getLogger(ShadowFlow.class));
private static final Logger logger = (Logger) LoggerFactory.getLogger(ShadowFlow.class);
private static ListAppender<ILoggingEvent> listAppender;

private static final DummyObject dummyObjectA = new DummyObject("Bob", "Utrecht", List.of("Mirabel", "Bruno"));
Expand Down

0 comments on commit 2044050

Please sign in to comment.